NO IMAGE

服務間的IPC機制

按照微服務的架構體系,解決了服務發現的問題之後。就需要選擇合適的服務間通訊的機制。如果是在Springboot應用中,使用基於Http協議的REST API是一種同步的解決方案。而且Restful風格的API可以使每個微服務應用更加趨於資源化,服務化的鬆耦合思想靠近。
如果每個微服務是使用DDD的思想的話,那麼需要每個微服務儘量不使用同步的RPC機制。非同步的基於訊息的方式比如AMQP或者STOMP,來鬆耦合微服務間的依賴會是很好的選擇。目前基於訊息的點對點的pub/sub的框架選擇也比較多。下面具體介紹下兩種IPC的一些方案。

同步

對於同步的請求/響應模式的通訊方式。可以選擇基於Restful風格的Http協議進行服務間通訊,或者跨語言性很好的Thrift協議。如果是使用純Java語言的微服務,也可以使用Dubbo。如果是Springboot整合的微服務的架構體系,建議選擇跨語言性好,Spring社群支援比較好的RPC。

Dubbo

Dubbo是由阿里巴巴開發的開源的Java客戶端的RPC框架。Dubbo基於TCP協議的長連線進行資料傳輸。傳輸格式是使用Hessian二進位制序列化。其服務註冊中心可以通過zookeeper實現。

ApacheThrift

Thrift是由Facebook開發的RPC框架。其程式碼生成引擎可以在多種語言中,如C , Java, Python, PHP, Ruby, Erlang, Perl等建立高效的服務。傳輸資料採用二進位制格式,其資料包要比使用Json或者XML格式的http協議小。高併發,大資料場景下更有優勢。

REST

Rest Api基於Http協議,Http協議本身具有語義的豐富性。隨著Springboot被廣泛使用,越來越多的基於Restful風格的API流行起來。REST是基於http協議的,所以。並且大多數開發者也是熟知http的。
這裡另外提一點,很多公司或者團隊也是使用Springboot的,也在說自己是基於Restful風格的。但是事實其實往往是實施得並不到位。對於你的Restful是否是真的Restful,可以參考這篇文章,對於Restful風格API的成熟度進行了四個層次的分析: Richardson Maturity Model steps toward the glory of REST

如果使用Springboot的話,無論使用什麼服務發現機制,都可以通過Spring的RestTemplate來做基礎的Http請求封裝。
如果使用的前文提到的Netflix-Eureka的話,可以使用Netflix-FeignFeign是一個宣告式Web Service客戶端。客戶端的負載均衡使用Netflix-Ribbon

非同步

在微服務架構中,排除純粹的“事件驅動架構”,使用訊息佇列的場景一般是為了進行微服務之間的解耦。服務之間不需要了解是由哪個服務例項來消費或者釋出訊息。只要處理好自己領域範圍的邏輯,然後通過訊息通道來發布,或者訂閱自己關注的訊息就可以。目前開源的訊息佇列技術也很多。比如Apache KafkaRabbitMQApache ActiveMQ,以及阿里巴巴的RocketMQ。目前已經成為Apache專案之一。
訊息佇列的模型中,主要的三個組成就是:

  • Producer: 訊息生產者,將訊息寫入channel。
  • Message Broker:訊息代理,將寫入channel的訊息按佇列的結構進行管理。負責儲存/轉發訊息。Broker一般是需要單獨的搭建,配置的叢集,而且必須是高可用的。
  • Consumer:訊息的消費者。目前大多數的訊息佇列都是保證訊息至少被消費一次。所以根據使用的訊息佇列設施不同,消費者要做好冪等。

不同的訊息佇列的實現,訊息模型不同。各個框架的獨有的特性也不同:

RabbitMQ

RabbitMQ是AMQP協議的開源實現,由以高效能、可伸縮性出名的Erlang寫成。目前客戶端支援Java、.Net/C#和Erlang。在AMQP(Advanced Message Queuing Protocol)的元件中,Broker中可以包含多個Exchange(交換機)元件。Exchange可以繫結多個Queue以及其他Exchange。訊息會按照Exchange中設定的Routing規則,傳送到相應的Message Queue。在Consumer消費了這個訊息之後,會跟Broker建立連線。傳送消費訊息的通知。則Message Queue才會將這個訊息移除。

Kafka

Kafka是一個高效能跨語言分散式,基於釋出/訂閱的訊息系統。Kafka開發語言為Scala。其特性是:

  • 以時間複雜度為O(1)的方式快速訊息持久化;
  • 高吞吐率;
  • 支援服務間的訊息分割槽,及分散式消費,同時保證訊息順序傳輸;
  • 支援線上水平擴充套件,自帶負載均衡;
  • 支援只消費且僅消費一次(Exactly Once)模式等等。
  • 說個缺點: 管理介面是個比較雞肋的點,可以使用開源的kafka-manager

其高吞吐的特性,除了可以作為微服務之間的訊息佇列,也可以用於日誌收集, 離線分析, 實時分析等。
Kafka官方提供了Java版本的客戶端API, Kafka社群目前也支援多種語言, 包括PHP, Python, Go, C/C , Ruby, NodeJS等。

ActiveMQ

ActiveMQ是基於JMS(Java Messaging Service)實現的JMSProvider。JMS主要提供了兩種型別的訊息:點對點(Point-to-Point)以及釋出/訂閱(Publish/Subscribe)。目前客戶端支援 Java, C, C , C#, Ruby, Perl, Python, PHP。而且ActiveMQ支援多種協議:Stomp,AMQP,MQTT 以及OpenWire。

RocketMQ/ONS

RocketMQ是由阿里巴巴研發開源的高可用分散式訊息佇列。ONS是提供商業版的高可用叢集。ONS支援pull/push。可支援主動推送,百億級別訊息堆積。ONS支援全域性的順序訊息,以及有友好的管理頁面,可以很好的監控訊息佇列的消費情況,並且支援手動觸發訊息多次重發。

小結

通過上篇的微服務的服務發現機制,加上Restful API,可以解決微服務間的同步的程序間通訊。當然,既然使用了微服務,就希望所有的微服務能有合理的限界上下文(系統邊界)。微服務之間的同步通訊應儘量避免,以防止服務間的領域模型互相侵入。為了避免這種情況,就可以在微服務的架構中使用一層API gateway(會在下一篇介紹)。所有的微服務通過API gateway進行統一的請求的轉發,合成。並且API gateway需要同時支援同步,以及NIO的非同步的請求(可以提高請求合併的效率以及效能)。
訊息佇列可以用於微服務間的解耦。在基於Docker的微服務的服務叢集環境下,網路環境會比一般的分散式叢集複雜。選擇一種高可用的分散式訊息佇列實現即可。如果自己搭建諸如Kafka,RabbitMQ叢集環境的話,那對於Broker設施的高可用性會要求很高。基於Springboot的微服務的話,比較推薦使用Kafka,或者ONS。雖然ONS是商用的,但是易於管理以及穩定性高,尤其對於必要場景才依賴於訊息佇列進行通訊的微服務架構來說,會更適合。如果考慮到會存在日誌收集,實時分析等場景,也可以搭建Kafka叢集。目前阿里雲也有了基於Kafka的商用叢集設施。
下一篇會總結一下在微服務中使用API gateway,以及服務請求的熔斷機制的解決方案