當單塊架構被劃分成微服務之後,隨著微服務數量的增多,毫無疑問,將會面臨比單塊架構更複雜的問題。
部署微服務將會面臨以下問題。
1.運維負擔
對傳統的單塊架構系統來說,產品通常只有一個發布包,升級、部署系統往往只需要部署這個發布包即可。現在,面臨著這麼多的微服務,顯然運維的負擔要比之前更重了。對於運維工程師來說,部署的服務呈指數上升,傳統的手工部署方式往往已經不能適應日益增長的服務運維需求。
⒉服務間的依賴
在一個微服務結構中,你更容易遇到的錯誤是來自依賴的問題。在微服務架構系統中,某些業務功能需要幾個微服務協同才能完成,這些服務之間難免存在一定的依賴關係。特別是以某種方式更新某個服務的API時,同時也會影響其他服務,造成某些服務的不可用。例如,在天氣預報系統中,天氣預報微服務是依賴於天氣數據API微服務及城市數據API微服務的,只要這兩個數據API微服務其中一個不可用,則會導致整個天氣預報微服務不可用。所以在更新服務時,需要先確定哪些服務需要更新,而後評估更新對其他服務的影響是什麼。
3.更多的監控
每個微服務往往需要設置單獨的監控,這意味著更多的監控。而且每個微服務可能使用不同的技術或語言,依靠不同的機器或容器,使用其特有的版本控制,這也大大增加了監控的複雜性。
4.更頻繁的發布
每個微服務都需要單獨部署,這就意味著需要更多的服務發布。微服務的顆粒度相對較小,修改和發布也較為容易,所以發布也會相對更加頻繁。這是微服務的優點,但同時也是實施微服務所要解決的難題。
5.更複雜的測試
微服務化之後,服務可以獨立開發和測試,團隊或成員之間可以並行快跑,這極大提高了系統的研發效率,但也給測試工作帶來了挑戰。除了驗證各個獨立微服務之外,我們還需要考慮通過具有分布式特性的微服務架構檢查全部關鍵性事務的執行路徑。由於微服務的目標之一在於實現快速變更,因此我們必須更加關注服務的依賴性,以及性能、可訪問性、可靠性和彈性等非功能性要求。
針對上面的部署和發布的問題,一般採取如下的解決思路。
1.自動化運維
微服務顯著增加了開發團隊的運維和工具負擔。每個服務都需要一個部署管道、一個監控系統、自動報警、輪流電話值班等。在這種情況下,採用自動化運維手段,可以有效提升運維的效率。
微服務需要大量的基礎設施用於開發和部署,因此要使用一個自動化運維平臺。Kubernetes ,Swarm、Mesos、Docker及其他類似產品可以提供很大的幫助。
2.處理服務間的依賴關係
服務越多,服務間的依賴關係就越複雜。其中解決其複雜關係的一個基本原則是:永遠只有不同層級的單向依賴,即上層依賴下層,高層服務可以依賴低層服務,同層服務間不互相依賴。這樣就能讓系統有一個清晰的依賴關係,而且這樣的話,單向依賴就永遠不可能形成環狀。如果出現了同層服務間依賴,就說明服務分層出現了問題,此時需要抽象出一個更高層次的服務或者提升其中一個服務的層次。
3.日誌收集
由於微服務的數量眾多,每個服務都有自己的日誌,那麼通過這些散落的日誌來查看服務的狀態將會變成一個難題。針對微服務的日誌,我們傾向於將所有的微服務的日誌進行收集,儘量統一到一個平臺中,這樣就能在同一個平臺中監控所有微服務的狀態。
日誌收集方式也儘量做到統一。由於很多設計裡對於業務日誌、容器日誌、宿主機日誌等採用不同的agent,這是一個不好的設計方式,因為agent也是需要管理的,引入太多agent只會給自己增加不必要的管理成本。
在日誌收集方面的方案有Splunk、Logstash、Flume、Fluentd等。本書後續章節也會對微服務的日誌管理展開詳細的討論。
4.監控和告警
從功能上來說,服務的監控可以分為兩種類型,一種是對主機的監控,另一種是對服務的監控。
對於服務的監控,是指在不知道服務具體運行的情況下去檢查這個服務本身是否可用,以及在它出了故障以後如何進行故障的恢復。這種監控方式在容器和非容器上差異性比較小,但是與具體使用的技術棧或平臺會有比較大的關聯性。例如,如果使用JConsole工具來監控程序的性能,顯然這裡的程序只能是Java程序。對於主機的監控,是指我們需要去了解這個伺服器內部的運行狀態,如CPU使用率是否爆滿,磁碟佔用一段時間是否出現異常。對於主機監控主要作用有兩點,一種是出現嚴重故障的時候,我們要對發生故障的現場進行回溯,另一種是我們通過監控數據能夠去預測—些可能發生的問題。
當監控到異常時,監控軟體最好能自動做出一些處置機制。例如,在集成伺服器中,當檢測到提交的代碼有問題時,集成伺服器會自動將部署的版本回溯到上一個可用的版本,以保證現場部署的服務始終可用。
當監控軟體檢測到系統超過閾值時,應該要發送告警信息給運維人員。常見的告警方式有簡訊、郵件、閃光燈、音響喇叭等。
5.微服務的發布
由於同一個微服務可能會被發布到多個主機上進行水平擴展,這就要求不同的主機之間部署的是相同的軟體。同時,微服務能夠獨立於其他微服務發布或者取消發布,在部署時,微服務之間的功能不會產生相互影響。
一種比較好的方式是把微服務打包成鏡像,這樣就保證了不同主機之間能夠使用相同的鏡像。
同時,由於鏡像中包含了服務的配置文件和環境,這樣,就可以儘可能地避免主機環境對軟體部署產生的影響。
考慮使用Docker容器,這將會使構建、發布、啟動微服務變得十分快捷。
通過Kubernetes能夠進一步擴展Docker 的能力,能夠從單個Linux主機擴展到Linux集群,支持多主機,管理容器的位置,提供服務發現等功能,這些都是微服務需求的重要特性。因此,利用Kubernetes管理微服務和容器的發布,是一個非常有力的方案。
6.API版本控制
版本控制應當適用於任何API,對微服務也一樣。如果有某些改動打破了API的格式,那麼就應當針對該改動單獨發布另外一個版本。無論是公共接口還是其他內部服務使用的接口,在我們不清楚誰在使用這些接口的前提下,必須要保證向下兼容,或者至少要給用戶足夠的時間去適應。
一種比較好的實踐是,在部署新的接口時,保持老的接口暫時不變。新老接口並存的好處是,我們可以儘快地發布新的服務,其中包含了新的接口,同時,我們也給老的接口用戶遷移到新接口的時間。當所有的用戶都遷到了新接口後,就能將老的接口及相關代碼進行移除。這種部署方式,我們也稱為「藍―綠部署(Blue-Green Deployment) 」。
本篇內容篇理論知識,比較枯燥一些,也希望大家仔細閱讀。