在上文中,主要介紹了SOA的概念,什么叫做“服務”,“服務”應該具備哪些特性。本篇中,我將介紹SOA的一種很常見的設計實踐--基於服務總線的設計。
基於服務總線的設計
基於總線的設計,借鑒了計算機內部硬件組成的設計思想(通過總線傳輸數據)。在分布式系統中,不同子系統之間需要實現相互通信和遠程調用,比較直接的方式就是“點對點”的通信方式,但是這樣會暴露出一些很明顯的問題:系統之間緊密耦合、配置和引用混亂、服務調用關系錯綜復雜、難以統一管理、異構系統之間存在不兼容等。而基於總線的設計,正是為了解決上述問題。總線則作為中樞系統,提供統一的服務入口,並實現了服務統一管理、服務路由、協議轉換、數據格式轉換等功能。這樣能夠將不同系統有效地連接起來,並大大降低了連接數(每個子系統只需要和總線建立連接)和系統間連接拓撲的復雜度。如圖所示:
基於服務總線的設計,往往需要ESB(Enterprise Service Bus,企業服務總線)產品來充當基礎設施。ESB采用了“總線”這樣一種模式來管理和簡化應用之間的集成拓撲結構,以廣為接受的開放標准為基礎來支持應用之間在消息、事件和服務的級別上動態的互連互通。 ESB是一種在松散耦合的服務和應用之間標准的集成方式。
在其內部設計和實現中,通常會應用到一些經典的架構模式,例如:Broker模式、消息總線模式、管道過濾器模式、發布訂閱模式等。這里,我們將重點介紹這幾種核心的架構模式。
Broker模式
Broker可以看作是服務總線中的一部分,通常應用於同步調用的場景(調用服務后阻塞,等待遠程服務響應完成后再返回結果)。Broker可以看作是代理、分發,意味着對服務的調用,可以直接通過Broker來完成。在軟件架構設計中,向已經存在(引用或者調用)關系的兩者中間加入“第三者”是一種常見的解耦方式,顯然,Broker也不例外。如下圖所示:
為了進一步加深讀者對Broker模式的理解,這里通過舉例來說明:
在現實生活中,我們需要租房子(可以看作是一種服務調用),可以通過幾種途徑來完成。第一,我們可以先在網上了解,然后跑到目標小區去詢問和看房,最后再找房東簽合同等;第二,也可以直接找附近的地產中介,說出我們的要求和預算,請中介直接幫我們搞定一切。很明顯,第一種方式,需要自己對目標有足夠的了解而且還要親自去找房東簽合同(依賴具體,可以看作是緊密耦合),而第二種方式,僅僅需要告知中介需要什么即可完成租房,甚至都不需要知道哪個小區有房子、房東到底是誰等這些信息(依賴抽象,並通過第三者來實現解耦)。當然,找中介雖然省事,也會產生額外的經濟開銷。同理,通過Broker來調用服務也可能會產生一定的開銷。
消息總線模式
SOA系統有三種基礎組件:消息總線、信息轉換/處理引擎和存儲庫。一般來說,這些組件會集成到ESB中,而在這些基礎組件中,消息總線是最重要的。消息總線主要應用於異步通信場景(投遞消息后立刻返回結果,而不用等待遠程系統返回執行成功),可以大大提升響應速度和系統吞吐量。當然,消息總線也同時支持同步通信模式。基於消息總線模式的設計中,消息中間件屏蔽了系統間底層通信的細節,是比較典型的(異步)松耦合的架構。
在企業中,隨着業務的逐漸發展,各大系統之間的調用交互變得非常頻繁,關系錯綜復雜。
想象如果有幾十或者上百個系統(在保險、金融領域很常見),將變得難以維護。通過引入消息中間件,便能有效的解決這些問題。不同系統之間,只需要連接到消息總線,能保證成功投遞/接收消息即可。對於消息投遞者(生產者)而言,根本不用關心消息的接收者(消費者)到底有哪些,也不用關心消費者接收到消息之后該如何處理。對於接收者(消費者)而言,只需要關注與自己有關的消息,接收到消息后並做出相應的處理即可。如下圖所示:
比較典型的應用場景:張三在CRM系統中錄入了一條客戶簽約訂單的信息並審核通過后,CRM系統會向消息總線投遞一條消息(消息中包含必要信息,例如員工ID,訂單編號,產品編號和交易金額等,而CRM系統不用關心有哪些系統會接受到該消息)。員工績效獎金管理系統訂閱了該消息主題,收到消息通知后開始處理(給張三執行加獎金操作),同時,進銷存系統收到消息通知后也會即時地更新商品庫存的數量。這樣,便實現異構系統之間的松耦合、異步通信。當然,真實場景可能比這里更復雜,但是實現思路上都大同小異。
在理解了上述實例之后,有必要了解下Java EE中被廣泛應用和實現的JMS(Java消息服務)。
JMS是一種關於消息的規范,業界流行的ActiveMQ則是實現了JMS規范的開源消息總線。
JMS支持兩種模式:發布/訂閱模式和隊列模式(點對點模式)。其中,發布/訂閱模式借鑒了現實生活中的出版社(發布圖書)和讀者(訂閱圖書),消息的消費者(讀者)只需要訂閱自己感興趣的消息(圖書)即可,消息生產者(出版社)生產(出版)了消費者(讀者)感興趣的新消息(新書)后,會通知消費者(讀者)接受處理。在JMS發布/訂閱模式中,通常以Topic(主題)來標識消息,是一對多的模式,意味着同一個主題可以同時被多個消費者來訂閱和消費。而在JMS 隊列模型中,通常以Queue name來標識消息,是一對一的模型,意味着同一條消息只能被一個消費者接收並消費(且只能被消費一次)。在生產者和消費者都是集群的環境中,通常需要將這兩種模式結合起來使用,情況會復雜很多,而且需要考慮容錯性、負載均衡、消息一致性、消息優先級等復雜的問題。
業界主流的消息總線(消息中間件)產品,普遍支持消息過濾、自動重試、分布式事務、持久化、消息優先級、消息回溯、(生產者/消費者/中間件自身)集群、故障轉移等高級特性。
總結
基於總線架構的主要優勢在於:
l 可擴展性
使用消息架構,可以在不影響現有應用的情況下增加或移除應用。
l 低復雜度
每個應用只需要和總線通信,只有1個連接點,降低了應用程序集成的復雜度。
l 靈活性
對於構成復雜處理的應用程序通信組來說,只需要改變配置和控制路由參數就能滿足業務邏輯或者需求變更,而不需要更改服務本身。
l 松耦合
應用程序直接和消息總線通信,不依賴其它應用程序,因此可以替換和修改。
l 可擴展性
可以把多個應用程序附加到總線上,進行並發處理,達到負載均衡的目的。
基於總線的模型,可以面向同構和異構系統(跨平台)。當前主要應用於傳統企業應用的整合與系統集成中(例如:電信、保險、金融等行業)。由於基於總線的模型是一種集中式的架構,總線自身容易形成性能瓶頸,而且在實現高可用和容錯性方面的復雜度和成本相對較高。所以,該模式並不是很適合於高並發、高性能、高吞吐量的互聯網應用。
注:關於消息總線(消息中間件)的知識點很多,在實際應用中還有很多更加深入和復雜的細節問題。由於篇幅問題,筆者就不做過多的細節介紹和展開,感興趣的讀者,可以自行去查閱相關資料或者參考開源產品,做深入的學習和研究。
ESB產品主要包括:開源Mule ESB、ServiceMix、JBoss ESB,商業的Oracle ESB、BEA AquaLogic ServiceBus,.NET領域的NService Bus、MassTransit等。
MQ產品主要包括:ActiveMQ、RabbiteMQ、ZeroMQ、RocketMQ、Kafka、MSMQ等。
系列文章目錄:
1.SOA淺析
(從理論角度講述SOA和服務的概念,設計原則,面臨的問題等)
2.SOA之基於服務總線的設計
(從設計的角度講述服務總線--比較適合企業級系統集成的設計方式)
3.大型分布式網站的演變歷程
(隨着網站快速發展,解決業務復雜化、大流量、穩定性等問題的必經之路。正所謂“天下大勢,分久必合,合久必分”。
重點不是講負載均衡這些手段,而是設計層面的“集中式”到“分布式”)
4.SOA架構體系之通信協議和遠程調用(RPC)
(講解具體的實現技術,對比各自優缺點)
5.SOA之基於服務框架的應用
(服務化實踐--介紹流行的服務框架,重點演示一種服務框架的使用)