基於微服務成熟度模型的高可用優化實踐
前言
隨著微服務的流行,每個網際網路公司後臺都有無數大大小小的服務,服務與服務之間又有著千絲萬縷的呼叫關係。要保證整個微服務系統的成熟穩定,就必須保證每個微服務的成熟度。但如何來定義服務的成熟度?應該從哪些緯度來考量?各個緯度裡又有哪些普遍的問題?如何來優化?
本文介紹了愛奇藝技術產品團隊用來衡量服務成熟度的模型,並基於此模型對多個後臺服務進行評估,總結出了一些常見的低分項,並對低分項整理了相關優化方案。希望對大家有所幫助。
01
服務成熟度模型
為了能夠對服務的成熟度進行量化,我們需要從多個維度對服務進行評估。
每個服務隨著需求不斷迭代,每個迭代週期都需要經歷如下三個階段:開發測試,運維上線,線上執行。每一個階段,都需要一系列的措施來保證服務最終的成熟可靠。我們針對每一個階段,梳理出來需要關注的指標,來衡量該階段的整體質量。
我們對上面3個階段進行綜合評分,並根據評分對服務成熟度進行了等級劃分。(1-5分為準入級,6-7分為服務級,8-10分為成熟級。)
通過這樣的服務成熟度模型,我們就可以以量化的指標直觀的評價一個服務的成熟度,並發現服務有哪些可改進項。
02
低分項梳理
基於服務成熟度模型,我們對多個後臺服務進行了評估,發現了一些指標項在各個服務中普遍得分較低。這些指標項包括:
開發測試方面:程式碼規範,單元測試,壓力測試,介面撥測;
運維上線方面:灰度上線,上線回滾;
線上可用性方面:系統保護,資料備份,報警處理,應急預案。
於是我們優先對這些低分項的優化方案進行了梳理,期望通過對低分項的優化,提升服務的成熟度,使我們的服務提升至成熟級別。
03
低分項優化方案
我們的服務主要基於Java語言開發,主要是虛機部署的部署方式,並少量採用容器部署。所以下面的優化方案主要圍繞我們的服務現狀展開。
3.1
開發測試
線上bug往往都是開發新需求引入的,如果在開發測試階段儘可能的發現問題,提高程式碼質量,能夠將問題的影響範圍控制在最小。下面是開發測試階段一些常見的措施和手段:
3.1.1 程式碼規範
程式碼風格:採用統一的程式碼風格,一方面可以使得程式碼的可讀性提升,另一方面會減少程式碼合併時的衝突,並與開發工具整合,支援自動提示不規範程式碼,有的不規範程式碼甚至可以一鍵修正。配合GitLab CI和Sonar檢查,可以對每次的提交進行程式碼規範的檢查,並以報告的形式直觀的展現。
3.1.2 單元測試
單元測試位於測試金字塔的最底層。執行效率快,一般完成的測試case跑下來不會超過10分鐘,可以整合在CI流程中,快速反饋問題。維護成本低,單元測試在開發階段就能發現問題,修復成本低。測試金字塔越向上反饋的時間越長,實現的成本也越高。因此推薦大家提升單元測試的覆蓋率。
Java最常用的測試框架是Junit。另外配合Mock測試庫Mockito和測試覆蓋率工具Jacoco形成完整的單元測試工具集。在IDEA和SonarQube中都可以配置Jacoco的外掛來直觀的展示單元測試的覆蓋率。
在推進單元測試的過程中,我們經常遇見的問題是:專案補充單元測試費時費力,新增程式碼的測試覆蓋率如何把關?
我們的解決思路是:
已有程式碼優先對重要程式碼(如公共庫,工具類)補充單元測試。
新增程式碼增加程式碼覆蓋率的指標(如:設定新增程式碼測試覆蓋率不得低於90%)
隨著新增程式碼和對老程式碼修改,專案整體的測試覆蓋率會逐步提升。
新增程式碼測試覆蓋率統計:使用diff-cover工具可以通過分析分支程式碼差異和Jacoco測試報告,計算出當前分支修改程式碼的測試覆蓋率。
3.1.3 單元測試
(1)為什麼要做壓力測試?通過壓力測試,我們能夠:
· 發現效能瓶頸
· 預估資源使用情況
· 為限流配置提供參考
· 發現新需求引入的問題
(2)壓力測試工具應具備什麼功能?
常見的壓力測試工具有JMeter等。我們使用愛奇藝雲平臺提供的LoadMaker雲壓測系統,它具備如下特點:
· 多個施壓叢集,壓力可以達到很高
· 建立和儲存壓測場景,重複執行
· 提供壓測報告:QPS,響應時間,錯誤率等資料
同時,為了壓測不影響線上使用者的真實流量,我們構建了單獨的壓測資源池。在需要壓測時,選擇資源池中的機器和帶壓測模組,可自動構建壓測環境。
(3)什麼情況下需要壓測?
· 例行壓測:版本灰度期間對重點專案進行例行壓測。
· 新專案/介面上線前壓測:新專案上線前壓測,指導容量預估和限流配置。
3.1.4 介面撥測
對於後臺介面服務,我們比較關心線上介面返回的資料是否正確以及新程式碼上線是否影響了已有邏輯?介面撥測可以很好的覆蓋上面兩個問題。一方面可以用於線上介面返回資料的校驗,實時發現介面異常。另一方面可以用於自動化介面測試,配合上線流程,發現新增程式碼是否有引入的問題,及時終止上線操作。一個介面撥測系統應具備如下特性:
(1)支援對介面返回結果做校驗。
(2)複雜校驗支援編寫指令碼。
(3)可設定多個撥測點,模擬正式使用者請求場景。
(4)支援報警。
(5)詳細的測試報告。
(6)和上線流程打通,支援灰度後的自動化介面測試。
3.2
運維上線
3.2.1 灰度上線機制
程式碼在測試環境測試通過並不能保證程式碼完全沒有問題,仍然有可能因為測試疏漏或環境差異等原因導致未發現的問題。如果沒有灰度上線的機制,這些潛在問題直接上線,可能對線上系統帶來災難性的後果。
灰度上線需要配合灰度檢查來確保本次上線的安全性。我們採用的檢查方式有:
(1)灰度上線後針對灰度機器進行自動化介面檢測。
(2)對比灰度機監控指標和線上機器的監控指標。
(3)灰度環境測試功能驗收。
3.2.2 上線回滾
如果發生因為上線新程式碼導致的線上問題,首先要做的應該是回滾操作,而不是去分析問題和修復程式碼上線。回滾操作需要儘量做到以下幾點:
(1)回滾速度快,如果需要revert程式碼,重新編譯打包,上傳至伺服器,整個流程會比較漫長,故障恢復的時間也會比較長。
(2)回滾完整,有些程式碼和配置檔案是有依賴的,如果只回滾了程式碼,可能導致啟動後的異常。
(3)可回滾性,這需要架構層面的思考,不要出現無法回滾的情況,如上線後資料寫入,對回滾後的程式碼不相容。
我們採用的是RPM打包的方式進行上線和回滾。通過RPM的形式把一次部署的所有內容(程式碼和配置)打包,部署時伺服器保留歷史版本的RPM包,當需要回滾時,直接執行Job安裝歷史版本的RPM包即可。如果服務採用的是容器部署,則回滾起來會更簡單,只需啟動歷史版本的映象即可。
3.3
線上可用性
3.3.1 系統保護
線上執行時可能面對各種各樣的問題,機器故障,網路問題,依賴的服務方掛掉,流量劇增等等。如何在如此險惡的環境下生存?不能相信別人,只能提升服務自身的可靠性。一般採取方式有:熔斷,限流,降級,重試等。
熔斷
當我們依賴的服務方有問題時,不能把我們的服務拖垮,常用的方式是熔斷。當依賴方成功率低於我們設定的閾值時,暫停對其呼叫,過一定間隔再去重試。
常用的熔斷元件有:Hystrix,Sentinel等。下表是Hystrix和Sentinel的對比。
鑑於Netflix對Hystrix不再維護,以及Sentinel更加豐富的功能,我們選擇了Sentinel作為我們的熔斷元件。
降級
當發生突發事故,服務整體超負載時,為了避免服務整體不可用,一般會啟用服務降級,以保證重要或基本服務正常執行,非重要服務延遲使用或暫停使用。
為此,我們實現了一個頁面降級服務。該服務會定時請求頁面介面,並對其進行校驗,校驗通過後將結果儲存起來;當服務出現異常或超負載時,開啟降級開關,頁面服務會直接讀取之前儲存的靜態頁面資料返回。犧牲個性化,從千人千面降級為千人一面。由於去除了頁面構造的流程,處理能力會大幅提升,保證服務的正常執行。
限流
限流非常重要,它是保護服務正常執行的重要關卡。尤其是在出現流量突增時,合理的限流可以保護你的服務不被打垮。如果沒有配置限流,不但流量突增時服務會被打垮,服務也難以恢復,因為服務重啟後會被再次打垮。
我們一般會在閘道器層和服務層分別配置限流。
閘道器層使用nginx的限流外掛可以配置單機的限流。
服務層使用Sentinel限流。Sentinel可以基於QPS,併發數,呼叫關係來限流,並且支援叢集整體限流。下圖是Sentinel叢集限流的實現。
重試
從客戶端到後端服務,中間各個環節都有可能出現異常,如DNS故障,運營商節點故障,後臺伺服器故障等等,導致請求失敗。
針對不同的情形,適當的重試可以增加請求成功率。愛奇藝APP端的重試分為如下幾種:
1. IP直連重試,通過配置直連IP數來控制重試次數。
2. 超級管道重試,公司自研基於HTTP的閘道器代理服務,可做到異地重試。
3. HTTP重試。
4.原url重試。
詳細資訊可以參考公眾號文章《愛奇藝移動端網路優化實踐分享:網路請求成功率優化篇》。
重試可以提高成功率,但是過度重試可能會導致後端服務壓力過大,出現雪崩效應。所以重試策略上應該注意如下幾點:
1. 重試策略可雲控,極端情況下可後臺配置關閉重試。
2. 區分錯誤碼重試,不是所有錯誤碼都需要重試,如後臺觸發限流返回的錯誤碼就不需要重試。
3.3.2 資料備份
在資料庫的使用上,我們需要考慮資料庫的高可用。在這方面,公司的服務雲團隊做了很多方面的優化,大家可以在公眾號文章裡查詢到,本文就不詳細展開了。作為業務方,我們需要注意的是資料庫的使用要嚴格按照兩地三中心的架構申請和使用。
3.3.3 監控報警
完善的監控報警可以讓我們在服務出現問題的第一時間感知到,及時處理,避免問題的擴散。從不同的緯度,我們需要不同的監控,主要包括:
指標監控
監控服務的關鍵指標,這裡包括3部分:機器指標(CPU,記憶體,網路流量等),服務指標(QPS,成功率,響應時間等),第三方介面指標(QPS,成功率,響應時間等)。
具體的實現方案是:通過Collectd和自研Meerkat元件進行指標上報,上報給Graphint進行彙總儲存,並通過Grafana進行展示。
應用日誌監控
基於應用日誌的監控可以讓我們發現更加細粒度的異常,如應用內丟擲的異常,內部業務邏輯錯誤等。
首先我們定義了一套日誌列印的格式規範,所有需要監控的日誌都按統一的格式進行日誌輸出。然後通過日誌收集元件Venus將機器上的日誌投遞到Kafka佇列,最終入到Druid時序資料庫內,進行多維度的分析儲存。前端報表使用Graphna進行展示。
全鏈路監控
如果要監控上下文的鏈路關係、跨系統的故障定位等相關問題,需要進行全鏈路監控。詳細資訊可以參考公眾號文章《愛奇藝全鏈路自動化監控平臺的探索與實踐》。
3.3.4 應急預案
儘管我們上面列舉了一系列的可用性優化措施,但在真實的線上環境裡,仍然會出現各種各樣的異常,故障,需要我們進行手動處理。當問題真正出現時,如果現場去想應該如何處理,可能由於慌亂而沒有做到最優的處理方案。因此,我們需要提前想好可能出現的問題,以及出現這些問題時應該如何處理,並形成書面的文件。在問題出現時,我們只需要對著文件一步一步處理即可。
04
# 服務質量檢查
有了優化方案,如何判斷服務有沒有按照優化方案實施?如何保證服務長期保持較高的可用性?我們不希望做完一輪優化,服務成熟度提升之後,長期沒有跟進的話,服務成熟度又慢慢的開始下降。
因此對這些常見的服務成熟度指標進行了自動化的檢查,並形成每日的健康度報告,把服務的成熟度監控起來。一旦有某項指標出現異常,我們能夠及時處理。這樣使我們的服務成熟度保持長期的穩定狀態。
總結與展望
在本文介紹了愛奇藝提出的服務成熟度模型的定義,以可量化的指標來評估服務的成熟度。然後以該模型為標準,對後臺服務進行了評估,並總結了各個後臺服務普遍得分較低的指標項。針對這些低分項,梳理了優化方案。並建立了自動化的服務質量檢測機制,以保證服務成熟度的長期穩定。
通過可用性優化,多個重要服務的成熟度模型評分都已經提升到了8分以上,並通過自動化的服務質量檢測機制,長期監測成熟度的各個指標,一旦發現某些指標異常,及時進行修復改進。
未來,會在下面兩點進行持續的改進和增強:
1. 成熟度模型評分的自動化。避免人工評分的主觀因素,同時提升效率。
2. 自動化的服務質量檢測機制增加更多的指標。
希望通過基於服務成熟度模型的優化,使我們的服務可用性得到持續的提升。
也許你還想看
掃一掃下方二維碼,更多精彩內容陪伴你!