如何實現容器雲上的服務編排設計?
原題:《容器雲之服務編排設計》
本文作者:汪照輝 王作敬 中國銀河證券股份有限公司 信息技術部IT研發中心
引言
隨著業務部署容器化與微服務架構的採用,巨大的單體應用可能會逐步分解為多個微服務的方式來實現業務應用的改造。這樣既簡化分解了單體應用的複雜性,使每個微服務都可以獨立部署和擴展,每個微服務都可以作為獨立自治的一個模塊組件,方便的實現了敏捷開發和快速迭代部署。不過一枚硬幣總有正反面,事情都有兩面性,雖然容器雲平台和微服務架構給我們帶來了很多便利,但由於應用被拆分成很多個微服務組件,也導致需要運維管理的服務數量大幅增加,還要使用這些微服務組件編排構建業務應用系統,這也使應用服務運維管理變得複雜,壓力增加。
雖然有缺點,但優點也是很明顯。特別互聯網類應用的快速迭代要求,使我們公司也計劃採用容器雲PaaS,並邀請了一些容器雲廠商交流。交流的過程也發現對一些功能的理解差別挺大,比如多租戶,服務編排等,都宣稱支持多租戶,可此多租戶非彼多租戶,千差萬別。服務編排也是一樣。理解認識有差別,實現也就不一樣。這裡我們也想澄清一下有點混亂的服務編排和容器編排、服務和應用等概念。同時根據我們對容器雲PaaS的理解和基於ESB服務實施使用的經驗,以及對容器雲服務編排的思考,在此與大家分享容器雲服務編排的設計,拋磚引玉,以期共同學習和提高。
理論上說服務編排和容器雲沒有什麼關係,這是兩個層次的概念。但我們考慮在容器雲上實現服務編排,它們就有了關係,所以我們暫且命名為《容器雲之服務編排設計》吧。
一、服務編排和容器編排
對服務編排的理解不一樣,所以實現也就有差別。應該說每家容器雲廠商都支持服務編排,但從我們交流情況來看,對服務編排的理解還是有不少差距。首先我們需要明確區分容器編排和服務編排是兩個完全不同的概念。
服務編排我們是指不通過編程,在容器雲平台通過配置、映射等方法來實現服務間的調用,組合、部署成為一個新的服務或應用的過程。
容器編排是根據規則對容器進行調度、配置、組合、部署、回收、遷移等,以提供應用部署、維護、 擴展機制等功能。Kubernetes、Docker Swarm等就是容器編排的框架。當然通過容器編排可以來實現服務編排。比如使用Docker Compose.yml文件編排容器來實現服務編排,但有一定的局限性。
容器編排是容器編排調度框架考慮實現的功能,比如Kubernetes、Mesos、Docker Swarm需要提供對容器的編排調度。而服務編排是基於容器雲平台的基礎上,在應用服務層實現對實際應用服務的編排調用。
目前Docker的Compose.yml方式是通過yml文件編排scripts代碼來實現容器編排的方式實現服務編排,這種方式要求相關人員具備編碼能力,不過即便這樣也有很大的局限性。
二、應用和服務定義
首先我們澄清一下應用和服務在這裡的概念:
在Docker的文檔中,服務被定義為分散式應用的不同部分(In a distributed application, different pieces of the app are called 「services.」)。我們這裡,應用指業務應用,是由一系列服務通過編排而成的,完成特定業務功能的業務實體。服務是滿足特定需求的功能單元。一個業務應用由一到多個服務或業務服務編排而成,一個服務可能部署和運行多個服務實例(服務實例之間實現負載均衡)。舉例來說,我們通過Internet提供的客戶服務應用,它可能提供的客戶基本信息服務、客戶賬戶服務、客戶資產服務等。這裡的服務其實也可以看作是一個微服務(或者關聯的一個或多個操作的集合)。一個服務也可以獨立部署為應用,比如日誌服務,它可以單獨部署為日誌應用;或者跟其他服務進行編排,為其他服務提供日誌查詢服務等。
服務通過編排部署為應用或稱業務應用。其實對客戶或用戶來說,可見的是業務應用,至於說應用由多少服務編排而成,是不是服務編排而成,對終端客戶或用戶來說應該是不可見的。應該由應用編排開發或編排部署或運維人員來完成這部分工作,所以服務編排也可以看做是服務管理的一部分工作。
編排為一個應用的服務包含有一個或多個,這些服務之間是有密切關係的,通常前面服務的輸出是後面服務的輸入,也存在服務編排路徑並行或根據條件跳轉的情況(這種服務編排方式比較複雜,通常直接通過組合服務或集成服務通過編程在服務設計時來實現,不在平台層實現)。沒有關係的服務是沒有必要考慮編排的。在我們PoC測試過程中,有廠商給我們展示服務編排,拿兩個毫無關聯的服務連在一起,就告訴我們是服務編排。這個理解就有點偏差了。
三、服務編排實現方式
服務編排的方式有多種,其實就像我們的有些ESB服務,可以直接使用集成平台工具在業務處理流程中進行編排,然後打包發布為一個組合服務;或者通過API Gateway工具,實現服務編排;或者直接在服務架構設計時,定義相應的介面和配置管理方案,通過配置實現服務路由和編排等。容器雲平台可以使用Compose文件或Helm工具來支持容器編排能力,但有一定的局限性。基於我們的實踐經驗,我們推薦使用API管理工具來實現,另外提出了通過配置中心來實現服務編排的方式。
四、組合服務
簡單的說,組合服務就是把多個服務根據調用順序和條件進行組合,生成一個新的服務。組合服務通常使用工具來快速實現。比如我們在實施ESB時,服務編排通常直接通過ESB集成工具平台來實現,不同的服務可以集成在一個流程中,實現一個新的業務服務。比如TIBCO BusinessWorks工具提供了很多集成組件,可以很方便的實現服務編排(圖1)。
圖1 TIBCO BusinessWorks服務編排流程
微服務其實也可以採用這種方式,但這種方式不是很靈活,每次更新都需要重新部署。基於容器的微服務提供了一種通過Compose文件來編排服務的方式。
五、使用Docker Compose.yml文件實現
Docker平台定義了Stack對象,一個Stack是一組共享依賴關係的相關聯服務,能夠被一起編排和縮放(A stack is a group of interrelated services that share dependencies, and can be orchestrated and scaled together)。它使用Compose.yml文件來定義各個鏡像間的關係,然後一鍵部署。這種方式更多是通過容器間的編排來實現服務編排,同樣很大的局限性。這也讓我們覺得它更多是容器編排實現。
六、使用Helm工具實現
Helm是目前Kubernetes服務編排領域的開源子項目,目前好像只支持Kubernetes,是Kubernetes應用的一個包管理工具。Helm 使用一個被稱為Charts的包,一個Chart是一系列文件,描述一組相關的Kubernetes資源。單一的Chart可以被用於部署簡單的應用,比如一個緩存Pod;或者比如一個完整的Web應用,有HTTP Server、資料庫、緩存等等。
Helm通過軟體打包的形式,支持發布的版本管理和控制,很大程度上簡化了Kubernetes應用部署和管理的複雜性。Helm把Kubernetes資源(比如deployments、services或 ingress等) 打包到一個Chart中,而Chart被保存到Chart倉庫。通過Chart倉庫可用來存儲和分享Chart。Helm讓發布變得可配置,支持發布應用配置的版本管理,簡化了Kubernetes部署應用的版本控制、打包、發布、刪除、更新等操作。
圖表 2 Helm架構圖
Helm也是基於容器雲平台的組件,到目前為止仍然不成熟,也有容器雲廠商自己開發了新的組件來支持使用helm編排服務。不過Helm目前有不少公司開始關注,可能會是容器雲服務編排的一個有益嘗試。但是跟服務編排還是有差別,我們覺得稱為資源編排更合適些,雖然可以通過它實現服務編排。
七、使用傳統API管理工具實現服務編排
這是一種成熟的方式,也是我們目前推薦的實現方式。但缺點是成熟的工具都面臨著付費。目前商用的API管理和API Gateway產品也很多,Gartner提到的比較領先的比如Google APIgee、CA API Management、Axway、TIBCO Mashary、Redhat 3Scale等。這些工具通常都提供強大的API管理能力和服務編排能力以及安全認證、服務治理能力等。如我以前討論的那樣,如果採用微服務和容器雲,作為公司級的方案的話,我們覺得這是一個比較好的選擇。
八、使用服務配置中心實現服務編排
我們提供另外一個選擇,使用服務配置中心組件來實現服務編排。這也是我們一再提到服務配置中心這個組件的原因。基於服務配置中心,將可以提供很多僅僅通過配置就可以實現的能力。
這種方式對服務介面的設計有特殊的要求,我們是為了快速的通過配置部署來實現不同的業務需求,所以才採用了這種方式。
九、介面定義
為了適用不同的請求格式和應答格式,我們定義了統一的介面,把所有的請求/應答內容都以一個package body(Soap、Json或其他格式)的形式進行交互。在服務中使用工具對body中的具體請求/應答信息進行解析、過濾、轉換、計算、轉發等。這樣,我們就可以部署一個服務來接收所有的請求,然後根據配置中心應用服務的路由規則配置,分發請求到不同的服務上。比如,不同的業務請求可以使用不同的JMS Queue作為endpoint,在配置中心配置服務請求路由,也可以同時實現消息層的負載均衡,很方便的實現彈性收縮。Adapter可以看做業務應用系統或數據服務層。對不能改造的業務應用系統可以暫時以Adapter的方式集成。Adapter層同樣可以實現負載均衡和彈性伸縮能力。
圖表 3 使用配置中心實現服務編排
十、服務間調用的方式
對外介面提供SOAP over HTTP和restful的方式,兼容XML和JSON兩種格式。在服務化架構內部,消息通信我們採用JMS方式。JMS是基於Server中轉的消息交換方式,一般能達到毫秒的處理能力。如果對延遲要求比較高,可以採用端到端的消息交換方式,比如Kafka,或者商用的Solace、TIBCO FTL等,可達納秒的處理能力(特定場景)。
服務間的調用需要根據具體的業務來選擇調用方式,同步或非同步方式,或者根據需求選擇不同的transport,不同的協議。其實我們採用消息的另一個原因是它可以很方便的與其他系統集成,比如CEP複雜事件處理系統。在業務處理過程中也可以實現實時的風險控制、數據計算、統計分析等能力。
十一、拓撲支持
服務間調用可能存在一個應用中某個服務被多次循環調用的可能,我們在服務化實現中也遇到過這樣的問題。我們提供了一個介面服務,被一個業務服務調用,這個業務服務由被其他服務調用,由於所有服務必須通過這個介面服務做認證授權路由等操作,所以多次調用導致操作在高並發高負載下超時,引起連鎖反應。比如ServiceA會調用ServiceB來實現一個業務功能,要避免從ServiceA在轉發服務到GeneralService。比較好的方式是直接使用ServiceA和ServiceB組合成為一個組合服務,或者通過路由配置直接訪問ServiceB。
圖表 4 錯誤的服務調用
為避免這個問題,在服務設計實現時,需要儘可能使用原子服務來封裝業務服務,同時可以提供全鏈路拓撲支持,用可視化的方式查看服務調用關係。
圖表 5 拓撲支持
目前比如諧雲等提供了拓撲支持,對於容器雲用戶來說,將會是個有益的手段來協助管理應用服務之間的關係。
十二、原則
最後,我們想說的是:
1、 在編排服務時,盡量避免服務的循環調用,一個業務應用在實現時需要考慮從上到下整個服務調用鏈的關係,避免服務的循環調用。可以考慮採用拓撲關係圖協助,以便清晰地展示應用的服務間編排關係。
2、 服務編排調用鏈節點儘可能少。一是從性能考慮,二是從管理實現考慮。這個可能關係到業務梳理和數據梳理。具體的實現視實際情況而定。
3、 微服務在拆分時需要考慮業務領域合適的粒度,太細則會導致服務數量太多,微服務編排複雜化;太少則可能數據冗餘嚴重。
4、 服務編排是微服務實施的重要內容,微服務實施不可能一蹴而就,一步到位,可以採用分步實現、小步快跑的模式,但前提是有清晰的路線圖,知道每步做什麼,不合適時及時作出調整。
十三、寫在最後
不管什麼平台、什麼工具、什麼概念,我們覺得最重要的是理解服務編排的思想,理解SOA ESB服務編排和容器雲上服務編排有什麼差異。無論叫組合服務,或Stack,或Helm Charts等,最終都是為業務應用服務的,只要能很好的滿足自身業務應用需求,我們覺得就是一種很好的方案。就像我們說過的,學習CMM關鍵是學其思想來優化流程,而不是學其流程來固化流程。
另外感謝數人云CTO肖德時肖總的非常好的建議以及才雲杜寧總的支持!
參考文獻
1.Eric Newcomer,徐涵譯 《Understanding SOA with Web Services》
2.Docker https://docs.docker.com/get-started/part3/#about-services
3.Helm https://docs.helm.sh/
TAG:talkwithtrend |