Seata RPC 模块的重构之路
作者 | 張乘輝
 來源|阿里巴巴云原生公眾號(hào)
RPC 模塊是我最初研究 Seata 源碼開始的地方,因此我對(duì) Seata 的 RPC 模塊有過一些深刻研究,在我研究了一番后,發(fā)現(xiàn) RPC 模塊中的代碼需要進(jìn)行優(yōu)化,使得代碼更加優(yōu)雅,交互邏輯更加清晰易懂,本著 “讓天下沒有難懂的 RPC 通信代碼” 的初衷,我開始了 RPC 模塊的重構(gòu)之路。
這里建議想要深入了解 Seata 交互細(xì)節(jié)的,不妨從 RPC 模塊的源碼入手,RPC 模塊相當(dāng)于 Seata 的中樞,Seata 所有的交互邏輯在 RPC 模塊中表現(xiàn)得淋漓盡致。
這次 RPC 模塊的重構(gòu)將會(huì)使得 Seata 的中樞變得更加健壯和易于解讀。
重構(gòu)繼承關(guān)系
在 Seata 的舊版本中,RPC 模塊的整體結(jié)構(gòu)有點(diǎn)混亂,尤其是在各個(gè)類的繼承關(guān)系上,主要體現(xiàn)在:
針對(duì)上面發(fā)現(xiàn)的問題,在重構(gòu)過程中我大致做了如下事情:
在最新的 RPC 模塊中的繼承關(guān)系簡(jiǎn)單清晰,用如下類關(guān)系圖表示:
同時(shí)將客戶端和服務(wù)端的引導(dǎo)類邏輯抽象出來,如下類關(guān)系圖表示:
解耦處理邏輯
解耦處理邏輯即是將 RPC 交互的處理邏輯從 Netty Handler 中抽離出來,并將處理邏輯抽象成一個(gè)個(gè) Processor,為什么要這么做呢?我大致講下現(xiàn)在存在的一些問題:
在將處理邏輯從 Netty Handler 進(jìn)行抽離之前,我們先梳理一下 Seata 現(xiàn)有的交互邏輯。
- RM 客戶端請(qǐng)求服務(wù)端的交互邏輯:
- TM 客戶端請(qǐng)求服務(wù)端的交互邏輯:
- 服務(wù)端請(qǐng)求 RM 客戶端的交互邏輯:
從以上的交互圖中可以清晰地看到了 Seata 的交互邏輯。
客戶端總共接收服務(wù)端的消息:
1)服務(wù)端請(qǐng)求消息
- BranchCommitRequest、BranchRollbackRequest、UndoLogDeleteRequest
2)服務(wù)端響應(yīng)消息
- RegisterRMResponse、BranchRegisterResponse、BranchReportResponse、GlobalLockQueryResponse
- RegisterTMResponse、GlobalBeginResponse、GlobalCommitResponse、GlobalRollbackResponse、GlobalStatusResponse、GlobalReportResponse
- HeartbeatMessage(PONG)
服務(wù)端總共接收客戶端的消息:
1)客戶端請(qǐng)求消息
- RegisterRMRequest、BranchRegisterRequest、BranchReportRequest、GlobalLockQueryRequest
- RegisterTMRequest、GlobalBeginRequest、GlobalCommitRequest、GlobalRollbackRequest、GlobalStatusRequest、GlobalReportRequest
- HeartbeatMessage(PING)
2)客戶端響應(yīng)消息
- BranchCommitResponse、BranchRollbackResponse
基于以上的交互邏輯分析,我們可以將處理消息的邏輯抽象成若干個(gè) Processor,一個(gè) Processor 可以處理一個(gè)或者多個(gè)消息類型的消息,只需在 Seata 啟動(dòng)時(shí)注冊(cè)將消息類型注冊(cè)到 ProcessorTable 中即可,形成一個(gè)映射關(guān)系,這樣就可以根據(jù)消息類型調(diào)用對(duì)應(yīng)的 Processor 對(duì)消息進(jìn)行處理,用如下圖表示:
在抽象 Remoting 類中定一個(gè) processMessage 方法,方法邏輯是根據(jù)消息類型從 ProcessorTable 中拿到消息類型對(duì)應(yīng)的 Processor。
這樣就成功將處理邏輯從 Netty Handler 中徹底抽離出來了,Handler#channelRead 方法只需要調(diào)用 processMessage 方法即可,且還可以靈活根據(jù)消息類型動(dòng)態(tài)注冊(cè) Processor 到 ProcessorTable 中,處理邏輯的可擴(kuò)展性得到了極大的提升。
以下是 Processor 的調(diào)用流程:
1)客戶端
- RmBranchCommitProcessor:處理服務(wù)端全局提交請(qǐng)求。
- RmBranchRollbackProcessor:處理服務(wù)端全局回滾請(qǐng)求。
- RmUndoLogProcessor:處理服務(wù)端 undo log 刪除請(qǐng)求。
- ClientOnResponseProcessor:客戶端處理服務(wù)端響應(yīng)請(qǐng)求,如:BranchRegisterResponse、GlobalBeginResponse、GlobalCommitResponse 等。
- ClientHeartbeatProcessor:處理服務(wù)端心跳響應(yīng)。
2)服務(wù)端
- RegRmProcessor:處理 RM 客戶端注冊(cè)請(qǐng)求。
- RegTmProcessor:處理 TM 客戶端注冊(cè)請(qǐng)求。
- ServerOnRequestProcessor:處理客戶端相關(guān)請(qǐng)求,如:BranchRegisterRequest、GlobalBeginRequest、GlobalLockQueryRequest 等。
- ServerOnResponseProcessor:處理客戶端相關(guān)響應(yīng),如:BranchCommitResponse、BranchRollbackResponse 等。
- ServerHeartbeatProcessor:處理客戶端心跳響應(yīng)。
下面我以 TM 發(fā)起全局事務(wù)提交請(qǐng)求為例子,讓大家感受下 Processor 在整個(gè)交互中所處的位置:
重構(gòu)請(qǐng)求方法
在 Seata 的舊版本當(dāng)中,RPC 的請(qǐng)求方法也是欠缺優(yōu)雅,主要體現(xiàn)在:
針對(duì)以上舊版本 RPC 請(qǐng)求方法的各種缺點(diǎn),我作了以下改動(dòng):
最終,Seata RPC 的請(qǐng)求方法終于看起來更加優(yōu)雅且有層次感了。
同步請(qǐng)求:
異步請(qǐng)求:
其它
最終 RPC 模塊看起來是這樣的:
更多詳情可訪問?Seata?官網(wǎng)進(jìn)行了解。
總結(jié)
以上是生活随笔為你收集整理的Seata RPC 模块的重构之路的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 亲历者说 | 完整记录一年多考拉海购的云
- 下一篇: 深度 | 阿里云蒋江伟:什么是真正的云原
