1. 程式人生 > >大規模服務設計部署經驗談(5) | 釋出週期及測試

大規模服務設計部署經驗談(5) | 釋出週期及測試

5               釋出週期及測試

在生產環境中進行測試是一件很現實的事情,必須成為所有Internet 級服務所必須的質量保證方式之一。在儘可能(可以掏得起錢)的情況下,絕大多數服務都應當有至少一個與生產環境相似的測試實驗室,並且所有優秀的工程師團隊應當使用生產級的負載,以反映現實的方式測試伺服器。不過,我們的經驗是,這些測試實驗室即便模擬得再好,也絕不可能百分之百的逼真;它們至少總是會在一些細微的方式上和生產環境有所差別。由於這些實驗室在真實性上接近生產系統,因此相應的費用也呈漸進趨勢,在部署網際網路級大規模服務時,有關依賴管理和釋出週期及測試方面的經驗和最佳實踐在本文中得以體現。新的服務釋出版本可以順著標準單元測試、功能測試和生產測試實驗室測試一路走下來,一直進入受限的生產環境作為最後的測試階段。

快速逼近生產系統的開支。與此不同,我們推薦讓新的服務釋出版本順著標準單元測試、功能測試和生產測試實驗室測試一路走下來,一直進入受限的生產環境作為最後的測試階段。顯然,我們不想讓無法正常工作並給資料一致性帶來風險的軟體進入生產環境,因此這就不得不小心翼翼地實施。下面的原則一定要遵守:

1. 生產系統必須有足夠的冗餘,以保證在災難性的新服務故障發生時,能夠快速地恢復到原來的狀態;

2. 必須讓資料損壞或者狀態相關的故障極難發生(一定要首先通過功能測試);

3. 故障一定要能檢測得到,並且開發團隊(而不是運營團隊)必須監控受測程式碼的系統健康度;

4. 必須可以實現對所有變更的回滾操作,並且回滾必須在進入生產環境之前經過測試。這聽起來有點讓人心驚膽戰。不過我們發現,使用這個技術實際上能夠在新服務釋出時提升客戶體驗。與儘可能快地進行部署的做法不同,我們在一個數據中心中將一個系統放到生產環境數天。隨後在每個資料中心內把新系統引入生產環境。接著,我們會將整個資料中心帶入生產環境。最後,如果達到了質量和效能的目標,我們就進行全域性部署。這種方式可以在服務面臨風險之前發現問題,事實上還可以通過版本過渡提供更優秀的客戶體驗。一錘定音的部署是非常危險的。我們青睞的另一種可能違反直覺的方式是,在每天正午而不是半夜部署。在晚上部署,出現錯誤的風險更高,而且在半夜部署時如果有異常情況突然發生,那麼能處理這些問題的工程師肯定會少些。這樣做的目標是

為了使開發和運營團隊與整體系統的互動最小化,尤其在普通的工作日之外,使得費用得到削減的同時,質量得到提高。對於釋出週期和測試的最佳實踐包括:

5.1               經常性地交付。

經常性地交付。直覺上講,人們會認為更頻繁地交付難度要更大,而且會錯誤頻出。然而我們發現,頻繁的交付中突兀的變更數量很少,從而使得釋出的質量變得更高,並且客戶體驗更棒。對一次良好的釋出所進行的酸性測試,使用者提供可能會有所變化,但是關於可用性和延遲的運營

問題的數量應當在釋出週期中不受改變。我們會喜歡三個月一次的交付,但也可以有支援其他時長的論調。我們從心底認為,標準最終會比三個月更少,並且有許多服務已經是按周交付的了。比三個月更長的週期是很危險的。

5.2               使用生產資料來發現問題。

使用生產資料來發現問題。在大規模系統中的質量保證,是個資料探勘和視覺化的問題,而不是一個測試問題。每個人都必須專注於從生產環境的海量資料中獲得儘可能多的資訊。這方面的策略有:

l      可度量的釋出標準。定義出符合預期使用者體驗的具體標準,並且對其進行持續監控。如果可用性應當為99%,那麼衡量可用性是否達到目標。如果沒有達到,發出警報並且進行診斷。

l      實時對目標進行調優。不要停頓下來考慮到底目標應當是99%99.9%還是任何其他目標,設定一個可以接受的目標,然後隨著系統在生產環境中穩定性的建立,讓目標漸進式地增長。

l      一直收集實際資料。收集實際的度量,而不是那些紅紅綠綠的或者其他的報表。總結報表和影象很有用,不過還是需要原始資料用來診斷。

l      最小化“假陽性(falsepositive)”現象。在資料不正確時,人們很快就不再關注它們。不要過度警報,真是很重要的,否則運營人員會慢慢習慣於忽略這些警報。這非常重要,以至於把真正的問題隱藏成間接損害常常是可以接受的。

l      分析趨勢。這個可以用來預測問題。例如,當系統中資料移動的速度有異於往常的時候,常常能夠預測出更大的問題。這時就要研究可用的資料。

l      使系統健康程度保持高度透明。要求整個組織必須有一個全域性可用且實時顯示的系統健康報告。在內部安置一個網站,讓大家可以在任意時間檢視並瞭解當前服務的狀態。

l      持續監控。值得一提的是,人們必須每天檢視所有資料。每個人都應當這麼做,不過可以把這項工作明確給團隊的一部分人專職去做。

5.3               在設計開發上加大投入。

在設計開發上加大投入。良好的設計開發可以使運營需求降到最小,還能在問題變成實際運營矛盾之前解決它們。非常常見的一個現象就是組織不斷給運營部門增加投入,處理伸縮問題,卻從沒花時間設計一套伸縮的可靠架構。如果服務一開始沒有進行過巨集偉的構思,那麼以後就得手忙腳亂地追趕了。

5.4               支援版本回滾。

支援版本回滾。版本回滾是強制的,而且必須在釋出之前進行測試和驗證。如果沒有回滾,那麼任何形式的產品級測試都會存在非常高的風險。回覆到先前的版本應該是一個可以在任意部署過程中隨時開啟的降落傘扣。

5.5               保持前後版本的相容性

保持前後版本的相容性。這一點也是至關緊要的,而且也前面一點關係也非常密切。在元件之間更改檔案型別、介面、日誌/ 除錯、檢測(instrumentation)、監控和聯絡點,都是潛在的風險來源。除非今後沒有機會回滾到之前的老版本的可能,否則不要放棄對於老版本檔案的支援。

5.6               單伺服器部署。

單伺服器部署。這既是測試的需求也是開發的需求,整個服務必須很容易被託管到單一的系統中。在對於某些元件單伺服器無法實現的地方(比如說一個對於外部、非單箱的可部署服務),編寫模擬器來使單伺服器測試成為可能。沒有這個的話,單元測試會的難度會很大,而且不會完全覆蓋到實際條件。而且,如果執行完整的系統很困難的話,開發人員會傾向於接受從元件的角度看問題,而不是從系統的角度。

5.7               針對負載進行壓力測試。

針對負載進行壓力測試。使用兩倍(或者更多倍的)負載來執行生產系統的某些小部分,以確保系統在高於預期負載情況下的行為得到了解,同時也確保系統不會隨著負載的增加而瓦解。

5.8               在新發布版本之前進行功能和效能測試。

在新發布版本之前進行功能和效能測試。在服務的級別上這麼做,並針對每個元件這麼做,因為工作負載的特徵會一直改變。系統內部的問題和降級現象必須在早期捕獲。

5.9               表象性且迭代地進行構建和部署。

表象性且迭代地進行構建和部署。在開發週期中早早地把完整服務的骨架先搭建起來。這個完整服務可能幾乎做不了什麼,也可能在某些地方出現偏差,但是它可以允許測試人員和開發人員更有效率,而且也能讓整個團隊在一開始就從使用者的角度進行思考。在構建任何一個軟體系統時,這都是一個好方法。不對,對於服務來說這尤為重要。

5.10           使用真實資料測試。

使用真實資料測試。將使用者請求和工作量從生產到測試環境分門別類。選擇生產資料並把它放到測試環境中。產品形形色色的使用者,在發現bug 的時候總是顯得創意無窮。顯然,隱私承諾必須保持,使得這樣的資料永遠不會洩漏回到產品環境中,這是至關緊要的。

5.11           執行系統級的驗收測試。

執行系統級的驗收測試。在本地執行的測試提供可以加速迭代開發的健康測試。要避免大量維護費用,這些測試應當放在系統級別。

5.12           在完全環境中做測試和開發

在完全環境中做測試和開發。把硬體放在一邊,在專注的範圍內測試。作重要的是,使用和在這些環境中的生產條件下同樣的資料集合和挖掘技術,以保證投資的最大化。