Seata 1.5.2 源碼學習(Client端)

在上一篇中通過閱讀Seata服務端的代碼,我們瞭解到TC是如何處理來自客戶端的請求的,今天這一篇一起來了解一下客戶端是如何處理TC發過來的請求的。要想搞清楚這一點,還得從GlobalTransactionScanner說起。

啓動的時候,會調用GlobalTransactionScanner#initClient()方法,在initClient()中初始化TM和RM

TM初始化,主要是註冊各種處理器,最終構造一個處理器映射表,不再多說

HashMap<Integer/*MessageType*/, Pair<RemotingProcessor, ExecutorService>> processorTable = new HashMap<>(32);

重點關注RM初始化

RM初始化過程中,設置了 resourceManager 和 transactionMessageHandler,然後也是註冊各種處理器,最終也是構造一個消息類型和對應的處理器的一個映射關係

可以看到,圖中上半部分是RM特有的,下半部分與TM初始化註冊處理器類似

然鵝,真正處理請求的還是靠調用各個處理器中的handler.onRequest()方法,於是問題的關鍵就很明顯了,就在於handler

1.  ResourceManager

在瞭解ResourceManager之前,讓我們首先了解一下ResourceManagerInbound和ResourceManagerOutbound

ResourceManagerInbound是處理接收到TC的請求的,是TC向RM發請求

ResourceManagerOutbound是處理流出的消息的,是RM向TC發請求

ResourceManager繼承了二者,所以既負責向TC發請求,又負責接收從TC來的請求。

還記得剛纔在RMClient中是怎麼獲取ResourceManager的嗎?是調用DefaultResourceManager.get()獲取的

DefaultResourceManager.get()得到的是一個單例DefaultResourceManager,創建DefaultResourceManager的時候會構建一個分支類型與ResourceManager的一個Map

2. TransactionMessageHandler

TransactionMessageHandler負責處理接收到的RPC消息

前面在 RMClient 中通過 DefaultRMHandler.get() 獲取 TransactionMessageHandler

3. 消息處理

RMClient#init()的時候new了一個RmNettyRemotingClient

這裏要記住,rmNettyRemotingClient的兩個成員變量此時已經被賦值了:

  • resourceManager是DefaultResourceManager,
  • transactionMessageHandler是DefaultRMHandler

RmNettyRemotingClient構造方法中調用父類AbstractNettyRemotingClient的構造方法

可以看到,根據收到的RPC消息類型,從processorTable中獲取對應的Processor,最後調用對應RemotingProcessor的process()方法進行處理消息

RemotingProcessor的實現類很多,挑其中一個RmBranchCommitProcessor看一下

真相大白,最終還是調DefaultRMHandler#handle()

捋一下這個過程

最後,補充一個,this爲什麼是DefaultRMHandler

補充二:AbstractTransactionRequestToRM

4. 分支事務提交(二階段)

交給AsyncWorker去執行

可以看到:

  1. 封裝成一個Phase2Context對象,並將其放入隊列中
  2. 如果放入成功,則立即返回提交成功,後續交由定時任務執行
  3. 如果放入失敗,則主動觸發定時任務先執行一次,以便騰出空間來,待執行完後,隊列裏面就有空間了,再將任務放入隊列,等待下一次定時任務執行
  4. 定時任務1秒執行一次,執行的時候將隊列中的任務取出,然後循環遍歷分段執行
  5. 執行的過程就是刪除對應事務的undo log
  6. 如果過程中拋異常,則將任務再放回隊列中

所以,RM收到TC發的提交指令後,僅僅只是刪除該事務的undo_log表記錄

5. 分支事務回滾(二階段)

與提交類似

所以,回滾就是根據事務的undo_log進行回滾

6. 總結

1、啓動時,自動代理數據源,應用GlobalTransactionalInterceptor,初始化TM和RM

2、進入@GlobalTransactional業務方法時,TM向TC發請求申請開啓全局事務,並獲得全局事務ID

3、業務方法調用遠程服務接口完成業務處理

4、RM執行本地邏輯,註冊分支事務,獲取全局鎖,成功後提交本地事務並寫入undo_log,本地事務提交成功後向TC報告分支事務

5、TM發起全局事務提交請求,TC向所有已註冊的RM發請求,讓RM進行分支提交,刪除本地undo_log

6、若執行失敗,TM發起全局事務回滾,TC向所有RM發請求,回滾分支事務,還原數據

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章