搞懂微服務,從捕捉一頭野豬說起

 

看上圖,當一條獵狗抓一隻兔子的時候是不是很輕鬆,畢竟兔子的體型比狗小的多。

 

 

 

但當一條獵狗去捕捉野豬呢,那我們就可以等着吃狗肉了。野豬的力量和體型不比狗小,對於狗來說,野豬就是大數據

 

 

 

一條狗治不了那我就安排多條,一條負責咬耳朵,一條咬喉嚨,一隻條咬肚子,分工明確,成功把野豬拿下。

 

爲了捕捉到野豬我可以有兩個選擇,一個是養頭獵豹,一個是養三條土狗。養獵豹的話是不可能的,屬於保護動物,就算可以養,成本也高。養三條土狗的成本遠遠比養一頭獵豹的低的多,但能達到的目的是一樣的。這三條土狗就組成一個簡單的分佈式系統,每條狗都相當於一個微服務,不同的分工,協力合作。

 

 

微服務沒有一個精確的定義,可以說這是一種軟件架構風格,利用模組化的方式組合出複雜的大型應用程序,各功能區塊使用通過 API 相互通訊,而實現方法也多種多樣,每個公司使用微服務的出發點也不盡相同。但是微服務卻有幾個重要的共同特點:

 

1. 小而單一 (small and single resposibility),並且專注於做一件事情,只負責一個系統下的某一個功能。

 

例如例子中的獵狗,在捕殺野豬時分工明確,全身心的做自己該做的事。

 

在初步劃分模塊的時候,通常公司可以按照自己的業務領域來分塊服務,一個典型的例子就是垂直電商系統一般可以分爲:

 

用戶模塊服務 Customer Service,、產品模塊服務 Product Service、訂單模塊服務 Order Service、支付模塊服務 Payment Service 和 運送模塊服務Shipping Service。

 

每一個服務只負責一個領域模型中所需要完成的任務。這樣輕鬆實現整個微服務系統的鬆耦合和較高的維護能力。

 

 

2. 獨立部署 (independently deployable),升級,擴展或者替換。

 

當我們發現咬野豬的生殖器官比耳朵更致命時,我們就可以訓練野狗這個技能,方便下次以更快速度進行捕殺,這就是升級。

 

要是準備去捕殺一隻野豬王,它體型比平時的野豬都大,而且兇。這時候三條獵狗是不夠的,我們可以多叫上幾條獵狗,這就是擴展。

 

當一條土狗陣亡了,我可以比較快速地去再養一隻,讓它儘快地參與戰鬥,這就是替換。

 

 

在此我們可以對比一下單體應用(monolithic application)。譬如上文中提到的垂直電商系統,在單體應用下,所有這些模塊都是打包在同一個war,或者ear文件下面,部署到一個應用服務器上面,這個應用服務器可以Web應用服務器,譬如Tomcat,或者是J2EE應用服務器,譬如WebLogic或者是Jboss。

 

通常在這樣架構下,當我們需要替換,升級,或者一個簡單的修改某一個模塊,譬如支付模塊的話,我們需要怎麼做?修改支付模塊代碼,編譯整個項目,重新打包成一個war,ear文件,然後替換整個應用系統。

 

即使我們修改的模塊和其他模塊沒有任何關係,但是,我們必須一起替換。這就增加了我們日常的工作量和風險,譬如測試方便,除了做單元測試,我們還需要做一個集成測試,來保持我們其他模塊一樣工作。

 

如果一個架構不是很好的系統,軟件模塊之間沒實現鬆耦合,那麼修改一個模塊,很有可能導致另外一個模塊的不工作。

 

當你是一個新人,加入一個開發組,team leader告訴你,把支付模塊一個bug修了,你廢了九牛二虎之力,很開心的修完了那個bug,通過單元測試,提交了代碼,過了一會一封郵件過來,jenkins上面出錯了,某一個和支付模塊完全不相關的用戶管理模塊出錯了。是誰的錯,不是你的錯,可能是架構師沒有架構好軟件,但是通常情況下,你得負責。

 

 

而微服務的獨立部署能力就是爲了避免這樣類似的問題再出現,通常一個微服務是領域驅動設計下完成的,各模塊之間有非常清楚明晰的邊界。

 

  

那麼有人會說,那怎麼從一個單體應用,轉換成一個成功,鬆耦合,易於升級和擴展的微服務架構的。這有一個非常有趣的話題,包括很多方面的考慮,從領域驅動設計,到技術選擇和實現,到怎麼一步一步分解一個巨大而複雜的單體應用,到一個個微服務,以及各個微服務之間的通信選擇,畢竟當你擁有200個微服務的時候,微服務之間的通信已經不是簡單的進程內呼叫了,而是通過網絡協議來實現的,穩定性和性能都會有影響。

 

 

3. 輕量級通信協議 (lightweight communication protocol)

 

最常用的是HTTP協議下的REST,或者Message機制,譬如JMS, 或者AMQP (Advanced Message Queuing Protocol),也就是消息隊列。

 

由於每個微服務都是一個獨立的應用程序,這個獨立程序可以部署在同一個,或者不同的服務器上面,從Java程序角度來講,每一個微服務就是一個Java進程。所以服務之間的通信就不再是一個進程內的呼叫。我們就需要一個輕量級通信協議來完成各個分佈式服務之間的通信。

 

而這種通信可以分爲兩種,同步和異步。當我們需要一個同步呼叫來完成一個業務邏輯,通常會通過HTTP下的REST API來實現,通常可以選擇Spring下的Restful框架或者是Oracle下的JAX-RS。而當我們需要服務之間做異步通信時,Message會是一個很好的協議。Java微服務應用程序之間可以使用非常成熟的JMS,如果是Java和非Java程序應用之間,現在比較流行的是AMQP協議。

 

 

4. 去中心化數據管理 (decentralized data management)

 

多樣化持久性(Polyglot Persistence),即讓每一個微服務都有其自己的數據庫,並且允許其各自擁有不同類型的數據持久化特性一直是微服務架構所倡導的。

 

當我們開發一個企業化大型應用時,我們通常會發現,數據的類型,屬性和被查詢和修改的頻率都會不一樣,而傳統的單體應用下,我們通常會使用一箇中心數據庫,來存儲所有數據。

 

譬如一個垂直電商的應用裏面可以有客戶信息數據,商品數據,購物車數據,訂單數據,支付數據。單體應用下,我們很可能就使用一個Mysql數據庫就解決所有問題。

 

而微服務框架下,允許也提倡每一個服務模塊下擁有自己的數據庫,這個數據庫可以是SQL類型的數據庫,譬如Oracle,MYSQL,PostgreSQL等等,也可以是Nosql類型數據庫,譬如MongoDB,Cassandra, Amazon DynamoDB等等,當然你也可以根據你的數據類型,在NOSQL裏面來選擇哪種類型的數據庫。

 

那麼說我們就不能讓兩個或多個微服務之間共享一個數據庫了嗎,個人認爲是不提倡,但是也不反對,具體情況具體分析。譬如當你需要一個request call裏面的多個數據持久化在一個事務內完成,在這種情況下,通常一個SQL數據庫會讓事情變得簡單。譬如當你擔心數據的一致性能否得到保障,而且要達到ACID級別時,可能分佈式數據管理會變得不可能。

 

當然如果你一定要分佈式管理數據的話,可以通過最終一致性(Eventual Consistency)來做。實現數據的強一致性,強最終一致性,還是最終一致性一直是分佈式計算下的一個難題。這也是我們在設計微服務架構時可能會遇到也需要考慮的問題。

 

 

5. 公共設施自動化 (Infrastructure Automation)

 

通過採用一系列的開源軟件,自動化開發,測試,部署流程,可以大大提高產品的質量和交付能力。

 

在決定是否要採用微服務架構前,應該考慮團隊是否有足夠的經驗在公共設施自動化方面。實戰用例告訴我們,那些在微服務系統上面取得成功的團隊都擁有豐富的連續集成和連續交付能力。

 

這涉及到一連串的自動化能力,包括編譯,單元測試,功能測試,集成測試,用戶體驗測試和性能測試上面的自動化,包括部署自動化。我們只有通過做大量的自動化測試,才能大大的增強團隊的信心。因爲當我們採用微服務架構時,我們所要處理的不是一個單體應用所帶來的問題,而且幾十個,幾百個微服務,甚至是部署在上百個服務器上面,到那時候我們再考慮自動化,可能未免太晚了。

 

 

好了,已經深夜了。本文從大數據,分佈式系統,談到了當前非常流行的微服務架構以及其共享的一些重要特徵。當然,當你真正開始着手開始把一個單體應用變爲一系列微服務時,所需要面臨的挑戰還有很多。

 

譬如怎麼來對你已經存在的碩大的單體應用來解體;譬如當你成功解體到一系列的微服務後,怎麼來解決由於分佈式結構導致的系統性能問題;譬如當你實現了多樣持久化後,發現事務處理變得積極複雜,怎麼來管理分佈式系統下的數據,保證數據一致性等等。

 

繼續關注,下次接着說~~

 

--end--

 

作者介紹:機械自學轉型大數據開發,目前任職於西班牙外企,致力於傳播大數據技術。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章