架構之:微服務架構漫談
目錄
簡介
微服務和單體服務
微服務的特征
組件服務化
組織的劃分
服務之間的通信
去中心化治理
去中心化數據管理
自動化部署
對異常的響應
總結
簡介
微服務的架構出現已經很久很久了,微服務架構就是一種將單個應用程序轉換為一組小服務的方法,每個小服務都在自己的進程中運行,并使用輕量級的交互方式(如HTTP)進行通信。
服務的劃分是根據具體的業(yè)務來的,并且可以通過完全自動化的部署機制獨立部署。雖然大家都在談論微服務,但是什么時候應該使用微服務,使用微服務需要注意哪些問題對于很多人來說仍然是一個模糊的概念。本文將會和大家一起探討一下微服務相關的一些問題。
微服務和單體服務
在最開始的程序體系中,通常都是單體服務。對于單體服務來說,所有的服務都在一個進程中。企業(yè)應用程序通常由三個主要部分構建: 客戶端用戶界面(由 HTML 頁面和在用戶機器上的瀏覽器中運行的 javascript 組成),數據庫(由插入到公共的、通常是關系的數據庫管理中的許多表組成系統(tǒng))和服務器端應用程序。
服務器端應用程序將處理 HTTP 請求、執(zhí)行域邏輯、從數據庫檢索和更新數據,以及選擇和填充要發(fā)送到瀏覽器的 HTML 視圖。這個服務器端應用程序是一個整體,也就是一個單獨的進程。對系統(tǒng)的任何更改都需要重新構建和部署服務器端應用程序的最新版本。
對于單體服務來說,所有的處理請求邏輯都在單個進程中運行,為了結構化和代碼編寫規(guī)范,通常會使用編程語言的基本功能將應用程序劃分為類、函數和命名空間等。
雖然單體服務也可以通過負載均衡器后面運行多個實例來水平擴展應用,但是隨著服務器端業(yè)務越來越復雜,對于服務的每一次很小的變動都會導致對于整體服務的重新構建和部署。并且隨著時間的推移,通常很難保持良好的模塊化結構,和對現有架構進行擴展。同時因為單體服務在一個進程中運行,如果該進程出現運行時問題,會導致所有的服務不可用,穩(wěn)定性不夠。
俗話說得好,雞蛋不能放在一個籃子里面。
于是把巨大的單體服務拆分成為一個個的微服務就是現在系統(tǒng)架構的熱潮。
微服務架構就是將單體的應用程序拆分為一個個的服務,這些服務可以獨立部署和擴展,并且服務之間有牢固的模塊邊界,服務之間主要通過HTTP協議進行交互。因為服務之間是無內部耦合的,所以我們可以甚至使用不同的編程語言來實現不同的服務。提高了程序的靈活性。
微服務的特征
微服務有些什么特征呢?什么樣的服務才能被稱為是微服務呢?
社會很復雜,單純的是人。實際工程上的問題,不會向書本上學到的知識那樣,有一個明確定義。事實上,出了學校之后,這個世界上的事情已經不是非黑即白了。
比如,我們上學時候學到的圓的定義,它清晰的告訴我們,什么是圓。而對于微服務來說,則并沒有這樣的定義。
因為微服務是在不斷的實踐中總結摸索出來的一種架構。雖然不同的人對微服務有不同的理解,但是他們應該都具有下面幾個共同的特征。
組件服務化
自從軟件變得復雜之后,為了更好的進行軟件開發(fā)和后續(xù)的擴展,軟件逐漸開始組件化。所謂組件就是一個個的可以獨立替換和升級的部件。
現代程序中有很多可以稱之為組件的東西,比如java中的依賴jar包,python中的依賴包等。
這些lib可以在運行時鏈接到程序中,以內存中的函數進行運行。
有了鏈接的lib,為什么我們還需要將這些組件服務化,以單獨的進程來運行呢?
使用服務作為組件(而不是庫)的一個主要原因是服務是可獨立部署的。如果您的應用程序 由單個進程中的多個庫組成,則對任何單個組件的更改都會導致必須重新部署整個應用程序。
但是,如果該應用程序分解為多個服務,那么對于該服務的變更,只需要重新部署該服務即可。雖然這不是絕對的,因為有些服務的變化會導致對應的調用接口的變化,所以也需要對應的服務來進行修改和適配。但是一個好的微服務架構的目標是通過服務契約中的內聚服務邊界和演化機制來最小化這些變動。
使用服務作為組件的另一個好處是更明確的組件接口。大多數語言沒有定義顯式發(fā)布接口的良好機制,從而導致組件之間的耦合過于緊密。通過使用顯式遠程調用機制,服務可以更容易的進行定義。
使用服務也有他的缺點,因為服務之間是通過遠程調用的,遠程調用比進程內調用更昂貴,所以服務之間的調用通常是更加粗粒度的調用,所以我們在界定服務的時候,需要劃分明確的職責分配。
組織的劃分
根據康威定律:組織溝通方式決定系統(tǒng)設計。
通常來說,對于大型的系統(tǒng)可以分為UI團隊,服務邏輯團隊和數據庫團隊。但是這樣的組織方式就會導致一個團隊的改動需要其他團隊也進行改動來配合。
所以在微服務中,組織應該是安裝具體的業(yè)務來劃分,這樣能夠保證組織的靈活性。
服務之間的通信
對于單體服務而言,依賴的lib是通過內部函數的調用來實現的,它的好處就是速度快,但是如果將單體服務轉換成微服務,就需要考慮到服務之間的相互調用問題。
常見的服務之間的調用方式有哪些呢?
最常見的就是HTTP/HTTPS協議之間的調用,這種方式的好處就是協議簡單通用,兼容性的成本較低。
如果是跨語言的,通常會用Thrift之類的RPC遠程調用協議,這種方式的好處就是會比HTTP調用要快,但是調用起來比較復雜。需要構建特定的客戶端。
上面講的是同步調用,如果是異步的話,還可以使用MQ機制,MQ的作用一是可以削峰,二是可以解耦。
去中心化治理
對于微服務來說,并不要求所有的微服務都采用同一種語言,同一種架構方式來進行。通常來說了保證系統(tǒng)和代碼的可維護性,一般來說是要求所有的服務都使用同樣的編程語言和架構。
但是對于特別的部分,比如對性能要求特別高這樣的需求,那么可以嘗試考慮一個不同的編程語言。
總的來說,就是每個微服務的團隊對他們自己的服務負責,只需要保證對外的服務和接口的正確性即可。
去中心化數據管理
對于單體應用來說, 所有的數據都放在一個數據庫中。如果對微服務進行了去中心化管理,那么相應的數據庫屬于各個微服務組,所以在理論上微服務的數據也應該是去中心化部署的。
但是這樣多個數據庫照成的后果就是各個數據庫中數據的一致性。在單體應用中,這個問題可以通過數據庫事務來解決。但是對于微服務來說,分布式事務是不可行的,或者說代價太大。一般來說對于微服務來說,我們需要保證數據的最終一致性。
通過補償機制來進行數據的校驗和修復。
自動化部署
自動化部署的目標就是持續(xù)交付,對于微服務來說,多個服務的自動化是必不可少的。通過自動化編譯,自動化測試,自動化集成和自動化部署,可以大大的減輕開發(fā)團隊和運維團隊的任務。提升開發(fā)效率。
對異常的響應
使用服務作為組件的結果是,應用程序需要設計成可以容忍服務失敗。 任何服務調用都可能因網絡或者其他的原因導致不可用而失敗,所以必須盡可能優(yōu)雅地對此做出響應。
于單體服務相比,這需要引入額外的復雜性來處理它,所以可以看做是微服務的一個缺點。開發(fā)團隊需要盡量多做異常測試,以保證在極端的環(huán)境中程序的正確性。
由于服務隨時可能出現故障,因此能夠快速檢測故障并在可能的情況下自動恢復服務非常重要。微服務應用程序非常重視應用程序的實時監(jiān)控,檢查架構元素(數據庫每秒收到多少請求)和業(yè)務相關指標(例如每分鐘收到多少訂單)。語義監(jiān)控可以提供錯誤的早期預警系統(tǒng),讓開發(fā)團隊跟進和調查。 監(jiān)控對于快速發(fā)現不良的緊急行為并加以修復至關重要。
我們希望看到針對每個單獨服務的復雜監(jiān)控和日志記錄設置,例如顯示啟動/關閉狀態(tài)的儀表板以及各種運營和業(yè)務相關指標,還包括有關斷路器狀態(tài)、當前吞吐量和延遲的詳細信息等。
總結
講了這么多微服務的特征,微服務雖然有他的靈活性的優(yōu)點,但是如何劃分微服務的邊界,和對微服務的監(jiān)控是一個很復雜的問題,所以到底要不要使用微服務還留給讀者自己思考。
最后,問大家一個問題,在現實的項目中,有很多人希望把現有的單體服務拆分成為微服務,但是各個微服務還是共享著同一個數據庫,也就是說這些微服務之間還存在著數據交叉。那么這種微服務算不算是真正的微服務呢?