微服務之間如何集成應該能夠說是微服務相關技術中最重要的知識之一。具體能夠表示成服務之間的調用方式、通訊協議、序列化協議等。
若是服務集成作得好,你的微服務能夠最大程度地保持自治,你能夠獨立地修改和發佈,相反,前期考慮得不周全的話,會給你帶來災難。html
本篇是微服務設計學習系列的第二篇(繼上一篇發佈竟然已經一個多月了,慚愧慚愧)。git
歡迎閱讀往期系列:程序員
服務集成的方式方法如此很是的多樣化,咱們如何在紛雜的技術中選出最適合的?github
首先,咱們要知道咱們想要從這些集成技術中獲得什麼?咱們指望的效果是怎麼樣的。這樣,咱們纔能有目的去選型。雖然根據業務不一樣會有不一樣的考慮,可是咱們總但願獲得這麼幾點的好處:編程
咱們不但願當咱們對某一個服務進行修改發佈的時候,須要對該服務的消費者們也進行修改發佈。咱們但願選用的技術可以儘可能避免破壞性修改的發生。好比,一個微服務在一個響應中添加了某個字段,已有的消費者不該該受到影響。segmentfault
幹咱們這一行的,應該最清楚這個領域惟一不變的就是不斷地變化。後端
新的工具、框架、語言層出不窮。好比如今的你是一個Java開發者,可能幾年後你會想嘗試Go語言這種更適合雲原生應用的語言來構建微服務。服務器
微服務靈活開放的特性來自於構建微服務的技術異構性,可是集成技術的選用不當,就會對微服務的具體實現技術產生限制。保證微服務之間通訊方式的技術無關性是很是重要的。這就意味着,不該該選擇那種對微服務的具體實現技術有限制的集成方式。網絡
消費方應該能很容易地使用咱們的服務。若是消費方使用該服務比登天還難,那麼不管該微服務多漂亮都沒有任何意義。架構
理想狀況下,消費方應該可使用任何技術來實現,從另外一方面來講,提供一個客戶端庫也能夠簡化消費方的使用。可是一般這種庫與其餘咱們想要獲得的東西不可兼得。舉個例子,使用客戶端庫對於消費方來講很方便,可是會形成耦合的增長。
(這一點經常會前面兩點衝突起來)
服務的內部實現細節應該最大程度地隱藏起來,不暴露出來。這也是從解耦的角度出發的。
全部傾向於暴露內部實現細節的技術都不該該被採用。
服務之間的方式能夠分爲同步通訊和異步通訊兩種方式。
若是使用同步通訊,發起一個遠程服務調用後,調用方會阻塞本身並等待整個操做的完成。如 RPC
,HTTP
調用。
若是使用異步通訊,調用方不須要等待操做完成就能夠返回,甚至可能不須要關心這個操做完成與否。如MQ
。
兩種通訊模式中,同步通訊的協做方式是 請求/響應 的方式,客戶端發起一個請求,而後等待響應。這種模式可以與同步通訊模式很好地匹配,但異步通訊也可使用這種模式。我能夠發起一個請求,而後註冊一個回調,當服務端操做結束以後,會調用該回調。
異步通訊的主要協做方式則是 基於事件 的方式,客戶端不是發起請求,而是發佈一個事件,而後期待其餘的協做者接收到該消息而後進行處理。
基於事件的系統天生就是異步的。整個系統都很聰明,也就是說,業務邏輯並不是集中存在於某個核心大腦,而是平均地分佈在不一樣的協做者中。基於事件的協做方式耦合性很低。客戶端發佈一個事件,但並不須要知道誰或者什麼會對此作出響應,這也意味着,你能夠在不影響客戶端的狀況下對該事件添加新的訂閱者。
延伸閱讀: 微服務模式-同步與異步,裏面對微服務通訊架構提出了更多的探討。上面的圖片也是從中引用。
一般來說,使用基於事件的協同工做的方式能夠有效下降系統的耦合度,而且你能更加靈活地對現有系統進行修改。可是,確實須要額外的工做來對業務流程作跨服務的監控。
這裏有好幾個因素須要考慮。同步調用比較簡單,並且很容易知道整個流程的工做是否正常。若是想要請求 / 響應風格的語義,又想避免其在耗時業務上的困境,能夠採用異步請求加回調的方式。另外一方面,使用異步方式有利於協同方案的實施,從而大大減小服務間的耦合,這偏偏就是咱們爲了能獨立發佈服務而追求的特性。
固然,在大部分的生產場景下,咱們看到的應該都是根據業務須要或者一些其餘緣由,混用不一樣的方式。
咱們先來看看目前流行的幾種集成方案:
本節主要針對 RPC(Remote Procedure Call,遠程過程調用)和 REST(REpresentational State Transfer,表述性狀態轉移)進行討論。
遠程調用(Remote Procedure Call,RPC)是一種網絡間的通訊方式,容許程序調用共享網絡中其餘服務器的方法或函數,而嚮應用開發者屏蔽遠程調用的相關技術細節。RPC應該儘可能作到簡單、高效和透明化。客戶端應用能夠像調用本地對象方法同樣直接調用另外一臺服務器上的服務端應用的對象方法。
RPC是一種技術思想而非一種規範。協議只規定了 Client 與 Server 之間的點對點調用流程,包括 stub、通訊協議、RPC 消息解析等部分,在實際應用中,還須要考慮服務的高可用、負載均衡等問題。
RPC要解決的兩個問題:
核心是通訊協議、序列化和調用框架。
現今流行的RPC 的實現會幫你生成服務端和客戶端的樁代碼,從而讓你快速開始編碼。基本不用花時間,我就能夠在服務之間進行內容交互了。這一般也是 RPC 的主要賣點之一:易於使用。從理論上來講,這種能夠只使用普通的方法調用而忽略其餘細節的作法簡直是給程序員的巨大福利。
(常見的RPC框架有:Java RMI, gRPC, Thrift, Dubbo等等)
然而有一些 RPC 的實現確實存在一些問題,好比和技術的強耦合特性,如Java RMI。這一點上有些RPC框架會經過不一樣語言的客戶端來解決調用的問題(如Dubbo),也有像gRPC同樣經過一個通用的服務契約,來生成代碼的方式來支持多種編程語言。
有不少的文章和書籍會將這二者放在一塊兒講,慣性思惟中,REST的實現方式是基於HTTP,RPC的通訊協議通常是TCP,可是RPC 這種方式也能夠實現REST風格的服務,只不過你須要本身定義動詞( GET, POST, PUT, DELETE),RPC 也可使用HTTP 實現,只用到 HTTP 不多的特性,而動詞和 HTTP 的錯誤碼都被忽略了。
最關鍵的是我認爲這二者不是一個維度的概念,很早以前我看一些文章把這兩個一塊兒對比的時候,我看着總會有點迷糊。
我以爲RPC 是面向過程(面向遠端服務函數調用),REST 則是面向資源。好比你提供一個查詢用戶的接口,用RPC風格,你可能會這樣寫:
/queryUser?userId=123 用Restful風格呢? Get /user?userId=123 再精煉一點,甚至能夠這樣: Get /user/123
RPC的思想是把本地函數映射到API,也就是說一個API對應的是一個function,我本地有一個getAllUsers,遠程也能經過某種約定的協議來調用這個getAllUsers。至於這個協議是Socket、是HTTP仍是別的什麼並不重要;
PS:實現一個RPC不難,難的是如何實現一個高性能高可靠的RPC框架
至於REST,是一種架構風格。REST 風格包含了不少原則和限制,我覺的最核心的點就在於規範,例如使用HTTP status code作錯誤碼,使用HTTP METHOD來表達本次請求要作的動做,使不一樣的業務系統都有一個「統一」的規範能夠參照。
可是這個統一的規範,真的好統一嗎?
我我的以爲在實際業務開發中,REST 這種設計思路是反程序員直覺的,由於在本地業務代碼中仍然是一個個的函數,是動做,但表如今接口形式上則徹底是資源的形式。就像面向對象的「萬物皆對象」理論在習慣了純粹面向過程開發的程序員眼裏顯得十分別扭同樣:個人代碼原本就是按順序、循環、分支這麼運行的啊,爲啥非得在很明確的結構上封裝一層一層的基類子類接口,還要故意給兩個函數起同一個名字,調用時才選擇用哪個呢?使用「萬物皆資源」的思想編寫實際項目中的API接口時,最多見的問題就是「這玩意究竟是個什麼資源?……算了,我就直接寫吧,無論什麼風格了」
主要是想說明,RESTful API在不少實際項目中並不實用。所以真的作了項目,要設計接口了,你可能會發現只能用HTTP+JSON來定義接口,API的語義和設計沒法嚴格遵照REST風格。(JSON+HTTP != REST)
這二者能夠共存嗎?有啊,SpringCloud 使用 Feign 組件將 REST 接口封裝成 RPC 調用,這不就是嗎?在這裏你的SpringBoot 應用接口能夠是REST風格的,只不過Feign 組件作了面向服務的包裝。
我我的以爲,REST 在先後端分離 的場景會比較有價值,或者說這個服務可能會被多個客戶端(網頁、移動端、其餘服務)集成的時候,REST的統一「規範」就顯示出了他的價值。
若是隻是內部服務的話,至少我瞭解的更多的使用的是成熟的RPC框架,由於一個成熟的RPC框架,更多的是封裝了「服務發現」,"負載均衡",「熔斷降級」一類面向服務的高級特性。能夠這麼理解,RPC框架是面向服務的更高級的封裝,Java 中 SpringCloud 是這樣,Dubbo也是這樣。
關於REST、RPC、HTTP之間的概念,我發現網上不少的文章講的實際上不是很清楚。我也是看了這篇文章Debunking the Myths of RPC & REST以後,才慢慢理解了這三者之間的概念。推薦你閱讀哦~
若是你以爲英文理解有難度的話,能夠閱讀這篇,很是的大白話:RPC-與-Restful
REST 風格包含的內容不少,強烈建議你看一看 Richardson 的成熟度模型,其中有對 REST 不一樣成熟度的比較。
REST 就像是講普通話,好處就是誰都聽得懂,誰都會講。
RPC 就像是講黑話,好處是能夠更精簡、更加保密、更加可定製,壞處就是要求「說」黑話的那一方(client端)也要懂,並且一旦你們都說一種黑話了,換黑話就困難了。
以上對於RPC和REST的討論,雖然思考了好久,但終歸仍是一家之言,很是但願有經驗有心得體會的同道們有不一樣意見能夠指明出來。
由於時間精力的緣由,本文並無過多的涉及代理消息傳遞這種方式的討論。但須要在這裏重提的是,REST、RPC和代理消息傳遞不是互斥的,它們均可以在你的微服務體系結構中一塊兒工做。 大公司的系統(基於雲)都在某種程度上有效利用了這幾種方式。最重要的仍是要根據業務場景合適的選擇適合的技術,不一樣通訊方式如何界定服務域邊界和解析方式。
關於RPC/REST/Brokered Messaging的更深刻的討論,推薦閱讀這一篇文章 REST, RPC, and Brokered Messaging
以上,是我對微服務集成技術的一些學習。但願能對你有所啓發和幫助。
若是本文有幫助到你,但願能點個贊,這是對個人最大動力。