本人在 Gopher 大會進行了分享,在分享後將核心內容寫了下來,供參考。git
華爲在 2016 年成立 Cloud BU,引入了 kubernetes,prometheus 等 CNCF 項目。這些軟件大部分有 Go 語言編寫,研發團隊天然開始引入 Go 語言構建雲服務,然而那時 Go 的生態並不完善,因此要本身從頭至尾編寫基礎能力模塊,以供不一樣雲應用引入。github
首先從一個簡單雲應用展開看他的實現過程
一個簡單的註冊發現服務 Service Center,和 eureka 同樣,這裏很少贅述他的職責。golang
動靜分離
爲了減小數據信息量,抽出公共部分統一進行管理,經過靜態信息來劃分實例歸屬。因此微服務與微服務實例爲 1 對n 的映射,將微服務名,版本,描述等信息都抽到了公共部分,經過下降冗餘度,來減小網絡的開銷,這樣好比「描述「這樣的信息就不在網絡中傳遞,同時又能兼顧微服務管理能力,規範化了微服務模型。好比一個微服務必須具有版本信息。而真正下發到微服務緩存中的實例信息就少多了,許多字段是給人類看到,並不是機器執行所須要的。算法
從圖中咱們看到微服務靜態信息裏面包含了一個 Schemas,裏面關聯了微服務所關聯的契約文檔,一樣是 1 對 n 的映射關係。能夠經過手動上傳或者代碼自動生成文檔上傳,能夠在註冊中心中查看微服務文檔,且文檔與微服務的版本號綁定,一旦上傳就不容許更改。那麼爲什麼要保證文檔先行?chrome
錯誤的方式:客戶端開發團隊等待後端的服務編寫完成後,才能開始進行集成開發。docker
正確的方式:以文檔爲基準,客戶端與服務端同時開發,客戶端經過 mock 以去除對服務端的依賴。apache
另外,若是文檔不及時審視,那麼將會出現很是糟糕的狀況。好比不一致的命名規範,定義類似的 API,擴展能力差,任何一點都會大大增長研發成本。及早審視並規避是十分重要的。這就是爲什麼註冊中心加入文檔上傳與查詢能力。編程
服務間依賴管理
調用層級太高將引發定位困難,以及性能降低。合理的層級是 3 個服務 a->b->c 的調用就能夠完成一次調用。bootstrap
彼此互相依賴的兩個服務在功能升級或者變動時要花費更可能是時間來分析影響,好比 ab 互相依賴,一個新功能涉及 2 個都要更改,那怎麼一塊兒上線?後端
此外簡單的依賴有助於系統測試和分析。這給架構師一個很好的審視方式,能夠及時看到微服務間的依賴關係,對架構進行調整。
緩存機制
Service Center 內部自己是不存持久化數據的,一旦 etcd 出現網絡故障的時候,就會致使Service Center 不可用。然而etcd 須要 3 個不一樣機房才能作到高可用,好比節點 2,2,1 分佈在 3 個數據中心,這成本顯然是很大的。
咱們就要用軟手段來規避,獲取必定的可靠性。因此Service Center 引入了異步緩存機制,在啓動之初Service Center 會與 etcd 創建一個長鏈接,也就是 watch。每次 watch 的時候爲了防止創建 watch 時間窗發生變化,作了一層保護,在 watch 以前作了全量的查詢。在運行過程當中查詢所獲得的資源變化會緩存到 Service Center 本地,而後進行異步的循環,這樣不只低成本的提高了可用性,也提高了性能。
Consul的實現實際上是計算存儲一體,而非分離,我認爲業務體量沒上去前,這樣的架構對運維的成本很低,是個很好的選擇,然而他是否能支撐較大的微服務體量,是要畫個問號的,因此我執着於計算與存儲分離並踐行,同時service center支持內置etcd,也就是說也支持計算存儲一體在初期幫助你減小管理成本。
總結:咱們經過了多種手段來提高微服務研發效率,減小網絡開銷,並經過異步緩存提高性能和可靠性,這是咱們在這個服務上積累下來的能力。使得註冊發現這個組件對技術管理者變得更加友好,能夠幫助架構師持續改進並管理架構。然而云應用遠遠不止交付業務功能這麼簡單。
咱們剛纔看到的只是水面之上的冰山,而冰山之下還隱藏着大量的基礎能力須要編寫。先讓咱們來展開 Service center 的架構看看
雲服務 service center
該組件主要負責微服務的註冊發現,提供 restful API 。
他有四個主要的模塊:
服務註冊發現:經過註冊發現完成服務拓撲的感知
契約發現:每一個服務具有一個契約記錄,支持多種格式如 Open API,gRPC proto
RBAC:基於角色的訪問控制,管理員能夠管理帳號,將帳號分發給微服務或者不一樣人員
服務治理:針對微服務下發治理規則,好比重試,限流,熔斷,路由策略等。
交付一個雲服務遠遠不止交付業務功能,而是要去全方面的考慮安全,韌性,隱私,可運維等能力,固然咱們將部分的能力能夠交給一些中間件來完成,好比網關。然而仍有大量功能須要本身編寫,且能夠複用在每一個微服務中,這就是基礎能力庫編寫的初衷。
配額管理:雲資源按照租戶進行配額管理,租戶所能使用的資源受到嚴格限制
告警:當微服務發生關鍵問題時要直接上報告警系統,而非經過雲服務設置閾值等告警策略
安全:加解密證書,密碼
ID 生成:ID 的生成算法,用於生成微服務 ID,實例 ID 等
多種中間件:調用過程須要被審計,調用鏈追蹤,生成指標監控等
項目地址https://github.com/apache/servicecomb-service-center
對於這些能力,抽取普通的庫函數也是徹底不夠用的,混合雲,公有云,開源項目,因此要作到以下能力:
可插拔:也就是按需在編譯期引入(受限於 go 語言能力),例如配額系統的具體實如今社區是不須要的
異構系統:也就是一個功能要有多種具體實現,好比審計,公有云存在一套審計系統須要對接,而社區則是本地日誌打印。
不一樣的算法:解密工具,ID 生成器,面對不一樣的交付場景或者是安全要求,都要經過不一樣實現來替換算法。好比 ID 生成能夠是 snowflake,UUID。加解密算法使用- AES 或者其餘公開算法。你也能夠考慮閉源核心算法,而後寫個簡單算法做爲新插件並連同整個項目開源出去,以讓社區幫助完善周邊能力,而保護本身的商業版本競爭力
Go chassis 開發框架
咱們該如何面對
可插拔:按需在編譯期引入
異構服務:一個後臺服務可能有多種具體實現。
不一樣的算法:解密工具,ID 生成器,面對不一樣的交付場景或者是安全要求,都要經過不一樣實現來替換算法。
分佈系統難以治理:框架能夠幫助知足雲原生應用,如何實現這樣的框架
爲了可以面對需求的多樣性,而且全部新規劃的組件也能受益,快速進行開發,咱們須要統一的框架和標準來加速開發,這就是開發框架 Go chassis 誕生的過程。
從圖中咱們能夠看到業務邏輯就是用戶本身編寫的業務代碼,那麼框架自己就是協議層,中間層和插件套件 3 部分,管理部分就是雲服務,框架開發出來的應用能夠無感知的對接上去使用這些雲能力。好比:
註冊發現插件能夠對接 service center 與 kubenetes
配額管理插件能夠對接雲服務的配額管理服務
中間件好比指標監控對接到 prometheus
那麼咱們如何經過這個框架來加速咱們的開發呢。
手段 1:將後端服務做爲插件使用
常見的後端
配額管理
認證鑑權服務
對象存儲服務
雲原生的其中一個要素是,把後端服務看成附加資源。如何界定什麼被做爲後端服務對待,就是那些不禁本身組織開發並運維,從應用運行時到基礎設施不可見、serverless的API server,對你來講爲黑盒子的服務。
當咱們調用這些後端服務時,其實他們並不在微服務的治理體系內,考慮到可測試性(好比 mock 測試)以及可替換性(業務可以連續,且隨時更換更好的服務,應對變換的需求等),咱們須要將他們插件化,以靈活的進行選擇替換或者去除。
開發你的插件並安裝到框架中就能夠經過配置的方式拉起並調用。
手段 2:沉澱需求基線
在咱們提供任何一種服務前,咱們都須要知足基本的要求,好比:
請求體必須作大小限制
API 必須限流
密碼不能明文存儲
訪問進行認證鑑權
無單點故障
訪問審計
運維能力
那麼咱們首先要將運行時的調用標準化,由於不一樣部門可能有私有協議訴求,那麼服務治理就交給核心框架完成。協議由業務部門決定自主研發或是集成現有協議。當你發現公司內部不一樣部門都在開發本身的協議作本身的服務治理時,再向將業務統一一個架構,一個工具鏈上,將很是困難。
咱們經過 Invocation 模型將不經過協議歸一上去,這樣就能夠在統一的處理鏈中進行處理。
處理鏈的設計比較相似 AOP 的思想,也就是在業務處理的先後加入代碼邏輯進行特殊處理,好比:審計用戶操做,收集請求指標數據。
ResponseCallBack 用於接受後置 handler 返回的結果,因此每個 handler 處理時均可以按需定義本身的 ResponseCallBack 來獲取後面 handler 甚至是業務邏輯代碼的執行結果。幫助通用邏輯(即中間件)和業務邏輯完全解耦。
能夠看下如今已經支持的中間件,不管限流,熔斷,負載均衡,認證鑑權,審計,咱們都用此機制實現:將公司所有的工具鏈,服務治理手段,安全合規等都落入處處理鏈中,可快速加快研發速度,並統一規範,減小管理負擔。
框架內部提供了命令式調用能力,好比指標收集就是這樣的典型能力也提供了聲明式使用方式,好比流量管理,基於流量特徵的限流能力聲明式使用也支持金絲雀發佈
插件能力全景圖:
能夠看到目前已經支持了很多的生態,並對多種後端系統提供了抽象接口幫助應用快速開發。
那麼經過這樣的框架,咱們可讓業務團隊專一於業務代碼開發,而無需理解後端的複雜性,和其餘非功能需求。收益以下
對於龐大的系統能夠進行 mock 測試,提高交付質量
應對不一樣的交付場景
保證後端可替換性
研發職責界面分離
從架構或者業務演進的角度來思考,所採用的後端所使用的技術是在快速演進的,咱們須要經過後端服務的快速替換來確保系統和產品能夠及時演進,因此重點要考慮接口的設計。可替換性的重要性大於可重用性。這也知足程序設計原則的依賴倒置當咱們再開發一個新的微服務時,僅僅須要實現他的業務邏輯便可
手段 3:配置治理
可直接參考https://github.com/go-chassis/go-archaius,後面我會專門出文章來說這塊,Shopee在這裏已經實踐的很是好了。
手段 4:易處理
意思是說它們能夠瞬間開啓或中止。這裏咱們不會談到快速的開始,由於 go 語言+docker 運行時與容器平臺就能處理這樣的一個場景,咱們談談面向意外的處理。
這個 protocol server 一般表明一個協議,也能夠是某種編程模型,好比 http,編程模型如beego,gin這有個框架的配置樣例,意思是在一個微服務進程中拉起了 2 個http 端口和 grpc 端口服務
在收到系統信號後,就會遍歷的中止每一個 server
另外由社區開發者貢獻的自定義優雅停機功能,能夠容許用戶劫持信號和停機處理過程,也能夠在先後自定義處理過程。
手段 5:輕量級內核
基本上依賴就只有必要的 prometheus,opentracing,jwt,k8s client,go-restful 相關的庫。註冊發現也是可插拔的。
多種能力都在另外一個倉庫中提供,是一系列的擴展插件。好比 grpc 協議,kubernetes 註冊中心等,均可以按需引入。名字參照的chrome-extension。
咱們可以打造如此輕量的內核得益於三板斧,這也是go chassis幾個核心概念:
中間件:handler chain處理請求
bootstrap:任意替換默認實現和執行邏輯
插件化:後端和實現任意替換。
擁有本身從新制造的輪子
這就是 go chassis 開發框架的名字和 logo 想要傳達的理念,chassis 是底盤。logo 是一個輪胎的形狀
咱們常常聽到有人在重複造輪子,還有人在抨擊造輪子,我相信這是因爲現有的方案開放性設計依然存在不足,每一個團隊都在項目發展期植入了太多有本身項目或者業務影子的東西,致使你們不得不重複製造適合本身的輪子。
咱們應該描述並實現一個更加抽象並定義範式,而在這個底盤之上進行能力構建。你將這個最原始的輪子引入並進行加強,打形成更加適合本身的輪子,你是要越野仍是雪地輪,均可以本身製做和調校。咱們將本身研發團隊積累的能力抽象成多種接口及插件,爲的就是不要再重複製造輪子,而是基於現有輪子從新打造,讓項目產品跑的更快,而且全部延展出的功能,原生就是兼容的。這就是對一個 go 研發團隊來講最大的效能提高。目前這個輪子我更願意稱他爲雲服務的開發輪子,很是適合咱們作雲服務的團隊使用。從後面的例子你就能夠看出來。
案例
華爲榮耀手機和智慧屏等終端的視頻通話後臺
已經上線華爲公有云,支撐終端公司暢聯通話上億註冊用戶,基於 go-chassis 和 service center 進行服務治理。
邊緣計算 kubeedge
§ 基於 go chassis 開發服務治理底座
§ 管理着全國 29 個省、自治區的將近 10 萬邊緣節點,超過 50 萬邊緣應用的部署。支撐了 1 萬多個收費站中門架信息採集業務的不斷調整、更新,知足了每日 3 億條以上的信息採集。
§ 爲往後車路協同、自動駕駛等創新業務的發展提供了良好的平臺支撐
https://github.com/kubeedge/kubeedge
Shoppe
本次Gopher大會還邀請了Shopee來說述go chassis在他們供應鏈平臺上的使用。能夠參考他們的分享
總結
1. 定義你的應用開發通訊協議一家公司,很是重要的 2 個東西企業文化與行爲規範,這是每一個公司的領導者必須優先定義的 2 個事情,這就是一種 「通訊協議」,保證公司良好的運做下去。這樣領導者就無需事必躬親。顯然定義一套通 「信協議」 是很是重要的。Go chassis 就是咱們 Go 研發團隊的通訊協議。每一個微服務都是個小團隊開發的,有多是同一個團隊,也多是不一樣團隊,咱們所作的框架是爲了定義這套通訊協議,以此來減輕研發的成本,同時兼顧擴展性,不要對開發有過渡的限制。咱們規範化了 api first 來審視 api 設計,依賴管理來審視合理的服務關係,並規定全部的能力要沉澱爲插件與中間件等等都是爲了定義研發團隊開發與治理雲服務的 「通訊協議」。
2. Go 在新基建中的做用咱們都知道,5g 的時代容許更多的設備接入,咱們看互聯網演進第一代是pc 機互聯時代,第二代是手機,第三代即是萬物互聯,而較小的設備勢必會催生新的半導體,新的操做系統(好比說華爲的鴻蒙),這樣一層層下去,勢必會須要一種新的語言及對應的框架,go 語言自己很契合這樣的一個位置,這裏我不會展開去講,由於你們也知道 go 語言自己適合的場景。而分佈式的設備也須要一種框架來進行治理,go chassis 將在這裏扮演一個比較重要的角色。他極可能成爲基礎設施領域的一個開發底座,從 kubeedge,視頻雲等項目使用 go chassis,能夠看出端倪。
歡迎你們參與社區,開源項目地址: https://github.com/go-chassis/go-chassis
看到這裏歡迎你們留言講述還須要我展開哪部分深刻分析下。若是以爲個人內容有幫助,請爲咱們的項目service center與go chassis點上一個star。
本文分享自微信公衆號 - GoCN(golangchina)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。