Go chassis是一個go語言微服務開發框架
java
經過這篇文章中,我將從設計思路到源碼剖析來深度分析Go Chassis。而且介紹本身在實踐過程當中的go語言性能調優和最佳實踐,最後將使用go chassis編寫一個http服務,此爲上篇,將主要介紹go chassis的運行機制mysql
項目地址:github.com/go-chassis/…git
go依然是一門新興的語言,和java比它還很是年輕,不過隨着kubenetes和docker等項目的成功,能夠說go語言已經成爲了很是好的中間層開發語言,而且逐漸流行起來。github
編譯速度快,支持多平臺,內存佔用低,輕量級協程等。算法
他的協程設計下降了開發者門檻,讓更多人能夠輕鬆地編寫支持高併發的後臺服務sql
當你要解決微服務模式帶來的新問題的時候你要實現多少代碼來處理分佈式帶來的複雜度?docker
我相信一個成熟的開發框架須要2萬行以上的代碼。而go chassis正是這樣一個框架編程
- go chassis集成了不少的功能,提供了一站式服務,可以讓用戶在一個方案中,得到路由管理,註冊發現,負載均衡,限流,指標監控,分佈式追蹤等大量功能。緩存
- go chassis是一個協議中立的開發框架,它不只支持http,也支持rpc協議,甚至能夠集成mysql等中間件的協議。並將它們歸入統一的治理。bash
- go chasis支持Istio控制面板,也就是說你能夠將它與envoy進行混合使用,但只須要使用istio便可,它支持原生的istio配置管理。以此使服務吞吐提高,CPU佔用下降。
- go chassis是插件化設計,支持用戶開發定製模塊,並接入到框架中
主要有如下幾點:
● 插件化註冊中心: 默認支持Service Center,kubernetes,istio
● 動態治理框架: 經過此框架,開發者可實現進程運行時配置熱加載
● 插件化協議: 開發者可實現本身的RPC協議,默認實現了 http 和highway(RPC)
● 熔斷降級: 支持根據超時,併發,錯誤率等進行服務的熔斷
● 容錯:支持重試次數等配置,並支持backoff退讓重試,
● 路由管理: 可根據流量權重和Header匹配等配置規則,輕鬆實現金絲雀發佈
● 客戶端負載均衡: 支持定製策略
● 限流: 支持客戶端和服務端限流
● 插件化Cipher: 支持開發者自定義加解密工具,並應用於AKSK和TLS 證書
● 處理鏈: 可支持在通訊的過程當中加入定製的業務邏輯
● Metrics: 支持自動導出Prometheus格式的運行時監控數據
● Tracing: 使用opentracing,支持用戶快速對接不一樣分佈式追蹤系統
● Logger: 日誌工具支持擴展並下沉到不一樣存儲中
● 治理: 可經過動態治理框架,在運行時熱加載,熔斷,負載均衡,路由等配置信息
● 最大的靈活性和擴展性
協議是容許開發者靈活擴展的,在通訊管道中任意的插入本身的特殊業務邏輯。
● 易用性
開發者能夠用最小化的配置和代碼來啓動框架,而且框架內部提供友好的API供用戶使用,每一個模塊甚至能夠拆開使用,功能任意剪裁。
● 服務可治理
提供客戶端負載均衡,熔斷降級,容錯,限流,路由管理等功能使分佈式系統可治理,同時提供錯誤注入功能,來提早模擬分佈式系統中的錯誤,以使本身的系統更增強壯。
● 服務可視化
微服務運行時產生的監控數據可以導出到監控系統,使數據可視化。
● 運行時配置熱加載
分佈式環境中,存在大量進程,若是由於更改配置就要發佈新的軟件包,會有必定成本,若是登錄到機器上去改配置再重啓,更是費時費力。go chassis提供動態配置框架來幫開發者解決配置熱加載問題。這也是服務動態治理的基礎。
以下圖所示:
● 架構思路
● 編程接口:擁有RPC和Rest 2種編程模型
● 運行模型:使用Handler Chain與Invocation概念統一了不一樣協議
● 傳輸層:一個進程擁有多種協議。同協議可運行多個協議服務實例,運行在不一樣端口,使用端口進行API隔離
● Handler chain可任意插入業務邏輯
● Http服務可支持自動掛載 Promethues數據到指定的API路徑。
● 日誌可支持擴展,好比輸出到kafka等服務中
● 請求處理過程
不一樣協議請求進入到對應的Server,Server將具體的協議請求轉換爲Invocation統一抽象模型,並傳入Handler chain,在這裏Chassis已經默認實現了不少的Handler,好比熔斷,限流,路由管理,客戶端負載均衡,Metrics收集,分佈式追蹤,錯誤注入等,因爲handler根據統一模型Invocation進行處理,沒必要每一個協議開發出來都本身開發一套治理。處理鏈可經過配置任意剪裁。最終再進入Transport handler,使用目標微服務的協議客戶端傳輸到目標。
這裏提到的幾個關鍵對象在後面會詳細介紹。
● 處理鏈與Invocation
這個概念是從Java chassis引入的, 框架的編程接口層、運行模型層和傳輸層就是經過這個對象進行解耦,它是多協議支持的基礎。能夠參考它的代碼:
Invocation爲一個結構體,它將各個協議的內容抽象了,運行不一樣協議的request都可以統一對應到一次Invocation中,好比request的Payload,以及框架的治理相關信息。
● Handler
Handler是微服務在運行過程當中在框架層面裏的一個最小處理單元。go chassis經過handler和handler的組裝實現組件化的運行模型架構。其基本的使用方式就是實現接口、註冊邏輯:
2. 開發者實現該接口後可經過API註冊進框架
● Handler Chain
用於加載一系列Handler並處理消息,目前支持負載均衡,路由管理,監控等功能,用戶能夠經過配置文件定義加載多種handler。請求調用時,會按照配置文件中的定義的順序進入handler進行處理
Handler的設計能夠保證每個handler都能獲得後面的handler的執行結果。好比:熔斷和網絡穿的功能就在chain當中,每當傳輸失敗,都會被熔斷拿到錯誤結果,並計算,當達到必定閾值,便會出發熔斷。
● Invoker
因爲RPC和Http的編程風格不一樣,go chassis使用2種不一樣的Invoker來解決調用,不管哪一種Invoker都會初始化一個Invocation並最終進入處理鏈中進行處理,最終進入各協議的Client實現並傳輸到目標服務中,這一切對用戶都是透明的。
RPC
爲了下降用戶學習成本,使用了go語言標準庫中net/rpc的調用風格
Http
爲了下降用戶學習成本,支持了go語言通用的http調用方式,容許用戶任意操控原生http request 與 response,而且沒有任何限制
接下來,用一個微服務調用過程當中最基本的Consumer到Provider的業務請求流程來看一下前面的那些關鍵對象是如何協同工做的.
● 客戶端發送請求
● 服務端接收請求
go的動態能力相對有限,go 1.8提供了插件能力,可是會給build帶來複雜度,咱們先來看看Java怎麼解決插件化的
Class<?> act = Class.forName("com.bla.TestActivity");複製代碼
基於這個能力也出現了Spring這樣的項目,開發者能夠輕鬆地解決插件化的問題
但是go語言該怎麼作呢?
下面以Go chassis的實踐爲例
提供接口與Map定義
開發者須要實現接口,並實現NewFunc返回具體實現
註冊插件
經過調用API進行插件安裝
使用插件
考慮到易用性貼近Spring的風格,chassis使用yaml格式的配置文件來管理插件。
如下爲實現思路
啓動和初始化機制以下:
支持的插件
chassis框架支持如下插件,具體請參考gitbook文檔https://go-chassis.readthedocs.io/en/latest/。
客戶端負載均衡器負責使用本地的註冊中心緩存來進行服務發現。
go chassis 封裝了不少的高級特性
爲了能讓用戶輕鬆地製造系統混亂,在Consumer側,實現了錯誤注入機制,能夠根據配置定義錯誤或者故意製造調用延遲,來測試分佈式系統遇到問題時的容錯能力,一樣支持運行時動態加載配置。目前只支持簡單的錯誤和延遲以及發生百分比
開發者甚至能夠經過此接口爲一個協議安裝錯誤注入插件,可徹底替代目前的錯誤注入實現
go micro架構:
圖片來自go micro官網https://micro.mu/docs/images/go-micro.png
這裏我引用micro.mu的關於go micro與go kit對比
Go micro是一個插件化RPC分佈式開發框架,能夠開箱即用,也能夠任意定製本身的RPC協議中的每一個模塊。他是一個eco system,如今已經有大量的插件實現,並在go-micro基礎之上有了不少的新框架,Micro組織下有許多圍繞go-micro創建的子項目。
Go kit是一個用來構建微服務的的工具包,每一個包都是獨立的,開發者本身選擇須要的工具組裝本身的微服務,包含了豐富的治理功能,熔斷,監控,限流等,且擁有豐富的插件化協議和註冊中心。
Go chassis是插件化框架,與Go micro的不一樣在於,go chassis提供的能力是插件化協議,你能夠將http或RPC,甚至是Mysql,Redis等協議接入到框架中,而且提供一站式功能,將熔斷,限流,監控等功能所有集成到框架中,開發者無需本身尋找這些方案。擁有3者中最豐富的治理功能。一樣擁有開放的定製能力,可是做爲一個新的框架,生態尚需完善。
開發者能夠經過開發體驗和特性支持對框架進行選型。