設計全球級的分布式、任務關鍵型應用 - 從實際項目中得來的教訓(下)
此篇為設計下一代智能DNS和流量管理平臺的NSONE公司的創建者和CEO Kris Beevers的客座文章的第二部分。點此閱讀第一部分
集成和功能測試非常關鍵
每一個軟件開發的課程都會反復強調單元測試的重要性。無論你是正在進行測試驅動的開發還是只想炫耀一下代碼,沒有進行單元測試的情況下,你仍然無法肯定代碼的功能。而且,隨著代碼的修改,單元測試要不斷進行,從而保證代碼的功能正確性。
在一個分布式應用中,即使你擁有全世界最好的功能測試覆蓋,系統仍然有可能出問題。單元測試永遠不夠!
你需要測試不同子系統之間的交互情況。例如,如果配置數據的一個特殊部分變化,會有什么影響呢?它會不會影響到子系統A與子系統B之間的通信呢?又如,如果你改變了一種消息格式,產生和處理這些消息的子系統還可以繼續與其他子系統進行通信嗎?代碼修改后,需要依靠4個不同后端子系統給出的結果的一類特殊請求還會得到正確反饋嗎?
單元測試回答不了這些問題,但是集成測試可以。在集成測試環境中投入時間和精力,并且在研發和部署過程中要適時進行集成測試。理想情況下,最好一直在產品系統中運行集成測試。
沒有中斷維護這種東西
如果你正在設計一個真正的任務關鍵型應用(客戶需要依賴該應用來打理生意),那么該應用可能不需要開關。它永遠不需要停止工作。那么,你永遠都不會有終端維護的權利和可能。即使是世界上最復雜的后端架構也會有需要改變的時候。
這就是你需要認真思考架構的其中一個原因。幾個小時的認真思考可能可以避免后期幾個月的漏洞彌補時間。
Kris就遇到過一個真實的情況。NSONE的團隊從一開始在架構設計階段就投入了大量精力,使得項目沿著正確的方向前進。但是,該團隊仍然有沒有考慮到的問題——平臺接收高頻率的數據反饋。這些反饋會影響到如何對復雜流量管理配置下DNS記錄的請求進行回答。數據反饋可以應用到多個DNS記錄中,也就是說一個服務器負載信息的反饋可以通知牽涉到服務器上多個網站的流量路由決策。當時,NSONE團隊假設只有一個單獨的數據反饋連接到若干個DNS記錄。那么,就可以通過把到達系統的數據反饋根據每個所連接的DNS記錄發送到相應的邊沿位置來節約大量時間和精力。然而,團隊的假設是不成立的。一些客戶把數據反饋連接到了數千個DNS記錄。前期的偷懶導致內部發生DoS,而且隨著系統的擴展,問題會越來越嚴重。
其問題在于:團隊不能通過發送比較少的控制消息來解決以上問題。Kris等需要修改數據模型、消息模型和一些一直在運行的系統。前期只需要2-3個小時就可以避免的問題卻引起了6周的“馬拉松”——頭腦風暴式的會話、相當復雜的反應、大量正確性測試以及一系列的小心翼翼的部署和遷移等。所有這些都只是為了在不中斷系統的情況修復以上的問題。
在極端情況下,新框架或者代碼的每一次部署都會是無縫的——仔細的規劃、滾動重啟和集成測試等。一旦系統在服務用戶,就永遠不能關機。
非常小心的進行自動部署和配置管理
現在的開發生態系統擁有大量的自動部署和配置管理的工具,包括Chef、Puppet、Ansible、SaltStack、Terraform等數不勝數。選擇使用哪個工具就像決定哪個模型更好一樣根本無關緊要。真正有關系的是你要使用這些工具。即使是在公司的初創階段,即使事情看起來非常容易搞定,你也千萬不要手動管理配置或者部署——你會犯錯、你會限制自身能力的提升以及使得以后的自動化變得十分艱難。
但是,要小心:權力越大,責任越大。自動部署工具使得你可以把平臺迅速搞砸。
利用Chef管理所有主機的IP表?一個疲憊工程師的一個無意的按鍵動作就可以使你的平臺全部癱瘓。把一個經過反復測試的特性部署到開發用的環境中?一個真實環境和模擬環境中略有差別的流量就可以使得端到端自動部署的產品崩潰。要善用自動化工具!
Kris等就利用Ansible管理NSONE的配置和部署。這是一個非常好的工具。 NSONE團隊本可以把一切自動化,實現一鍵部署新的DNS傳輸代碼到所有的邊緣位置。但是,他們沒有這么做。他們選擇從最低流量到最高流量,一個設備一個設備的部署。在一個設備內部,他們甚至挨個核或者挨個服務器,運行復雜的單步功能測試。在移動到更加關鍵的設備前,該團隊還會花費數十個小時或者幾天時間來研究度量,確認沒有潛在的問題。而且在部署之前,他們還會進行應用程序代碼以及Ansible配置等的仔細審查。
對于你的團隊和應用而言,要適時的使用自動化。但是也別忘記,自動化加速項目發展的同時,也可以加速項目的死亡!
做好“消防演習”
壞的事情總會發生。每一個科技公司都會遇到服務器崩潰的情況。NSONE團隊在項目之初就想到了各種服務器崩潰的情況——磁盤失效、網卡失效、RAM失效、內核崩潰、虛擬環境中的鄰域效應等等。各種情況都可能非常容易的引起服務器失效。
此外,電源供應也可能出問題。還記得颶風桑迪嗎?NSONE的員工不得不不斷加注柴油,才能保證系統在發電機的幫助下保持工作。
而且,光纜也可能會斷。BGP有可能被黑。你也可能遭遇64k的ICMP報文、DNS和NTP放射放大攻擊以及等等。你該怎么辦呢?
唯一能做的就是提前進行演練。在壞的事情發生之間進行演練。Netflix的Chaos Monkey就是一個很著名的例子。你不可能直接模擬可能遇到的每一種狀況,但是你可以盡力去模擬你的反應。唯一能夠保證你在遇到狀況時可以保持鎮定的方法就是,使用你已經提前放置好的工具,然后快速反應。
最小化表面積
隨著你的應用程序變得越來越分布,暴露給惡意攻擊的表面積也會在不經意間迅速增加。看好你的系統,并最小化系統暴露給互聯網的表面積。
架構中的每一個角色都應該只向那些允許訪問的系統集暴露其服務接口。面向互聯網的系統只提供面向用戶的那些服務。在后端,系統之間應該盡可能的通過私有IP空間進行通信。否則,也應該通過加密的通道進行數據傳輸。無論是使用像AWS的安全組這樣的提供商的工具,還是使用路由器ACL或已經防火墻進行ip表規則的自動管理,你應該盡可能的是防火墻。首先拒絕,然后在逐個按情況放行。
永遠都不要允許通過SSH等對產品系統進行直接訪問。人們應該通過采用多元素認證、端口試探、IP白名單等重重保護的主機來進入系統。確保主機分布于各種網絡、多個地域。進入產品架構的權限應該也限制為只有堡壘似的主機才可以。
有很多種策略可以幫助你看好系統。你只要去尋找,然后從一開始就考慮到系統的安全,使得安全成為系統的一部分即可。千萬不要隨著系統的擴展而淡化安全因素。
了解供應商環境
幾乎每一個現代技術公司都選擇把第一代產品放置在AWS、DigitalOcean或者其他低價低門檻的云服務提供商中。互聯網一直在快速發展。由此,云服務提供商也在近些年迅速增多。
絕大部分公司都沒有必要在擴張時著急放棄AWS。但是,每一個公司都應該盡可能的保留可選性。
你或許會發現應用程序中的一些負載在裸機中運行效率最高,也可能發現你需要一個在澳大利亞的CDN,或者在沒有AWS存在的市場中獲得很多關鍵性的用戶。那么,花一些時間來讓自己熟悉框架生態系統的各個方面——IaaS供應商、場地出租、DNS、CDN以及監控等等。在早期設計架構時,就考慮到以后可能需要遷移的地方。時刻準備著迅速遷移。
NSONE公司就操作著一個全球任意播的DNS傳輸網絡。當建立原型的時候,AWS起了很大的幫助。但是在平臺部署之前,他們就不得不遷移到別的地方來滿足網絡需求。設計一個非常具有競爭力的任意播DNS網絡很大程度上依靠公司與框架供應商、網絡供應商等進行協商,獲得盡可能多的控制權。在很多情況下,Kris等人不得不幫助供應商來找到合適的合作方式。
千萬別忘了:基礎設施運營商也都是怪胎,他們也經常歡迎各種新的想法和挑戰。時刻了解生態系統,做好準備工作。
總結
Kris已經分享了自己在設計和擴展分布式、任務關鍵系統時的經驗和教訓。或許,你不能在項目初創之時就把一些都規劃好。但是,你可以努力把自己放在一個更好的位置,來迎接公司擴張所帶來的挑戰。
此外,正在設計互聯網產品的公司也應該認真思考如何以分布式的方法來設計產品架構和擴展之路,從而為用戶提供最大的性能、最好的可靠性和安全性。
來自:http://www.infoq.com/cn/articles/design-global-level-distributed-mission-critical-apps-part02