Go 微服務(wù)開(kāi)發(fā)框架?DMicro?的設(shè)計(jì)思路
DMicro?源碼地址:
GitHub:?https://github.com/osgochina/dmicro
Gitee:?https://gitee.com/osgochina/dmicro
背景
DMicro?誕生的背景,是因?yàn)槲覍?xiě)了 10 來(lái)年的 PHP,想在公司內(nèi)部推廣?Go, 公司內(nèi)部的組件及 rpc 協(xié)議都是基于?swoole?定制化開(kāi)發(fā)的。調(diào)研了市面上的各種框架,包括?beego,goframe,gin,go-micro,go-zero,erpc?等等,可能是我當(dāng)時(shí)技術(shù)能力有限,并不能讓這些框架很好的適配我們的業(yè)務(wù)。
我們業(yè)務(wù)開(kāi)發(fā)有幾個(gè)痛點(diǎn),在當(dāng)時(shí)?golang?的生態(tài)中無(wú)法找到一整套解決方案。
微服務(wù)應(yīng)用和單體應(yīng)用同時(shí)開(kāi)發(fā)。
高性能,高可用的網(wǎng)絡(luò)通訊。
需要自定義應(yīng)用層的協(xié)議 (重點(diǎn))。
需要靈活的插件擴(kuò)展機(jī)制,方便適配現(xiàn)有系統(tǒng) (重點(diǎn))。
服務(wù)端與客戶端的概念模糊,互相都能使用相同的 api 調(diào)用對(duì)方。
支持 Push 消息。
連接 / 會(huì)話管理。
高效率的開(kāi)發(fā),支持通過(guò) proto 生成代碼。
支持多種網(wǎng)絡(luò)協(xié)議,tcp,websocket,quic,unixsocket.
兼容 http 協(xié)議。
能夠更快速的定位問(wèn)題。
更便捷的增加新特性。
在對(duì)常用的開(kāi)源框架做了簡(jiǎn)單的調(diào)研以后,發(fā)現(xiàn)并沒(méi)有一款合適的框架能滿足我的所有需求。在認(rèn)真思考過(guò)后,發(fā)現(xiàn)?erpc?和?goframe?兩個(gè)框架的結(jié)合體能滿足我的需求,于是就誕生了自研?DMicro.
概述
DMicro?中的?drpc?組件的思想是參考?erpc?實(shí)現(xiàn),甚至可以說(shuō)是它的繼承者。
drpc?組件是?DMicro?框架的一部分,為了適配?DMicro?框架,在?erpc?的基礎(chǔ)上做了深入的擴(kuò)展開(kāi)發(fā)。
整個(gè)?DMicro?大量使用?goframe?中的組件,如果業(yè)務(wù)使用?goframe?框架,可以無(wú)縫接入。
DRpc?特性列表:
對(duì)等通信?,?對(duì)等Api
高性能?,?非阻塞異步IO
自定義Proto,,?兼容http協(xié)議?,?自定義Codec
Hook點(diǎn)?,?插件系統(tǒng)?,
Push消息?,session管理,Socket抽象?,
斷線重連?,?過(guò)載保護(hù)?,?負(fù)載均衡?,?心跳機(jī)制?,
平滑重啟?...
DServer?特性列表:
快速構(gòu)建?,?平滑重啟?,?多進(jìn)程支持?,?單/多進(jìn)程一致
預(yù)定義命令行?,ctrl命令管理服務(wù)
可觀測(cè)?,?可控制?,?應(yīng)用沙盒
DMicro?已經(jīng)內(nèi)置組件:
[x]?Registry?服務(wù)注冊(cè)
[x]?Selector?服務(wù)發(fā)現(xiàn)
[x]?Eventbus?事件總線
[x]?Supervisor?進(jìn)程管理
[ ]?Code gen?代碼生成
[ ]?Tracing?鏈路追蹤
[ ]?Metrics?統(tǒng)計(jì)告警
[ ]?Broker?限流熔斷
[ ]?OpenAPI?文檔自動(dòng)生成
架構(gòu)
設(shè)計(jì)理念
對(duì)?DMicro?框架的設(shè)計(jì),從設(shè)計(jì)之初就是在追求靈活性,適應(yīng)性。在保證微服務(wù)的穩(wěn)定性前提下,追求項(xiàng)目的開(kāi)發(fā)效率。
面向接口設(shè)計(jì),保證代碼穩(wěn)定,提供靈活定制。
抽象各組件的接口,高內(nèi)聚,低耦合。
分層設(shè)計(jì),自上而下逐層封裝,利于穩(wěn)定和維護(hù)。
高性能,高可用,低消耗。
對(duì)開(kāi)發(fā)友好,封裝復(fù)雜度。
提供豐富的組件及功能,讓開(kāi)發(fā)專(zhuān)注業(yè)務(wù)。
無(wú)數(shù)個(gè)寫(xiě)?DMicro?的日夜,我都謹(jǐn)記開(kāi)發(fā)三原則:
Clarity(清晰)
Simplicity(簡(jiǎn)單)
Productivity(生產(chǎn)力)
無(wú)論工作,還是做開(kāi)源項(xiàng)目,都應(yīng)該保持這三個(gè)原則,養(yǎng)成良好的習(xí)慣。
面向接口設(shè)計(jì)
DMicro?秉承著萬(wàn)物皆接口的原則,提供框架無(wú)與倫比的擴(kuò)展性.
下圖展示的是消息的發(fā)送的流轉(zhuǎn)流程,可以看到,所有的功能點(diǎn)都被抽象成了接口,每個(gè)功能點(diǎn)都提供了不同的實(shí)現(xiàn).
會(huì)話 Session
大多數(shù)的?Rpc?框架并不強(qiáng)調(diào)會(huì)話 (session) 的概念,因其應(yīng)用場(chǎng)景不需要用到會(huì)話 (session). 那么?drpc?為什么需要抽象出會(huì)話 (session) 呢?
Endpoint?融合了?Client?和?Server, 需要提供相同的?Api.
服務(wù)端需要主動(dòng)向客戶端發(fā)送消息,并且獲取客戶端的響應(yīng).
服務(wù)端支持對(duì)多個(gè)客戶端批量發(fā)送消息.
異步主動(dòng)斷開(kāi)一個(gè)或多個(gè)會(huì)話.
獲取會(huì)話底層的文件描述符?, 對(duì)其進(jìn)行性能調(diào)優(yōu).
可以為每個(gè)會(huì)話綁定特殊的數(shù)據(jù)/屬性.
Session?抽象了整個(gè)?drpc?框架的會(huì)話,把?Socket,Message,Context?都融合到一起。開(kāi)發(fā)者只需要對(duì)?session?進(jìn)行操作,就能實(shí)現(xiàn)大多數(shù)需求.
獲取連接信息
控制連接的生命周期 (超時(shí)時(shí)間)
控制單次請(qǐng)求的生命周期 (超時(shí)時(shí)間)
接收消息
發(fā)送消息
創(chuàng)建消息的上下文
綁定會(huì)話的相關(guān)信息 (如用戶信息)
斷線重連
主動(dòng)斷開(kāi)會(huì)話.
健康檢查
獲取連接關(guān)閉事件
為會(huì)話設(shè)置單獨(dú)的 id
Session?接口可以細(xì)分為 4 個(gè)?interface{}, 分別是?EarlySession,BaseSession,CtxSession,Session. 對(duì)應(yīng)的是應(yīng)用的不同生命階段會(huì)話 (Session) 擁有的不同屬性.
EarlySession?表示剛生成會(huì)話,尚未啟動(dòng) goroutine 讀取數(shù)據(jù)的階段.
BaseSession?只有最基礎(chǔ)的方法,用于關(guān)閉連接時(shí)候的插件參數(shù).
CtxSession?在處理程序上下文中傳遞的會(huì)話對(duì)象.
Session?全功能的會(huì)話對(duì)象.
正常情況下,開(kāi)發(fā)者用到的都是?Session,CtxSession?這兩個(gè)接口,其他 2 個(gè)接口是在插件中使用.
消息?Message
消息?Message?包含消息頭?Header, 消息體?Body, 是客戶端與服務(wù)端之間通信的實(shí)體.
Message interface{}?抽象了對(duì)通信實(shí)體的操作.
Size?消息的長(zhǎng)度
Transfer-Filter-Pipeline?報(bào)文數(shù)據(jù)過(guò)濾處理管道
Seq?序列號(hào)
MType?消息類(lèi)型
ServiceMethod?資源標(biāo)識(shí)符
Meta?消息的元數(shù)據(jù)
BodyCodec?消息體編碼格式
Body?消息體
協(xié)議 Proto
協(xié)議是對(duì)消息Message?對(duì)象的序列化和反向序列化,框架提供?Proto?接口。只需要實(shí)現(xiàn)該接口,開(kāi)發(fā)者就能定制符合業(yè)務(wù)需求的自定義協(xié)議,從而提升了框架的靈活性.
接口的定義如下:
?
type Proto interface { Version() (byte, string) Pack(Message) error Unpack(Message) error}
?
Version()?返回該協(xié)議的 id 和名字,兩個(gè)組成唯一的版本號(hào).
Pack?對(duì)消息?Message?對(duì)象進(jìn)行序列化.
Unpack?對(duì)字節(jié)流反序列化,生成一個(gè)消息?Message?對(duì)象.
目前框架已支持?Http,Json,Raw,Protobuf,JsonRpc?這 5 個(gè)協(xié)議.
RAW?協(xié)議組成如下:
其他協(xié)議可以參考代碼.
編碼 Codec
作為一個(gè)通用性的框架,支持的協(xié)議可以有多種,消息體的編解碼也可以有多少種.?drpc?使用?Codec?接口對(duì)消息體 Body 進(jìn)行編解碼.
接口的定義如下:
?
type Codec interface { ID() byte Name() string Marshal(interface{}) ([]byte, error) Unmarshal([]byte, interface{}) error }
?
ID?返回編 Codec 的 id
Name?返回編 Codec 的名字,名字是為了開(kāi)發(fā)者更容易識(shí)別.
Marshal?對(duì)消息內(nèi)容進(jìn)行編碼
Unmarshal?對(duì)消息內(nèi)容進(jìn)行解碼
目前框架已支持?Form,Json,plain,Protobuf,XML?這 5 個(gè)編解碼.
連接 Socket
Socket?擴(kuò)展了?net.Conn, 并且抽象出接口,方便框架對(duì)底層網(wǎng)絡(luò)協(xié)議的集成.
Socket?接口實(shí)現(xiàn)了一部分?Session?接口的功能,Session?接口調(diào)用的一些方法,實(shí)際上是轉(zhuǎn)發(fā)調(diào)用了?Socket?中的方法.
這樣的分層實(shí)現(xiàn),讓?Socket?擁有的集成其他協(xié)議的能力.
TCP V4,TCP V6
Unix Socket
KCP
QUIC
支持對(duì)連接的性能調(diào)優(yōu).
SetKeepAlive?開(kāi)啟鏈接?;?/p>
SetKeepAlivePeriod?鏈接保活間隔時(shí)間
SetReadBuffer?設(shè)置鏈接讀緩沖區(qū) size
SetWriteBuffer?獲取鏈接寫(xiě)緩沖區(qū) size
SetNoDelay?開(kāi)啟關(guān)閉 no delay 算法
ControlFD?支持操作鏈接的原始句柄
有機(jī)的組合
前面講到,DMicro?框架萬(wàn)物皆接口,分層 + 接口的設(shè)計(jì),讓?DMicro?有了靈活的組成高效且符合業(yè)務(wù)實(shí)際情況的能力.
接下來(lái)我們要講到實(shí)現(xiàn)這些能力的基礎(chǔ)。插件系統(tǒng).
插件 Plugin
插件系統(tǒng)給框架帶來(lái)了極大的擴(kuò)展性和靈活性,是整個(gè)框架的一個(gè)靈魂模塊,有了它,框架就有了無(wú)限可能。
什么樣的插件系統(tǒng)才能算是優(yōu)雅呢?我能想到的有以下幾點(diǎn):
合理且豐富的?hook?位置,能夠覆蓋整個(gè)框架的生命周期,貫穿通訊的各個(gè)環(huán)節(jié)。
每個(gè)?hook?位置的入?yún)⒑统鰠⒍际墙?jīng)過(guò)精心設(shè)計(jì)。
每個(gè)插件都能夠使用多個(gè)?hook?位置,每個(gè)?hook?位置都能被多個(gè)插件使用。
設(shè)計(jì)的足夠簡(jiǎn)潔,優(yōu)雅。能方便的進(jìn)行二次開(kāi)發(fā)定制。
在?drpc?中,鉤子貫穿與整個(gè)?Endpoint?的生命周期,是它不可或缺的重要一環(huán)。
?通過(guò)這些鉤子 Hook?點(diǎn),賦予了插件無(wú)限可能.
組件
有了插件,就能通過(guò)插件的組合,編寫(xiě)綜合功能的組件,目前框架提供一些內(nèi)置的組件,
服務(wù)端 Rpc Server
客戶端 Rpc Client
服務(wù)注冊(cè) Registry
服務(wù)發(fā)現(xiàn) Selector
事件總線 EventBus
進(jìn)程管理 Supervisor
即將提供:
鏈路追蹤 Tracing
統(tǒng)計(jì)告警 Metrics
限流熔斷 Broker.
限于篇幅的原因,具體組件的實(shí)現(xiàn),這里就不深入講解,請(qǐng)關(guān)注后續(xù)的文章.
未來(lái)展望
如果把?DMicro?比作人生,現(xiàn)在成長(zhǎng)的階段還處在少年時(shí)期,只完成了基礎(chǔ)的架構(gòu)設(shè)計(jì)和一部分組件的開(kāi)發(fā).
接下來(lái)的方向主要是往易用性和可靠性方向發(fā)展.
易用性:
項(xiàng)目效能工具?dmctl?工具的開(kāi)發(fā),包括代碼生成,項(xiàng)目結(jié)構(gòu)生成,打包,編譯等等功能.
符合 openapi 定義的文檔組件的開(kāi)發(fā).
更加完善的文檔和使用示例.
可靠性:
可觀測(cè)性
鏈路追蹤
指標(biāo)信息
日志流
生產(chǎn)可用
測(cè)試用例的完善
代碼覆蓋率
性能調(diào)優(yōu)
希望?DMicro?能在大家的呵護(hù)及鞭策下茁長(zhǎng)成長(zhǎng).
開(kāi)源不易,需要更多小伙伴加入,共創(chuàng)?DMicro. 如果你希望使用?DMicro, 趕快引入代碼,搭建你的第一個(gè)新項(xiàng)目吧!如果你也想為?DMicro?生態(tài)添磚加瓦,趕快?Fork?代碼,給我們提交?pr?吧!
評(píng)論