定義Go語言云應用開發(fā)的“通信協(xié)議”
本人在?Gopher?大會進行了分享,在分享后將核心內容寫了下來,供參考。
華為在?2016?年成立?Cloud BU,引入了?kubernetes,prometheus?等?CNCF?項目。這些軟件大部分有?Go?語言編寫,研發(fā)團隊自然開始引入?Go?語言構建云服務,然而那時?Go?的生態(tài)并不完善,所以要自己從頭到尾編寫基礎能力模塊,以供不同云應用引入。
首先從一個簡單云應用展開看他的實現(xiàn)過程

一個簡單的注冊發(fā)現(xiàn)服務?Service Center,和?eureka?一樣,這里不多贅述他的職責。
動靜分離

為了減少數(shù)據(jù)信息量,抽出公共部分統(tǒng)一進行管理,通過靜態(tài)信息來劃分實例歸屬。所以微服務與微服務實例為?1?對n?的映射,將微服務名,版本,描述等信息都抽到了公共部分,通過降低冗余度,來減少網(wǎng)絡的開銷,這樣比如“描述“這樣的信息就不在網(wǎng)絡中傳遞,同時又能兼顧微服務管理能力,規(guī)范化了微服務模型。比如一個微服務必須具備版本信息。而真正下發(fā)到微服務緩存中的實例信息就少多了,許多字段是給人類看到,并非機器執(zhí)行所需要的。
從圖中我們看到微服務靜態(tài)信息里面包含了一個?Schemas,里面關聯(lián)了微服務所關聯(lián)的契約文檔,同樣是?1?對?n?的映射關系。可以通過手動上傳或者代碼自動生成文檔上傳,可以在注冊中心中查看微服務文檔,且文檔與微服務的版本號綁定,一旦上傳就不允許更改。那么為何要保證文檔先行?
?

錯誤的方式:客戶端開發(fā)團隊等待后端的服務編寫完成后,才能開始進行集成開發(fā)。
正確的方式:以文檔為基準,客戶端與服務端同時開發(fā),客戶端通過?mock?以去除對服務端的依賴。

另外,如果文檔不及時審視,那么將會出現(xiàn)非常糟糕的情況。比如不一致的命名規(guī)范,定義相似的?API,擴展能力差,任何一點都會大大增加研發(fā)成本。及早審視并規(guī)避是十分重要的。這就是為何注冊中心加入文檔上傳與查詢能力。
服務間依賴管理

調用層級過高將引起定位困難,以及性能下降。合理的層級是?3?個服務?a->b->c?的調用就可以完成一次調用。
彼此互相依賴的兩個服務在功能升級或者變更時要花費更多是時間來分析影響,比如?ab?互相依賴,一個新功能涉及?2?個都要更改,那怎么一起上線?
此外簡單的依賴有助于系統(tǒng)測試和分析。這給架構師一個很好的審視方式,可以及時看到微服務間的依賴關系,對架構進行調整。
緩存機制

?
?Service Center?內部本身是不存持久化數(shù)據(jù)的,一旦?etcd?出現(xiàn)網(wǎng)絡故障的時候,就會導致Service Center?不可用。然而etcd?需要?3?個不同機房才能做到高可用,比如節(jié)點?2,2,1?分布在?3?個數(shù)據(jù)中心,這成本顯然是很大的。
我們就要用軟手段來規(guī)避,獲取一定的可靠性。所以Service Center?引入了異步緩存機制,在啟動之初Service Center?會與?etcd?建立一個長連接,也就是?watch。每次?watch?的時候為了防止建立?watch?時間窗發(fā)生變化,做了一層保護,在?watch?之前做了全量的查詢。在運行過程中查詢所得到的資源變化會緩存到?Service Center?本地,然后進行異步的循環(huán),這樣不僅低成本的提升了可用性,也提升了性能。
Consul的實現(xiàn)其實是計算存儲一體,而非分離,我認為業(yè)務體量沒上去前,這樣的架構對運維的成本很低,是個很好的選擇,然而他是否能支撐較大的微服務體量,是要畫個問號的,所以我執(zhí)著于計算與存儲分離并踐行,同時service center支持內置etcd,也就是說也支持計算存儲一體在初期幫助你減少管理成本。

總結:我們通過了多種手段來提升微服務研發(fā)效率,減少網(wǎng)絡開銷,并通過異步緩存提升性能和可靠性,這是我們在這個服務上積累下來的能力。使得注冊發(fā)現(xiàn)這個組件對技術管理者變得更加友好,可以幫助架構師持續(xù)改進并管理架構。然而云應用遠遠不止交付業(yè)務功能這么簡單。

我們剛才看到的只是水面之上的冰山,而冰山之下還隱藏著大量的基礎能力需要編寫。先讓我們來展開?Service center?的架構看看
云服務?service center
該組件主要負責微服務的注冊發(fā)現(xiàn),提供?restful API?。
他有四個主要的模塊:
?服務注冊發(fā)現(xiàn):通過注冊發(fā)現(xiàn)完成服務拓撲的感知
契約發(fā)現(xiàn):每個服務具備一個契約記錄,支持多種格式如?Open API,gRPC proto
RBAC:基于角色的訪問控制,管理員可以管理賬號,將賬號分發(fā)給微服務或者不同人員
服務治理:針對微服務下發(fā)治理規(guī)則,比如重試,限流,熔斷,路由策略等。
交付一個云服務遠遠不止交付業(yè)務功能,而是要去全方面的考慮安全,韌性,隱私,可運維等能力,當然我們將部分的能力可以交給一些中間件來完成,比如網(wǎng)關。然而仍有大量功能需要自己編寫,且可以復用在每個微服務中,這就是基礎能力庫編寫的初衷。
配額管理:云資源按照租戶進行配額管理,租戶所能使用的資源受到嚴格限制
告警:當微服務發(fā)生關鍵問題時要直接上報告警系統(tǒng),而非通過云服務設置閾值等告警策略
安全:加解密證書,密碼
ID?生成:ID?的生成算法,用于生成微服務?ID,實例?ID?等
多種中間件:調用過程需要被審計,調用鏈追蹤,生成指標監(jiān)控等
項目地址https://github.com/apache/servicecomb-service-center
對于這些能力,抽取普通的庫函數(shù)也是完全不夠用的,混合云,公有云,開源項目,所以要做到如下能力:
可插拔:也就是按需在編譯期引入(受限于?go?語言能力),例如配額系統(tǒng)的具體實現(xiàn)在社區(qū)是不需要的
?異構系統(tǒng):也就是一個功能要有多種具體實現(xiàn),比如審計,公有云存在一套審計系統(tǒng)需要對接,而社區(qū)則是本地日志打印。
不同的算法:解密工具,ID?生成器,面對不同的交付場景或者是安全要求,都要通過不同實現(xiàn)來替換算法。比如?ID?生成可以是?snowflake,UUID。加解密算法使用- AES?或者其他公開算法。你也可以考慮閉源核心算法,然后寫個簡單算法作為新插件并連同整個項目開源出去,以讓社區(qū)幫助完善周邊能力,而保護自己的商業(yè)版本競爭力
Go chassis?開發(fā)框架

?我們該如何面對
可插拔:按需在編譯期引入
異構服務:一個后臺服務可能有多種具體實現(xiàn)。
不同的算法:解密工具,ID?生成器,面對不同的交付場景或者是安全要求,都要通過不同實現(xiàn)來替換算法。
分布系統(tǒng)難以治理:框架可以幫助滿足云原生應用,如何實現(xiàn)這樣的框架
為了能夠面對需求的多樣性,并且所有新規(guī)劃的組件也能受益,快速進行開發(fā),我們需要統(tǒng)一的框架和標準來加速開發(fā),這就是開發(fā)框架?Go chassis?誕生的過程。
從圖中我們可以看到業(yè)務邏輯就是用戶自己編寫的業(yè)務代碼,那么框架本身就是協(xié)議層,中間層和插件套件?3?部分,管理部分就是云服務,框架開發(fā)出來的應用可以無感知的對接上去使用這些云能力。比如:
注冊發(fā)現(xiàn)插件可以對接?service center?與?kubenetes
配額管理插件可以對接云服務的配額管理服務
中間件比如指標監(jiān)控對接到?prometheus
那么我們如何通過這個框架來加速我們的開發(fā)呢。
手段?1:將后端服務作為插件使用
常見的后端
配額管理
認證鑒權服務
對象存儲服務
云原生的其中一個要素是,把后端服務當作附加資源。如何界定什么被作為后端服務對待,就是那些不由自己組織開發(fā)并運維,從應用運行時到基礎設施不可見、serverless的API server,對你來說為黑盒子的服務。
當我們調用這些后端服務時,其實他們并不在微服務的治理體系內,考慮到可測試性(比如?mock?測試)以及可替換性(業(yè)務能夠連續(xù),且隨時更換更好的服務,應對變換的需求等),我們需要將他們插件化,以靈活的進行選擇替換或者去除。

開發(fā)你的插件并安裝到框架中就可以通過配置的方式拉起并調用。
手段?2:沉淀需求基線
在我們提供任何一種服務前,我們都需要滿足基本的要求,比如:
請求體必須做大小限制
?API?必須限流
密碼不能明文存儲
訪問進行認證鑒權
無單點故障
訪問審計
運維能力
那么我們首先要將運行時的調用標準化,因為不同部門可能有私有協(xié)議訴求,那么服務治理就交給核心框架完成。協(xié)議由業(yè)務部門決定自主研發(fā)或是集成現(xiàn)有協(xié)議。當你發(fā)現(xiàn)公司內部不同部門都在開發(fā)自己的協(xié)議做自己的服務治理時,再向將業(yè)務統(tǒng)一一個架構,一個工具鏈上,將非常困難。
?


我們通過?Invocation?模型將不通過協(xié)議歸一上去,這樣就可以在統(tǒng)一的處理鏈中進行處理。
處理鏈的設計比較類似?AOP?的思想,也就是在業(yè)務處理的前后加入代碼邏輯進行特殊處理,比如:審計用戶操作,收集請求指標數(shù)據(jù)。
ResponseCallBack?用于接受后置?handler?返回的結果,所以每一個?handler?處理時都可以按需定義自己的?ResponseCallBack?來獲取后面?handler?甚至是業(yè)務邏輯代碼的執(zhí)行結果。幫助通用邏輯(即中間件)和業(yè)務邏輯徹底解耦。
可以看下現(xiàn)在已經(jīng)支持的中間件,無論限流,熔斷,負載均衡,認證鑒權,審計,我們都用此機制實現(xiàn):將公司全部的工具鏈,服務治理手段,安全合規(guī)等都落入到處理鏈中,可快速加快研發(fā)速度,并統(tǒng)一規(guī)范,減少管理負擔。

框架內部提供了命令式調用能力,比如指標收集就是這樣的典型能力也提供了聲明式使用方式,比如流量管理,基于流量特征的限流能力聲明式使用也支持金絲雀發(fā)布
插件能力全景圖:
?

可以看到目前已經(jīng)支持了不少的生態(tài),并對多種后端系統(tǒng)提供了抽象接口幫助應用快速開發(fā)。
那么通過這樣的框架,我們可以讓業(yè)務團隊專注于業(yè)務代碼開發(fā),而無需理解后端的復雜性,和其他非功能需求。收益如下
對于龐大的系統(tǒng)可以進行?mock?測試,提升交付質量
應對不同的交付場景
保證后端可替換性
研發(fā)職責界面分離
從架構或者業(yè)務演進的角度來思考,所采用的后端所使用的技術是在快速演進的,我們需要通過后端服務的快速替換來確保系統(tǒng)和產(chǎn)品可以及時演進,所以重點要考慮接口的設計??商鎿Q性的重要性大于可重用性。這也滿足程序設計原則的依賴倒置當我們再開發(fā)一個新的微服務時,僅僅需要實現(xiàn)他的業(yè)務邏輯即可
手段?3:配置治理
?

可直接參考https://github.com/go-chassis/go-archaius,后面我會專門出文章來講這塊,Shopee在這里已經(jīng)實踐的非常好了。
手段?4:易處理
意思是說它們可以瞬間開啟或停止。這里我們不會談到快速的開始,因為?go?語言+docker?運行時與容器平臺就能處理這樣的一個場景,我們談談面向意外的處理。
?

這個?protocol server?通常代表一個協(xié)議,也可以是某種編程模型,比如?http,編程模型如beego,gin這有個框架的配置樣例,意思是在一個微服務進程中拉起了?2?個http?端口和?grpc?端口服務
在收到系統(tǒng)信號后,就會遍歷的停止每個?server
另外由社區(qū)開發(fā)者貢獻的自定義優(yōu)雅停機功能,可以允許用戶劫持信號和停機處理過程,也可以在前后自定義處理過程。
手段?5:輕量級內核

?基本上依賴就只有必要的?prometheus,opentracing,jwt,k8s client,go-restful?相關的庫。注冊發(fā)現(xiàn)也是可插拔的。

多種能力都在另一個倉庫中提供,是一系列的擴展插件。比如?grpc?協(xié)議,kubernetes?注冊中心等,都可以按需引入。名字參照的chrome-extension。

我們能夠打造如此輕量的內核得益于三板斧,這也是go chassis幾個核心概念:
中間件:handler chain處理請求
bootstrap:任意替換默認實現(xiàn)和執(zhí)行邏輯
插件化:后端和實現(xiàn)任意替換。
擁有自己重新制造的輪子

這就是?go chassis?開發(fā)框架的名字和?logo?想要傳達的理念,chassis?是底盤。logo?是一個輪胎的形狀
我們經(jīng)常聽到有人在重復造輪子,還有人在抨擊造輪子,我相信這是由于現(xiàn)有的方案開放性設計依然存在不足,每個團隊都在項目發(fā)展期植入了太多有自己項目或者業(yè)務影子的東西,導致大家不得不重復制造適合自己的輪子。
我們應該描述并實現(xiàn)一個更加抽象并定義范式,而在這個底盤之上進行能力構建。你將這個最原始的輪子引入并進行增強,打造成更加適合自己的輪子,你是要越野還是雪地輪,都可以自己制作和調校。我們將自己研發(fā)團隊積累的能力抽象成多種接口及插件,為的就是不要再重復制造輪子,而是基于現(xiàn)有輪子重新打造,讓項目產(chǎn)品跑的更快,并且所有延展出的功能,原生就是兼容的。這就是對一個?go?研發(fā)團隊來說最大的效能提升。目前這個輪子我更愿意稱他為云服務的開發(fā)輪子,非常適合我們做云服務的團隊使用。從后面的例子你就可以看出來。
案例
華為榮耀手機和智慧屏等終端的視頻通話后臺
已經(jīng)上線華為公有云,支撐終端公司暢聯(lián)通話上億注冊用戶,基于?go-chassis?和?service center?進行服務治理。
邊緣計算?kubeedge
§?基于?go chassis?開發(fā)服務治理底座
§??管理著全國?29?個省、自治區(qū)的將近?10?萬邊緣節(jié)點,超過?50?萬邊緣應用的部署。支撐了?1?萬多個收費站中門架信息采集業(yè)務的不斷調整、更新,滿足了每日?3?億條以上的信息采集。
§?為日后車路協(xié)同、自動駕駛等創(chuàng)新業(yè)務的發(fā)展提供了良好的平臺支撐?
https://github.com/kubeedge/kubeedge
Shoppe
本次Gopher大會還邀請了Shopee來講述go chassis在他們供應鏈平臺上的使用??梢詤⒖妓麄兊姆窒?br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">
總結
1.???定義你的應用開發(fā)通信協(xié)議一家公司,非常重要的?2?個東西企業(yè)文化與行為規(guī)范,這是每個公司的領導者必須優(yōu)先定義的?2?個事情,這就是一種?“通信協(xié)議”,保證公司良好的運作下去。這樣領導者就無需事必躬親。顯然定義一套通?“信協(xié)議”?是非常重要的。Go chassis?就是我們?Go?研發(fā)團隊的通信協(xié)議。每個微服務都是個小團隊開發(fā)的,有可能是同一個團隊,也可能是不同團隊,我們所做的框架是為了定義這套通信協(xié)議,以此來減輕研發(fā)的成本,同時兼顧擴展性,不要對開發(fā)有過渡的限制。我們規(guī)范化了?api first?來審視?api?設計,依賴管理來審視合理的服務關系,并規(guī)定所有的能力要沉淀為插件與中間件等等都是為了定義研發(fā)團隊開發(fā)與治理云服務的?“通信協(xié)議”。
2.????Go?在新基建中的作用我們都知道,5g?的時代允許更多的設備接入,我們看互聯(lián)網(wǎng)演進第一代是pc?機互聯(lián)時代,第二代是手機,第三代便是萬物互聯(lián),而較小的設備勢必會催生新的半導體,新的操作系統(tǒng)(比如說華為的鴻蒙),這樣一層層下去,勢必會需要一種新的語言及對應的框架,go?語言本身很契合這樣的一個位置,這里我不會展開去講,因為大家也知道?go?語言本身適合的場景。而分布式的設備也需要一種框架來進行治理,go chassis?將在這里扮演一個比較重要的角色。他很可能成為基礎設施領域的一個開發(fā)底座,從?kubeedge,視頻云等項目使用?go chassis,可以看出端倪。
歡迎大家參與社區(qū),開源項目地址:?https://github.com/go-chassis/go-chassis
?看到這里歡迎大家留言講述還需要我展開哪部分深入分析下。如果覺得我的內容有幫助,請為我們的項目service center與go chassis點上一個star。
