不少開發者都表示他們基於HTTP的API是RESTful的。可是,如同Fielding在他的博客中所說,這些API可能並不都是RESTful的。Leonard Richardson爲REST定義了一個成熟度模型,具體包含如下4個層次(摘自IBM):html
使用基於HTTP的協議有以下好處:
• HTTP很是簡單而且你們都很熟悉。
• 可使用瀏覽器擴展(好比Postman)或者curl之類的命令行來測試API。
• 內置支持請求/響應模式的通訊。
• HTTP對防火牆友好的。
• 不須要中間代理,簡化了系統架構。
不足之處包括:
• 只支持請求/響應模式交互。可使用HTTP通知,可是服務端必須一直髮送HTTP響應才行。
• 由於客戶端和服務端直接通訊(沒有代理或者buffer機制),在交互期間必須都在線。
• 客戶端必須知道每一個服務實例的URL。如以前那篇關於API Gateway的文章所述,這也是個煩人的問題。客戶端必須使用服務實例發現機制。
開發者社區最近從新發現了RESTful API接口定義語言的價值。因而就有了一些RESTful風格的服務框架,包括RAML和Swagger。一些IDL,例如Swagger容許定義請求和響應消息的格式。其它的,例如RAML,須要使用另外的標識,例如JSON Schema。對於描述API,IDL通常都有工具來定義客戶端和服務端骨架接口。
Thrift
Apache Thrift是一個頗有趣的REST的替代品。它是Facebook實現的一種高效的、支持多種編程語言的遠程服務調用的框架。Thrift提供了一個C風格的IDL定義API。使用Thrift編譯器能夠生成客戶端和服務器端代碼框架。編譯器能夠生成多種語言的代碼,包括C++、Java、Python、PHP、Ruby, Erlang和Node.js。
Thrift接口包括一個或者多個服務。服務定義相似於一個JAVA接口,是一組方法。Thrift方法能夠返回響應,也能夠被定義爲單向的。返回值的方法其實就是請求/響應類型交互模式的實現。客戶端等待響應,並可能拋出異常。單向方法對應於通知類型的交互模式,服務端並不返回響應。
Thrift支持多種消息格式:JSON、二進制和壓縮二進制。二進制比JSON更高效,由於二進制解碼更快。一樣緣由,壓縮二進制格式能夠提供更高級別的壓縮效率。JSON,是易讀的。Thrift也能夠在裸TCP和HTTP中間選擇,裸TCP看起來比HTTP更加有效。然而,HTTP對防火牆,瀏覽器和人來講更加友好。java
瞭解完HTTP和Thrift後,咱們來看下消息格式方面的問題。若是使用消息系統或者REST,就能夠選擇消息格式。其它的IPC機制,例如Thrift可能只支持部分消息格式,也許只有一種。不管哪一種方式,咱們必須使用一個跨語言的消息格式,這很是重要。由於指不定哪天你會使用其它語言。
有兩類消息格式:文本和二進制。文本格式的例子包括JSON和XML。這種格式的優勢在於不只可讀,並且是自描述的。在JSON中,一個對象就是一組鍵值對。相似的,在XML中,屬性是由名字和值構成。消費者能夠從中選擇感興趣的元素而忽略其它部分。同時,小幅度的格式修改能夠很容器向後兼容。
XML文檔結構是由XML schema定義的。隨着時間發展,開發者社區意識到JSON也須要一個相似的機制。一個選擇是使用JSON Schema,要麼是獨立的,要麼是例如Swagger的IDL。
基於文本的消息格式最大的缺點是消息會變得冗長,特別是XML。由於消息是自描述的,因此每一個消息都包含屬性和值。另一個缺點是解析文本的負擔過大。因此,你可能須要考慮使用二進制格式。
二進制的格式也有不少。若是使用的是Thrift RPC,那可使用二進制Thrift。若是選擇消息格式,經常使用的還包括Protocol Buffers和Apache Avro。它們都提供典型的IDL來定義消息架構。一個不一樣點在於Protocol Buffers使用的是加標記(tag)的字段,而Avro消費者須要知道模式(schema)來解析消息。所以,使用前者,API更容易演進。這篇博客很好的比較了Thrift、Protocol Buffers、Avro三者的區別。
總結nginx
微服務必須使用進程間通訊機制來交互。當設計服務的通訊模式時,你須要考慮幾個問題:服務如何交互,每一個服務如何標識API,如何升級API,以及如何處理部分失敗。微服務架構有兩類IPC機制可選,異步消息機制和同步請求/響應機制。在下一篇文章中,咱們將會討論微服務架構中的服務發現問題。
原文連接:Building Microservices: Inter-Process Communication in a Microservices Architecture(翻譯:楊峯 校對:李穎傑)apache
或許不少人會說 Spring Cloud 和 Dubbo 的對比有點不公平,Dubbo 只是實現了服務治理,而 Spring Cloud 下面有 17 個子項目(可能還會新增)分別覆蓋了微服務架構下的方方面面,服務治理只是其中的一個方面,必定程度來講,Dubbo 只是 Spring Cloud Netflix 中的一個子集。可是在選擇框架上,方案完整度偏偏是一個須要重點關注的內容。編程
根據 Martin Fowler 對微服務架構的描述中,雖然該架構相較於單體架構有模塊化解耦、可獨立部署、技術多樣性等諸多優勢,可是因爲分佈式環境下解耦,也帶出了很多測試與運維複雜度。json
根據微服務架構在各方面的要素,看看 Spring Cloud 和 Dubbo 都提供了哪些支持。api
以上列舉了一些核心部件,大體能夠理解爲何以前說 Dubbo 只是相似 Netflix 的一個子集了吧。固然這裏須要申明一點,Dubbo 對於上表中總結爲「無」的組件不表明不能實現,而只是 Dubbo 框架自身不提供,須要另外整合以實現對應的功能,好比:瀏覽器
雖然,Dubbo 自身只是實現了服務治理的基礎,其餘爲保證集羣安全、可維護、可測試等特性方面都沒有很好的實現,可是幾乎大部分關鍵組件都能找到第三方開源來實現,這些組件主要來自於國內各家大型互聯網企業的開源產品。安全
另外,因爲 Dubbo 是基礎框架,其實現的內容對於咱們實施微服務架構是否合理,也須要咱們根據自身需求去考慮是否要修改,好比 Dubbo 的服務調用是經過 RPC 實現的,可是若是仔細拜讀過 Martin Fowler 的 microservices 一文,其定義的服務間通訊是 HTTP協議的 REST API。那麼這兩種有何區別呢?服務器
先來講說,使用 Dubbo 的 RPC 來實現服務間調用的一些痛點:
相信這些痛點也是爲何當當網在 dubbox(基於 Dubbo 的開源擴展)中增長了對 REST 支持的緣由之一。
小結:Dubbo 實現了服務治理的基礎,可是要完成一個完備的微服務架構,還須要在各環節去擴展和完善以保證集羣的健康,以減輕開發、測試以及運維各個環節上增長出來的壓力,這樣才能讓各環節人員真正的專一於業務邏輯。而 Spring Cloud 依然發揚了 Spring Source 整合一切的做風,以標準化的姿態將一些微服務架構的成熟產品與框架揉爲一體,並繼承了 Spring Boot 簡單配置、快速開發、輕鬆部署的特色,讓本來複雜的架構工做變得相對容易上手一些(若是您讀過我以前關於 Spring Cloud 的一些核心組件使用的文章,應該能體會這些讓人興奮而激動的特性,傳送門)。因此,若是選擇 Dubbo 請務必在各個環節作好整套解決方案的準備,否則極可能隨着服務數量的增加,整個團隊都將疲於應付各類架構上不足引發的困難。而若是選擇 Spring Cloud,相對來講每一個環節都已經有了對應的組件支持,可能有些也不必定能知足你全部的需求,可是其活躍的社區與高速的迭代進度也會是你能夠依靠的強大後盾。
Dubbo 的文檔能夠說在國內開源框架中算是一流的,很是全,而且講解的也很是深刻,因爲版本已經穩定再也不更新,因此也不太會出現不一致的狀況,另外提供了中文與英文兩種版本,對於國內開發者來講,閱讀起來更加容易上手,這也是 Dubbo 在國內更火一些的緣由吧。
Spring Cloud 因爲整合了大量組件,文檔在體量上天然要比 dubbo 多不少,文檔內容上還算簡潔清楚,可是更多的是偏向整合,更深刻的使用方法仍是須要查看其整合組件的詳細文檔。另外因爲 Spring Cloud 基於 Spring Boot,不少例子相較於傳統 Spring 應用要簡單不少(由於自動化配置,不少內容都成了約定的默認配置),這對於剛接觸的開發者可能會有些不適應,比較建議瞭解和學習 Spring Boot 以後再使用 Spring Cloud,否則可能會出現不少只知其一;不知其二的狀況。
小結:雖然 Spring Cloud 的文檔量大,可是若是使用 Dubbo 去整合其餘第三方組件,實際也是要去閱讀大量第三方組件文檔的,因此在文檔量上,我以爲區別不大。對於文檔質量,因爲 Spring Cloud 的迭代很快,不免會出現不一致的狀況,因此在質量上我認爲 Dubbo 更好一些。而對於文檔語言上,Dubbo 天然對國內開發團隊來講更有優點。
經過上面再幾個環節上的分析,相信你們對 Dubbo 和 Spring Cloud 有了一個初步的瞭解。就我我的對這兩個框架的使用經驗和理解,打個不恰當的比喻:使用 Dubbo 構建的微服務架構就像組裝電腦,各環節咱們的選擇自由度很高,可是最終結果頗有可能由於一條內存質量不行就點不亮了,老是讓人不怎麼放心,可是若是你是一名高手,那這些都不是問題;而 Spring Cloud 就像品牌機,在 Spring Source 的整合下,作了大量的兼容性測試,保證了機器擁有更高的穩定性,可是若是要在使用非原裝組件外的東西,就須要對其基礎有足夠的瞭解。
從目前 Spring Cloud 的被關注度和活躍度上來看,頗有可能未來會成爲微服務架構的標準框架。因此,Spring Cloud 的系列文章,我會繼續寫下去。也歡迎各位朋友一塊兒交流,共同進步。
原文連接: 微服務架構的基礎框架選擇:SpringCloud仍是Dubbo
如何將一個系統拆分紅SCS(自包含系統)
在進行領域驅動設計(DDD)時,爲了儘量下降SCS之間的耦合,每一個SCS應該實現一個 邊界上下文 。每一個系統不僅擁有一個領域模型,事實上,一個系統能夠包含多個不一樣的領域模型。每個模型都有一個邊界上下文。例如,在電子商務系統裏搜索產品的當前價格時,產品的描述和數量是很重要的。而若是要向客戶發貨,則還須要其餘的信息:產品的重量和客戶的收貨地址。將系統拆分紅邊界上下文是構建自包含系統最爲有效的方式。
能夠經過對用戶故事進行分組來定義邊界上下文。假設咱們經過全文檢索來搜索產品,那麼經過分類和推薦來搜索也應該屬於相同的邊界上下文。固然,有時候拆分並不會有很是清楚的界線,這要取決於搜索的複雜性。
在將系統拆分紅SCS時也須要考慮到 用戶體驗 。用戶體驗描述了客戶與系統之間的交互步驟,好比搜索產品、結帳或註冊。每個步驟均可能成爲一個SCS。這些步驟之間通常只有不多的依賴。這些步驟之間有承上啓下的關係:購物車在結帳時就變成了一個訂單,而後完成支付。
SCS不僅處理某種特定的領域對象。例如,使用一個SCS來處理全部的客戶數據就沒有多大意義:不少不一樣的邊界上下文都會用到客戶數據。因此,爲客戶單首創建模型並在一個單獨的SCS裏實現是不可能的事情。若是真的這樣子作了,那麼每一個須要用到客戶數據的系統都會依賴它。這也就是爲何在將系統拆分紅SCS時須要經過用戶故事、邊界上下文或用戶體驗來驅動,這種自上而下的方法會帶來低耦合的系統。
雖然在後續有必要識別出公共部分,但這不該該成爲關鍵點。公共邏輯能夠被抽取到另外一個系統裏,但這意味着SCS會對這個系統產生依賴,它們之間就產生了耦合。
在微服務集成——《微服務設計》讀書筆記文章中,咱們說過服務間的消息傳遞有幾種方式,一種是請求/響應技術,另外一種是基於事件的機制。
RPC(遠程過程調用)
RPC是Remote Procedure Call的簡稱。
這是請求/響應技術的一種,它使用本地調用的方式和遠程進行交互,如SOAP、Thrift等,好比咱們常使用的WebService和Java RMI,就是這種類型。它先在本地生成樁代碼,而後經過樁代碼進行遠程調用。
RPC會帶來一些問題,如Java RMI,其耦合性較緊,同時RPC會對調用進行大量的封裝和解封裝,同時修改接口時會形成服務的提供方和調用方都要修改。
REST
REST是受Web啓發而產生的一種架構風格,REST風格包含的內容不少,Richardson的成熟度模型(http://martinfowler.com/articles/richardsonMaturityModel.html),其中有對REST不一樣風格的比較。
REST自己並無提到底層應該使用什麼協議,最經常使用的是HTTP,HTTP自己提供了不少功能,這些功能對於實現REST風格很是有用,好比HTTP的動詞(GET、POST、PUT等)就能很好地和資源一塊兒使用。
在使用REST時,傳輸的數據格式是XML仍是JSON,這個沒有一個定論。
基於HTTP的REST也有缺點:
1.它沒法幫你生成樁代碼(封裝rest請求參數時須要),
2.在要求低延遲的場景下,每一個HTTP請求的封裝開銷多是個問題,使用TCP、UDP可能更合適。
基於事件的異步協做
這種方式主要有兩個部分須要考慮:微服務發佈事件消費者接收事件機制。
消息隊列(如RabbitMQ)能夠同進處理上述兩方法的問題。生產者使用API向代理髮布事件,代理能夠向消費者提供訂閱服務,而且在事件發生時通知消費者。這種代理甚至能夠跟蹤消費者的狀態,如標記哪些消息是該消費者已經消費過的。這種系統一般具備較好的可伸縮性和彈性,但這麼作會增長開發流程的複雜度,由於你須要一個額外的系統(即消息代理)才能開發及測試服務。
另外一種方式是使用HTTP來傳播事件,ATOM是一個符合REST規範的協議,能夠經過它提供資源聚合的發佈服務,當服務提供方發生改變時,只須要簡單地向該聚合發佈一個事件便可,消費者會輪詢該聚合以查看變化。它的缺點是:HTTP不擅長處理低延遲的場景,並且使用ATOM的話,用戶還須要本身追蹤消息是否送達及管理輪詢等工做。
異步架構有其複雜性,好比,消息丟失了怎麼辦?消息重試失敗了怎麼辦?消息重發了怎麼辦?消息請求崩潰了怎麼辦?咱們能夠經過設置最大重試、黑名單、白名單等措施來解決這些問題。但這也意味着複雜性的增長。
參考
《微服務設計》(Sam Newman 著 / 崔力強 張駿 譯)
http://www.cnblogs.com/gudi/p/6624917.html