今天閱讀了兩篇關於微服務的文章,總結一些筆記,不敢貿然翻譯:一是由於水平不夠,翻譯的過程會丟掉做者的原意;二是由於技術翻譯是一個略微吃力不討好的活。前端
微服務(micro services)這個概念不是新概念,不少公司已經在實踐了,例如亞馬遜、Google、FaceBook,Alibaba。微服務架構模式(Microservices Architecture Pattern)的目的是將大型的、複雜的、長期運行的應用程序構建爲一組相互配合的服務,每一個服務均可以很容易得局部改良。 Micro這個詞意味着每一個服務都應該足夠小,可是,這裏的小不能用代碼量來比較,而應該是從業務邏輯上比較——符合SRP原則的才叫微服務。web
暫且不討論大小問題,讀者朋友你首先要考慮的是如何解決目前技術團隊遇到的開發問題、部署問題。正是在解決這些問題的過程當中,才漸漸總結提煉出了微服務架構模式的概念。docker
微服務跟SOA有什麼區別呢,能夠把微服務當作去除了ESB的SOA。ESB是SOA架構中的中心總線,設計圖形應該是星形的,而微服務是去中心化的分佈式軟件架構。數據庫
接下來會討論如下幾個話題:後端
web應用程序發展的早期,大部分web工程是將全部的功能模塊(service side)打包到一塊兒並放在一個web容器中運行,不少企業的Java應用程序打包爲war包。其餘語言(Ruby,Python或者C++)寫的程序也有相似的問題。服務器
假設你正在構建一個在線商店系統:客戶下訂單、覈對清單和信用卡額度,並將貨物運輸給客戶。很快,大家團隊必定能構造出以下圖所示的系統。網絡
這種將全部功能都部署在一個web容器中運行的系統就叫作巨石型應用。巨石型應用有不少好處:IDE都是爲開發單個應用設計的、容易測試——在本地就能夠啓動完整的系統、容易部署——直接打包爲一個完整的包,拷貝到web容器的某個目錄下便可運行。架構
可是,上述的好處是有條件的:應用不那麼複雜。對於大規模的複雜應用,巨石型應用會顯得特別笨重:要修改一個地方就要將整個應用所有部署(PS:在不一樣的場景下優點也變成了劣勢);編譯時間過長;迴歸測試周期過長;開發效率下降等。另外,巨石應用不利於更新技術框架,除非你願意將系統所有重寫(代價過高你願意老闆也不肯意)。併發
詳細一個網站在業務大規模爬升時會發生什麼事情?併發度不夠?OK,加web服務器。數據庫壓力過大?OK,買更大更貴的數據庫。數據庫太貴了?將一個表的數據分開存儲,俗稱「分庫分表」。這些都沒有問題,good job。不過,老外的抽象能力比咱們強,看下圖Fig2。app
這張圖從三個維度歸納了一個系統的擴展過程:
(1)x軸,水平復制,即在負載均衡服務器後增長多個web服務器;
(2)z軸擴展,是對數據庫的擴展,即分庫分表(分庫是將關係緊密的表放在一臺數據庫服務器上,分表是由於一張表的數據太多,須要將一張表的數據經過hash放在不一樣的數據庫服務器上);
(3)y軸擴展,是功能分解,將不一樣職能的模塊分紅不一樣的服務。從y軸這個方向擴展,才能將巨型應用分解爲一組不一樣的服務,例如訂單管理中心、客戶信息管理中心、商品管理中心等等。
將系統劃分爲不一樣的服務有不少方法:
(1)按照用例劃分,例如在線商店系統中會劃分出一個checkout UI服務,這個服務實現了checkout這個用例;
(2)按照資源劃分,例如能夠劃分出一個catlog服務來存儲產品目錄。
服務劃分有兩個原則要遵循:
(1)每一個服務應該儘量符合單一職責原則——Single Responsible Principle,即每一個服務只作一件事,並把這件事作好;
(2)參考Unix命令行工具的設計,Unix提供了大量的簡單易用的工具,例如grep、cat和find。每一個工具都小而美。
最後還要強調:系統分解的目標並不只僅是搞出一堆很小的服務,這不是目標;真正的目標是解決巨石型應用在業務急劇增加時遇到的問題。
對於上面的例子,按照功能和資源劃分後,就造成下面圖3的架構圖。分解後的微服務架構包含多個前端服務和後端服務。前端服務包括Catalog UI(用於商品搜索和瀏覽)、Checkout UI(用於實現購物車和下單操做);後端服務包括一些業務邏輯模塊,咱們將在巨石應用中的每一個服務模塊重構爲一個單獨的服務。這麼作有什麼問題呢?
《人月神話》中講到:沒有銀彈,意思是隻靠一把錘子是蓋不起摩天大樓的,要根據業務場景選擇設計思路和實現工具。咱們看下爲了換回上面提到的好處,咱們付出(trade)了什麼?
在巨石型架構下,客戶端應用程序(web或者app)經過向服務端發送HTTP請求;可是,在微服務架構下,原來的巨石型服務器被一組微服務替代,這種狀況下客戶端如何發起請求呢?
如圖4中所示,客戶端能夠向micro service發起RESTful HTTP請求,可是會有這種狀況發生:客戶端爲了完成一個業務邏輯,須要發起多個HTTP請求,從而形成系統的吞吐率降低,再加上無線網絡的延遲高,會嚴重影響客戶端的用戶體驗。
爲了解決這個問題,通常會在服務器集羣前面再加一個角色:API gateway,由它負責與客戶度對接,並將客戶端的請求轉化成對內部服務的一系列調用。這樣作還有個好處是,服務升級不會影響到客戶端,只須要修改API gateway便可。加了API gateway以後的系統架構圖如圖5所示。
內部服務之間的通訊方式有兩種:基於HTTP協議的同步機制(REST、RPC);基於消息隊列的異步消息處理機制(AMQP-based message broker)。
Dubbo是阿里巴巴開源的分佈式服務框架,屬於同步調用,當一個系統的服務太多時,須要一個註冊中心來處理服務發現問題,例如使用ZooKeeper這類配置服務器進行服務的地址管理:服務的發佈者要向ZooKeeper發送請求,將本身的服務地址和函數名稱等信息記錄在案;服務的調用者要知道服務的相關信息,具體的機器地址在ZooKeeper查詢獲得。這種同步的調用機制足夠直觀簡單,只是沒有「訂閱——推送」機制。
AMQP-based的表明系統是kafka、RabbitMQ等。這類分佈式消息處理系統將訂閱者和消費者解耦合,消息的生產者不須要消費者一直在線;消息的生產者只須要把消息發送給消息代理,所以也不須要服務發現機制。
兩種通訊機制都有各自的優勢和缺點,實際中的系統常常包含兩種通訊機制。例如,在分佈式數據管理中,就須要同時用到同步HTTP機制和異步消息處理機制。
在線商店的客戶帳戶有限額,當客戶試圖下單時,系統必須判斷總的訂單金額是否超過他的信用卡額度。信用卡額度由CustomerService管理、下訂單的操做由OrderService負責,所以Order Service要經過RPC調用向Customer Service請求數據;這種方法可以保證每次Order Service都獲取到準確的額度,單缺點是多一次RPC調用、並且Customer Service必須保持在線。
還有一種處理方式是,在OrderService這邊存放一份信用卡額度的副本,這樣就不須要實時發起RPC請求,可是還須要一種機制保證——當Customer Service擁有的信用卡額度發生變化時,要及時更新存放在Order Service這邊的副本。
當一份數據位於多個服務上時,必須保證數據的一致性。
在實際工做中,不多有機會參與一個全新的項目,須要處理的差很少都是存在這樣那樣問題的複雜、大型應用。這時候如何在維護老服務的同時,將系統漸漸重構爲微服務架構呢?
關於重構,有篇文章推薦你們閱讀——推倒重來的講究,關於重構有不少能夠寫的,但願我能快速進步,多寫點總結與你們分享。
微服務並非治百病的良藥,也不是什麼新的技術,我從中學到的最大的一點就是scale cube,從這個座標軸出發去考慮大規模系統的構建比較容易分析和實踐。