Go 微服務(wù)開發(fā)框架DMicro設(shè)計(jì)思路詳解
背景
DMicro
誕生的背景,是因?yàn)槲覍懥?10 來(lái)年的 PHP,想在公司內(nèi)部推廣 Go
, 公司內(nèi)部的組件及 rpc 協(xié)議都是基于 swoole
定制化開發(fā)的。調(diào)研了市面上的各種框架,包括 beego
,goframe
,gin
,go-micro
,go-zero
,erpc
等等,可能是我當(dāng)時(shí)技術(shù)能力有限,并不能讓這些框架很好的適配我們的業(yè)務(wù)。
我們業(yè)務(wù)開發(fā)有幾個(gè)痛點(diǎn),在當(dāng)時(shí) golang
的生態(tài)中無(wú)法找到一整套解決方案。
- 微服務(wù)應(yīng)用和單體應(yīng)用同時(shí)開發(fā)。
- 高性能,高可用的網(wǎng)絡(luò)通訊。
- 需要自定義應(yīng)用層的協(xié)議 (重點(diǎn))。
- 需要靈活的插件擴(kuò)展機(jī)制,方便適配現(xiàn)有系統(tǒng) (重點(diǎn))。
- 服務(wù)端與客戶端的概念模糊,互相都能使用相同的 api 調(diào)用對(duì)方。
- 支持 Push 消息。
- 連接 / 會(huì)話管理。
- 高效率的開發(fā),支持通過 proto 生成代碼。
- 支持多種網(wǎng)絡(luò)協(xié)議,
tcp
,websocket
,quic
,unixsocket
. - 兼容 http 協(xié)議。
- 能夠更快速的定位問題。
- 更便捷的增加新特性。
在對(duì)常用的開源框架做了簡(jiǎn)單的調(diào)研以后,發(fā)現(xiàn)并沒有一款合適的框架能滿足我的所有需求。在認(rèn)真思考過后,發(fā)現(xiàn) erpc
和 goframe
兩個(gè)框架的結(jié)合體能滿足我的需求,于是就誕生了自研 DMicro
.
概述
DMicro
中的 drpc
組件的思想是參考 erpc
實(shí)現(xiàn),甚至可以說是它的繼承者。
drpc
組件是 DMicro
框架的一部分,為了適配 DMicro
框架,在 erpc
的基礎(chǔ)上做了深入的擴(kuò)展開發(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抽象 ,
- 斷線重連 , 過載保護(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)目的開發(fā)效率。
- 面向接口設(shè)計(jì),保證代碼穩(wěn)定,提供靈活定制。
- 抽象各組件的接口,高內(nèi)聚,低耦合。
- 分層設(shè)計(jì),自上而下逐層封裝,利于穩(wěn)定和維護(hù)。
- 高性能,高可用,低消耗。
- 對(duì)開發(fā)友好,封裝復(fù)雜度。
- 提供豐富的組件及功能,讓開發(fā)專注業(yè)務(wù)。
無(wú)數(shù)個(gè)寫 DMicro
的日夜,我都謹(jǐn)記開發(fā)三原則:
Clarity(清晰)
Simplicity(簡(jiǎn)單)
Productivity(生產(chǎn)力)
無(wú)論工作,還是做開源項(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)斷開一個(gè)或多個(gè)會(huì)話.
- 獲取會(huì)話底層的文件描述符 , 對(duì)其進(jìn)行性能調(diào)優(yōu).
- 可以為每個(gè)會(huì)話綁定特殊的數(shù)據(jù)/屬性.
Session
抽象了整個(gè) drpc
框架的會(huì)話,把 Socket
,Message
,Context
都融合到一起。開發(fā)者只需要對(duì) session
進(jìn)行操作,就能實(shí)現(xiàn)大多數(shù)需求.
- 獲取連接信息
- 控制連接的生命周期 (超時(shí)時(shí)間)
- 控制單次請(qǐng)求的生命周期 (超時(shí)時(shí)間)
- 接收消息
- 發(fā)送消息
- 創(chuàng)建消息的上下文
- 綁定會(huì)話的相關(guān)信息 (如用戶信息)
- 斷線重連
- 主動(dòng)斷開會(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ì)象.
正常情況下,開發(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ù)過濾處理管道Seq
序列號(hào)MType
消息類型ServiceMethod
資源標(biāo)識(shí)符Meta
消息的元數(shù)據(jù)BodyCodec
消息體編碼格式Body
消息體
協(xié)議 Proto
協(xié)議是對(duì)消息Message
對(duì)象的序列化和反向序列化,框架提供 Proto
接口。只需要實(shí)現(xiàn)該接口,開發(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 的 idName
返回編 Codec 的名字,名字是為了開發(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
開啟鏈接?;?/li>SetKeepAlivePeriod
鏈接?;铋g隔時(shí)間SetReadBuffer
設(shè)置鏈接讀緩沖區(qū) sizeSetWriteBuffer
獲取鏈接寫緩沖區(qū) sizeSetNoDelay
開啟關(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)過精心設(shè)計(jì)。 - 每個(gè)插件都能夠使用多個(gè)
hook
位置,每個(gè)hook
位置都能被多個(gè)插件使用。 - 設(shè)計(jì)的足夠簡(jiǎn)潔,優(yōu)雅。能方便的進(jìn)行二次開發(fā)定制。
在 drpc
中,鉤子貫穿與整個(gè) Endpoint
的生命周期,是它不可或缺的重要一環(huán)。
通過這些鉤子 Hook
點(diǎn),賦予了插件無(wú)限可能.
組件
有了插件,就能通過插件的組合,編寫綜合功能的組件,目前框架提供一些內(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ì)和一部分組件的開發(fā).
接下來(lái)的方向主要是往易用性和可靠性方向發(fā)展.
易用性:
- 項(xiàng)目效能工具
dmctl
工具的開發(fā),包括代碼生成,項(xiàng)目結(jié)構(gòu)生成,打包,編譯等等功能. - 符合 openapi 定義的文檔組件的開發(fā).
- 更加完善的文檔和使用示例.
可靠性:
可觀測(cè)性
- 鏈路追蹤
- 指標(biāo)信息
- 日志流
生產(chǎn)可用
- 測(cè)試用例的完善
- 代碼覆蓋率
- 性能調(diào)優(yōu)
希望 DMicro
能在大家的呵護(hù)及鞭策下茁長(zhǎng)成長(zhǎng).
開源不易,需要更多小伙伴加入,共創(chuàng) DMicro
. 如果你希望使用 DMicro
, 趕快引入代碼,搭建你的第一個(gè)新項(xiàng)目吧!如果你也想為 DMicro
生態(tài)添磚加瓦,趕快 Fork
代碼,給我們提交 pr
吧!
以上就是Go 微服務(wù)開發(fā)框架DMicro設(shè)計(jì)思路詳解的詳細(xì)內(nèi)容,更多關(guān)于Go 微服務(wù)開發(fā)框架DMicro的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Golang使用singleflight解決并發(fā)重復(fù)請(qǐng)求
高并發(fā)的場(chǎng)景下,經(jīng)常會(huì)出現(xiàn)并發(fā)重復(fù)請(qǐng)求資源的情況,singleflight是golang內(nèi)置的一個(gè)包,這個(gè)包提供了對(duì)重復(fù)函數(shù)調(diào)用的抑制功能,所以下面我們就來(lái)看看如何使用它解決并發(fā)重復(fù)請(qǐng)求吧2023-08-08golang對(duì)etcd存取和數(shù)值監(jiān)測(cè)的實(shí)現(xiàn)
這篇文章主要介紹了golang對(duì)etcd存取和數(shù)值監(jiān)測(cè)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09golang gin 框架 異步同步 goroutine 并發(fā)操作
這篇文章主要介紹了golang gin 框架 異步同步 goroutine 并發(fā)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2020-12-12解決GO編譯時(shí)避免引入外部動(dòng)態(tài)庫(kù)的問題
最近碰到一個(gè)問題,有一個(gè)流量采集的組件中使用到了github.com/google/gopacket 這個(gè)庫(kù),這個(gè)庫(kù)使用一切正常,但是唯獨(dú)有一個(gè)缺點(diǎn),編譯后的二進(jìn)制文件依賴于libpcap.so的動(dòng)態(tài)庫(kù),這篇文章主要介紹了GO編譯時(shí)避免引入外部動(dòng)態(tài)庫(kù)的解決方法,需要的朋友可以參考下2022-10-10解決Golang在Web開發(fā)時(shí)前端莫名出現(xiàn)的空白換行
最近在使用Go語(yǔ)言開發(fā)Web時(shí),在前端莫名出現(xiàn)了空白換行,找了網(wǎng)上的一些資料終于找到了解決方法,現(xiàn)在分享給大家,有需要的可以參考。2016-08-08