周志明论架构之道:从SOA时代到微服务时代
SOA 架構(Service-Oriented Architecture)
面向服務的架構是一次具體地、系統性地成功解決分布式服務主要問題的架構模式。
為了對大型的單體系統進行拆分,讓每一個子系統都能獨立地部署、運行、更新,開發者們曾經嘗試過多種方案,這里列舉以下三種較有代表性的架構模式,具體如下。
煙囪式架構(Information Silo Architecture):信息煙囪又名信息孤島(Information Island),使用這種架構的系統也被稱為孤島式信息系統或者煙囪式信息系統。它指的是一種完全不與其他相關信息系統進行互操作或者協調工作的設計模式。這樣的系統其實并沒有什么“架構設計”可言。接著上一節中企業與部門的例子來說,如果兩個部門真的完全不會發生任何交互,就并沒有什么理由強迫它們必須在一棟樓里辦公;兩個不發生交互的信息系統,讓它們使用獨立的數據庫和服務器即可實現拆分,而唯一的問題,也是致命的問題是,企業中真的存在完全不發生交互的部門嗎?對于兩個信息系統來說,哪怕真的毫無業務往來關系,但系統的人員、組織、權限等主數據,會是完全獨立、沒有任何重疊的嗎?這樣“獨立拆分”“老死不相往來”的系統,顯然不可能是企業所希望見到的。
微內核架構(Microkernel Architecture):微內核架構也被稱為插件式架構(Plug-in Architecture)。既然在煙囪式架構中,沒有業務往來關系的系統也可能需要共享人員、組織、權限等一些的公共的主數據,那不妨就將這些主數據,連同其他可能被各子系統使用到的公共服務、數據、資源集中到一塊,成為一個被所有業務系統共同依賴的核心(Kernel,也稱為 Core System),具體的業務系統以插件模塊(Plug-in Modules)的形式存在,這樣也可提供可擴展的、靈活的、天然隔離的功能特性,即微內核架構,如圖 1-2 所示。
這種模式很適合桌面應用程序,也經常在 Web 應用程序中使用。任何計算機系統都是由各種軟件互相配合工作來實現具體功能的,本節列舉的不同架構實現的軟件,都可視作整個系統的某種插件。對于平臺型應用來說,如果我們希望將新特性或者新功能及時加入系統,微內核架構會是一種不錯的方案。微內核架構也可以嵌入到其他的架構模式之中,通過插件的方式來提供新功能的定制開發能力,如果你準備實現一個能夠支持二次開發的軟件系統,微內核也會是一種良好的選擇。
不過,微內核架構也有它的局限和使用前提,它假設系統中各個插件模塊之間是互不認識,不可預知系統將安裝哪些模塊,因此這些插件可以訪問內核中一些公共的資源,但不會直接交互。可是,無論是企業信息系統還是互聯網應用,這一前提假設在許多場景中都并不成立,我們必須找到辦法,既能拆分出獨立的系統,也能讓拆分后的子系統之間順暢地互相調用通信。
圖 1-2 微內核架構示意
圖片來自 O'Reilly 的開放文檔《Software Architecture Patterns》
事件驅動架構(Event-Driven Architecture):為了能讓子系統互相通信,一種可行的方案是在子系統之間建立一套事件隊列管道(Event Queues),來自系統外部的消息將以事件的形式發送至管道中,各個子系統從管道里獲取自己感興趣、能夠處理的事件消息,也可以為事件新增或者修改其中的附加信息,甚至可以自己發布一些新的事件到管道隊列中去,如此,每一個消息的處理者都是獨立的,高度解耦的,但又能與其他處理者(如果存在該消息處理者的話)通過事件管道進行互動,如圖 1-3 所示。
圖 1-3 事件驅動架構示意
圖片來自 O'Reilly 的開放文檔《Software Architecture Patterns》
當系統演化至事件驅動架構時,原始分布式時代結尾中提到的第二條通往更大規模軟件的路徑,即仍在并行發展的遠程服務調用也迎來了 SOAP 協議的誕生(詳見遠程服務調用一文),此時“面向服務的架構”(Service Oriented Architecture,SOA)已經有了它登上軟件架構舞臺所需要的全部前置條件。
SOA 的概念最早由 Gartner 公司在 1994 年提出,當時的 SOA 還不具備發展的條件,直至 2006 年情況才有所變化,由 IBM、Oracle、SAP 等公司共同成立了 OSOA 聯盟(Open Service Oriented Architecture),用于聯合制定和推進 SOA 相關行業標準。2007 年,在結構化資訊標準促進組織(Organization for the Advancement of Structured Information Standards,OASIS)的倡議與支持下,OSOA 由一個軟件廠商組成的松散聯盟,轉變為一個制定行業標準的國際組織,聯合 OASIS 共同新成立了的Open CSA組織(Open Composite Services Architecture),這便是 SOA 的官方管理機構。
軟件架構來到 SOA 時代,許多概念、思想都已經能在今天微服務中找到對應的身影了,譬如服務之間的松散耦合、注冊、發現、治理,隔離、編排,等等。這些在今天微服務中耳熟能詳的名詞概念,大多數也是在分布式服務剛被提出時就已經可以預見的困難點。SOA 針對這些問題,甚至是針對“軟件開發”這件事情本身,都進行了更加系統性、更加具體的探索。
“更具體”體現在盡管 SOA 本身還是屬抽象概念,而不是特指某一種具體的技術,但它比單體架構和前面所列舉的三種架構模式的操作性要更強,已經不能簡單視其為一種架構風格,而是可以稱為一套軟件設計的基礎平臺了。它擁有領導制定技術標準的組織 Open CSA;有清晰軟件設計的指導原則,譬如服務的封裝性、自治、松耦合、可重用、可組合、無狀態,等等;明確了采用 SOAP 作為遠程調用的協議,依靠 SOAP 協議族(WSDL、UDDI 和一大票 WS-*協議)來完成服務的發布、發現和治理;利用一個被稱為企業服務總線(Enterprise Service Bus,ESB)的消息管道來實現各個子系統之間的通信交互,令各服務間在 ESB 調度下無須相互依賴卻能相互通信,既帶來了服務松耦合的好處,也為以后可以進一步實施業務流程編排(Business Process Management,BPM)提供了基礎;使用服務數據對象(Service Data Object,SDO)來訪問和表示數據,使用服務組件架構(Service Component Architecture,SCA)來定義服務封裝的形式和服務運行的容器,等等。在這一整套成體系可以互相精密協作的技術組件支持下,若僅從技術可行性這一個角度來評判的話,SOA 可以算是成功地解決了分布式環境下出現的主要技術問題。
“更系統”指的是 SOA 的宏大理想,它的終極目標是希望總結出一套自上而下的軟件研發方法論,希望做到企業只需要跟著 SOA 的思路,就能夠一攬子解決掉軟件開發過程中的全部問題,譬如該如何挖掘需求、如何將需求分解為業務能力、如何編排已有服務、如何開發測試部署新的功能,等等。這里面技術問題確實是重點和難點,但也僅僅是其中的一個方面,SOA 不僅關注技術,還關注研發過程中涉及到的需求、管理、流程和組織。如果這個目標真的能夠達成,軟件開發就有可能從此邁進工業化大生產的階段,試想如果有一天寫出符合客戶需求的軟件會像寫八股文一樣有跡可循、有法可依,那對軟件開發者來說也許是無趣的,但整個社會實施信息化的效率肯定會有大幅的提升。
SOA 在 21 世紀最初的十年里曾經盛行一時,有 IBM 等一眾行業巨頭廠商為其吶喊沖鋒,吸引了不少軟件開發商、尤其是企業級軟件的開發商的跟隨,最終卻還是偃旗息鼓,沉寂了下去。在稍后的遠程服務調用一節,筆者會提到 SOAP 協議被逐漸邊緣化的本質原因:過于嚴格的規范定義帶來過度的復雜性。而構建在 SOAP 基礎之上的 ESB、BPM、SCA、SDO 等諸多上層建筑,進一步加劇了這種復雜性。開發信息系統畢竟不是作八股文章,過于精密的流程和理論也需要懂得復雜概念的專業人員才能夠駕馭。SOA 誕生的那一天起,就已經注定了它只能是少數系統陽春白雪式的精致奢侈品,它可以實現多個異構大型系統之間的復雜集成交互,卻很難作為一種具有廣泛普適性的軟件架構風格來推廣。SOA 最終沒有獲得成功的致命傷與當年的EJB如出一轍,盡管有 Sun Microsystems 和 IBM 等一眾巨頭在背后力挺,EJB 仍然敗于以 Spring、Hibernate 為代表的“草根框架”,可見一旦脫離人民群眾,終究會淹沒在群眾的海洋之中,連信息技術也不曾例外過。
讀到這里,你不妨回想下“如何使用多個獨立的分布式服務共同構建一個更大型系統”這個問題,再回想下“原始分布式時代”一節中 Unix DCE 提出的分布式服務的設計主旨:“讓開發人員不必關心服務是遠程還是本地,都能夠透明地調用服務或者訪問資源”。經過了三十年的技術進步,信息系統經歷了巨石、煙囪、插件、事件、SOA 等的架構模式,應用受架構復雜度的牽絆卻是越來越大,已經距離“透明”二字越來越遠了,這是否算不自覺間忘記掉了當年的初心?接下來我們所談論的微服務時代,似乎正是帶著這樣的自省式的問句而開啟的。
微服務架構(Microservices)
微服務是一種通過多個小型服務組合來構建單個應用的架構風格,這些服務圍繞業務能力而非特定的技術標準來構建。各個服務可以采用不同的編程語言,不同的數據存儲技術,運行在不同的進程之中。服務采取輕量級的通信機制和自動化的部署機制實現通信與運維。
“微服務”這個技術名詞最早在 2005 年就已經被提出,它是由 Peter Rodgers 博士在 2005 年度的云計算博覽會(Web Services Edge 2005)上首次使用,當時的說法是“Micro-Web-Service”,指的是一種專注于單一職責的、語言無關的、細粒度 Web 服務(Granular Web Services)?!拔⒎铡币辉~并不是 Peter Rodgers 直接憑空創造出來的概念,最初的微服務可以說是 SOA 發展時催生的產物,就如同 EJB 推廣過程中催生了 Spring 和 Hibernate 那樣,這一階段的微服務是作為一種 SOA 的輕量化的補救方案而被提出的。時至今日,在英文版的維基百科上,仍然將微服務定義為一種 SOA 的變種形式,所以微服務在最初階段與 SOA、Web Service 這些概念有所牽扯也完全可以理解,但現在來看,維基百科對微服務的定義已經頗有些過時了。
What is microservices
Microservices is a software development technique — a variant of the service-oriented architecture (SOA) structural style.
微服務是一種軟件開發技術,是一種 SOA 的變體形式。
—— Wikipedia,Microservices
微服務的概念提出后,在將近十年的時間里面,并沒有受到太多的追捧。如果只是對現有 SOA 架構的修修補補,確實難以喚起廣大技術人員的更多激情。不過,在這十年時間里,微服務本身也在思考蛻變。2012 年,在波蘭克拉科夫舉行的“33rd Degree Conference”大會上,Thoughtworks 首席咨詢師 James Lewis 做了題為《Microservices - Java, the Unix Way》的主題演講,其中提到了單一服務職責、康威定律、自動擴展、領域驅動設計等原則,卻只字未提 SOA,反而號召應該重拾 Unix 的設計哲學(As Well Behaved Unix Services),這點仿佛與筆者在前一節所說的“初心與自省”遙相呼應。微服務已經迫不及待地要脫離 SOA 的附庸,成為一種獨立的架構風格,也許,未來還將會是 SOA 的革命者。
微服務真正的崛起是在 2014 年,相信閱讀此文的大多數讀者,也是從 Martin Fowler 與 James Lewis 合寫的文章《Microservices: A Definition of This New Architectural Term》中首次了解到微服務的。這并不是指各位一定讀過這篇文章,應該準確地說——今天大家所了解的“微服務”是這篇文章中定義的“微服務”。在此文中,首先給出了現代微服務的概念:“微服務是一種通過多個小型服務組合來構建單個應用的架構風格,這些服務圍繞業務能力而非特定的技術標準來構建。各個服務可以采用不同的編程語言,不同的數據存儲技術,運行在不同的進程之中。服務采取輕量級的通信機制和自動化的部署機制實現通信與運維。”此外,文中列舉了微服務的九個核心的業務與技術特征,下面將其一一列出并解讀。
圍繞業務能力構建(Organized around Business Capability)。這里再次強調了康威定律的重要性,有怎樣結構、規模、能力的團隊,就會產生出對應結構、規模、能力的產品。這個結論不是某個團隊、某個公司遇到的巧合,而是必然的演化結果。如果本應該歸屬同一個產品內的功能被劃分在不同團隊中,必然會產生大量的跨團隊溝通協作,跨越團隊邊界無論在管理、溝通、工作安排上都有更高昂的成本,高效的團隊自然會針對其進行改進,當團隊、產品磨合調節穩定之后,團隊與產品就會擁有一致的結構。
分散治理(Decentralized Governance)。這是要表達“誰家孩子誰來管”的意思,服務對應的開發團隊有直接對服務運行質量負責的責任,也應該有著不受外界干預地掌控服務各個方面的權力,譬如選擇與其他服務異構的技術來實現自己的服務。這一點在真正實踐時多少存有寬松的處理余地,大多數公司都不會在某一個服務使用 Java,另一個用 Python,下一個用 Golang,而是通常會有統一的主流語言,乃至統一的技術?;驅S械募夹g平臺。微服務不提倡也并不反對這種“統一”,只要負責提供和維護基礎技術棧的團隊,有被各方依賴的覺悟,要有“經常被凌晨 3 點的鬧鐘吵醒”的心理準備就好。微服務更加強調的是確實有必要技術異構時,應能夠有選擇“不統一”的權利,譬如不應該強迫 Node.js 去開發報表頁面,要做人工智能訓練模型時,應該可以選擇 Python,等等。
通過服務來實現獨立自治的組件(Componentization via Services)。之所以強調通過“服務”(Service)而不是“類庫”(Library)來構建組件,是因為類庫在編譯期靜態鏈接到程序中,通過本地調用來提供功能,而服務是進程外組件,通過遠程調用來提供功能。前面的文章里我們已經分析過,盡管遠程服務有更高昂的調用成本,但這是為組件帶來隔離與自治能力的必要代價。
產品化思維(Products not Projects)。避免把軟件研發視作要去完成某種功能,而是視作一種持續改進、提升的過程。譬如,不應該把運維只看作運維團隊的事,把開發只看作開發團隊的事,團隊應該為軟件產品的整個生命周期負責,開發者不僅應該知道軟件如何開發,還應該知道它如何運作,用戶如何反饋,乃至售后支持工作是怎樣進行的。注意,這里服務的用戶不一定是最終用戶,也可能是消費這個服務的另外一個服務。以前在單體架構下,程序的規模決定了無法讓全部人員都關注完整的產品,組織中會有開發、運維、支持等細致的分工的成員,各人只關注于自己的一塊工作,但在微服務下,要求開發團隊中每個人都具有產品化思維,關心整個產品的全部方面是具有可行性的。
數據去中心化(Decentralized Data Management)。微服務明確地提倡數據應該按領域分散管理、更新、維護、存儲,在單體服務中,一個系統的各個功能模塊通常會使用同一個數據庫,誠然中心化的存儲天生就更容易避免一致性問題,但是,同一個數據實體在不同服務的視角里,它的抽象形態往往也是不同的。譬如,Bookstore 應用中的書本,在銷售領域中關注的是價格,在倉儲領域中關注的庫存數量,在商品展示領域中關注的是書籍的介紹信息,如果作為中心化的存儲,所有領域都必須修改和映射到同一個實體之中,這便使得不同的服務很可能會互相產生影響而喪失掉獨立性。盡管在分布式中要處理好一致性的問題也相當困難,很多時候都沒法使用傳統的事務處理來保證,但是兩害相權取其輕,有一些必要的代價仍是值得付出的。
強終端弱管道(Smart Endpoint and Dumb Pipe)。弱管道(Dumb Pipe)幾乎算是直接指名道姓地反對 SOAP 和 ESB 的那一堆復雜的通信機制。ESB 可以處理消息的編碼加工、業務規則轉換等;BPM 可以集中編排企業業務服務;SOAP 有幾十個 WS-*協議族在處理事務、一致性、認證授權等一系列工作,這些構筑在通信管道上的功能也許對某個系統中的某一部分服務是有必要的,但對于另外更多的服務則是強加進來的負擔。如果服務需要上面的額外通信能力,就應該在服務自己的 Endpoint 上解決,而不是在通信管道上一攬子處理。微服務提倡類似于經典 UNIX 過濾器那樣簡單直接的通信方式,RESTful 風格的通信在微服務中會是更加合適的選擇。
容錯性設計(Design for Failure)。不再虛幻地追求服務永遠穩定,而是接受服務總會出錯的現實,要求在微服務的設計中,有自動的機制對其依賴的服務能夠進行快速故障檢測,在持續出錯的時候進行隔離,在服務恢復的時候重新聯通。所以“斷路器”這類設施,對實際生產環境的微服務來說并不是可選的外圍組件,而是一個必須的支撐點,如果沒有容錯性的設計,系統很容易就會被因為一兩個服務的崩潰所帶來的雪崩效應淹沒??煽肯到y完全可能由會出錯的服務組成,這是微服務最大的價值所在,也是這部開源文檔標題“鳳凰架構”的含義。
演進式設計(Evolutionary Design)。容錯性設計承認服務會出錯,演進式設計則是承認服務會被報廢淘汰。一個設計良好的服務,應該是能夠報廢的,而不是期望得到長存永生。假如系統中出現不可更改、無可替代的服務,這并不能說明這個服務是多么的優秀、多么的重要,反而是一種系統設計上脆弱的表現,微服務所追求的獨立、自治,也是反對這種脆弱性的表現。
基礎設施自動化(Infrastructure Automation)?;A設施自動化,如 CI/CD 的長足發展,顯著減少了構建、發布、運維工作的復雜性。由于微服務下運維的對象比起單體架構要有數量級的增長,使用微服務的團隊更加依賴于基礎設施的自動化,人工是很難支撐成百上千乃至成千上萬級別的服務的。
《Microservices》一文中對微服務特征的描寫已經相當具體了,文中除了定義微服務是什么,還專門申明了微服務不是什么——微服務不是 SOA 的變體或衍生品,應該明確地與 SOA 劃清了界線,不再貼上任何 SOA 的標簽。如此,微服務的概念才算是一種真正豐滿、獨立的架構風格,為它在未來的幾年時間里如明星一般閃耀崛起于技術舞臺鋪下了理論基礎。
Microservices and SOA
由于與 SOA 具有一致的表現形式,這讓微服務的支持者更加迫切地拒絕再被打上 SOA 的標簽,盡管有一些人堅持認為微服務就是 SOA 的一種變體形式,也許從面向服務方面這個方面來說是對的,但無論如何,SOA 與微服務都是兩種不同的東西,正因如此,使用一個別的名稱來簡明地定義這種架構風格就顯得更有必要。
—— Martin Fowler / James Lewis,Microservices
從以上微服務的定義和特征中,你應該可以明顯地感覺到微服務追求的是更加自由的架構風格,摒棄了幾乎所有 SOA 里可以拋棄的約束和規定,提倡以“實踐標準”代替“規范標準”??墒?#xff0c;如果沒有了統一的規范和約束,以前 SOA 所解決的那些分布式服務的問題,不也就一下子都重新出現了嗎?的確如此,服務的注冊發現、跟蹤治理、負載均衡、故障隔離、認證授權、伸縮擴展、傳輸通信、事務處理,等等,這些問題,在微服務中不再會有統一的解決方案,即使只討論 Java 范圍內會使用到的微服務,光一個服務間遠程調用問題,可以列入解決方案的候選清單的就有:RMI(Sun/Oracle)、Thrift(Facebook)、Dubbo(阿里巴巴)、gRPC(Google)、Motan2(新浪)、Finagle(Twitter)、brpc(百度)、Arvo(Hadoop)、JSON-RPC、REST,等等;光一個服務發現問題,可以選擇的就有:Eureka(Netflix)、Consul(HashiCorp)、Nacos(阿里巴巴)、ZooKeeper(Apache)、Etcd(CoreOS)、CoreDNS(CNCF),等等。其他領域的情況也是與此類似,總之,完全是八仙過海,各顯神通的局面。
微服務所帶來的自由是一把雙刃開鋒的寶劍,當軟件架構者拿起這把寶劍,一刃指向 SOA 定下的復雜技術標準,將選擇的權力奪回的同一時刻,另外一刃也正朝向著自己映出冷冷的寒光。微服務時代中,軟件研發本身的復雜度應該說是有所降低。一個簡單服務,并不見得就會同時面臨分布式中所有的問題,也就沒有必要背上 SOA 那百寶袋般沉重的技術包袱。
需要解決什么問題,就引入什么工具;團隊熟悉什么技術,就使用什么框架。此外,像 Spring Cloud 這樣的膠水式的全家桶工具集,通過一致的接口、聲明和配置,進一步屏蔽了源自于具體工具、框架的復雜性,降低了在不同工具、框架之間切換的成本,所以,作為一個普通的服務開發者,作為一個“螺絲釘”式的程序員,微服務架構是友善的。可是,微服務對架構者是滿滿的惡意,對架構能力要求已提升到史無前例的程度,筆者在這部文檔的多處反復強調過,技術架構者的第一職責就是做決策權衡,有利有弊才需要決策,有取有舍才需要權衡,如果架構者本身的知識面不足以覆蓋所需要決策的內容,不清楚其中利弊,恐怕也就無可避免地陷入選擇困難癥的困境之中。
微服務時代充滿著自由的氣息,微服務時代充斥著迷茫的選擇。軟件架構不會止步于自由,微服務仍不是架構探索終點,如果有下一個時代,筆者希望是信息系統能同時擁有微服務的自由權利,圍繞業務能力構建自己的服務而不受技術規范管束,但同時又不必以承擔自行解決分布式的問題的責任為代價。管他什么利弊權衡!小孩子才做選擇題,成年人全部都要!
本文由機械工業出版社授權發布。
購買周志明博士最新力作《鳳凰架構》,可以在下圖掃碼或者直接通過查看原文跳轉,祝閱讀愉快!
? 往期推薦:
性能,10點系統性思考
每秒 10W 次高并發訂單業務,該怎么實現?
網飛人才特色:談錢,是對員工最好的尊重
架構師必須知道的架構設計原理
用領域驅動設計實現訂單業務的重構
? ?……
技術瑣話?
以分布式設計、架構、體系思想為基礎,兼論研發相關的點點滴滴,不限于代碼、質量體系和研發管理。
總結
以上是生活随笔為你收集整理的周志明论架构之道:从SOA时代到微服务时代的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深入理解java虚拟机 (周志明)JVM
- 下一篇: 《深入理解JAVA虚拟机》周志明 第三版