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