一、proxy配置(ratis自帶例子 - counter)

ratis proxy利用構(gòu)建者模式 - Builder構(gòu)建proxy實例,如圖65~ 68行,分別設(shè)置proxy服務(wù)的分組、配置信息、節(jié)點信息、狀態(tài)機。
分組信息封裝于:RaftGroup 對象中,包含對應(yīng)的分組標(biāo)識符 -?RaftGroupId 、構(gòu)成分組節(jié)點集。
配置信息封裝于:RaftProperties對象中,采用K-V模式將配置ratis需要的配置信息傳遞給Bulider構(gòu)建器。
節(jié)點信息封裝于:RaftPeerId對象中,包含當(dāng)前節(jié)點的組內(nèi)唯一命名。
狀態(tài)機信息:StateMachine具體實現(xiàn)實例,是當(dāng)前分組業(yè)務(wù)處邏輯處理的具體實現(xiàn)類,也是被分離在raft協(xié)議之外的具體業(yè)務(wù)實現(xiàn)邏輯。
二、proxy靜態(tài)模型

如圖2.1所示,RaftServerProxy 實現(xiàn)了接口 RaftServer,即proxy就是一個raft服務(wù)。
同時 proxy包含了九個主要屬性,proxy所有功能都是依賴于這九個屬性實現(xiàn)的。
????1、stateMachineRegistry:StateMachine.Regisstry - 狀態(tài)機注冊服務(wù)
? ? ? ? registry是proxy對所有狀態(tài)機的管理服務(wù),但是直到ratis - 2.3.0版本,該注冊服務(wù)都是名不副實。registr只是簡單實現(xiàn)了Function的一個接口定義。具體實體類在RaftServer接口中采用了lambda表達式(gid ->stateMachine)作為其實現(xiàn)類。沒有起到其狀態(tài)機注冊器的作用,應(yīng)為該注冊器始終只有一個狀態(tài)機被注冊。具體代碼可見?RaftServer$Builder#setStateMachine方法。
? ? 2、properties:RaftProperties - RaftServer配置項
? ? ? ? 簡單的K-V模式的封裝對象,對Ratis具體配置項的封裝。為Raft服務(wù)的運行提供系統(tǒng)、應(yīng)用層面的變量。Ratis服務(wù)通過簡單的 key 獲取配置的value,決定具體的運行方式。配置項詳情見RaftServerConfigKeys類(包含了配置項及其默認(rèn)值)
? ? 3、liftCycle:LifeCycle - RaftServer生命周期狀態(tài)機
? ? ? ? RaftServer生命周期狀態(tài)機,是對RaftServer整體狀態(tài)的控制器。包含了對RaftServer狀態(tài)規(guī)則信息變更、運行期間服務(wù)狀態(tài)的獲取判定的等操作。
? ? ? ? 其中狀態(tài)的變更必須符合以下規(guī)則

其規(guī)則控制就在LifeCycle中。
? ? 4、peerSupplier:Supplier<RaftPeer> - Raft節(jié)點協(xié)議通信封裝實體
? ? ? ? peer是對RaftServer當(dāng)前節(jié)點的通信必要信息的封裝。包含:唯一名稱、三組協(xié)議通信地址的包裝。為客戶端請求提供通信地址信息。
? ? ? ? 同時peer實例化通過MemoizedSupplier包裹,MemoizedSupplier是Supperlier的一個具體實現(xiàn)類,實現(xiàn)了對Supperlier執(zhí)行結(jié)果單例緩存通過proxy final的修飾實現(xiàn)peer屬性的不可變性。
? ? 5、implExecutor:ExecutorService -? 線程池(異步任務(wù)執(zhí)行器)
? ? ? ? implExecutor單獨針對RaftServer執(zhí)行動態(tài)添加節(jié)點或者動態(tài)添加分組操作的執(zhí)行線程池。將RaftServer寫類型的管理與業(yè)務(wù)邏輯分離開。
? ? ? ? implExecutor采用Executors.newSingleThreadExecutor()工具構(gòu)建一個只包含單個線程、無限工作隊列的線程池。
? ? ? ? 主要包含兩個操作:
? ? ? ? 1、節(jié)點的動態(tài)添加 -?org.apache.ratis.server.impl.RaftServerProxy.ImplMap#addNew
? ? ? ? ?2、異步動態(tài)添加分組 -?org.apache.ratis.server.impl.RaftServerProxy#groupAddAsync
? ? 6、executor:ExecutorService? - 具體業(yè)務(wù)邏輯執(zhí)行線程池
? ? ? ? executor通過配置項
? ? ? ? ? ? 1、raft.server.threadpool.proxy.cached - 是否采用緩存線程池【默認(rèn)值為:true】
? ? ? ? ? ? 2、raft.server.threadpool.proxy.size - 線程池最大線程數(shù)【默認(rèn)值為:0】
? ? ? ? ? ? 通過這個兩個配置項,構(gòu)建具體的業(yè)務(wù)邏輯處理線程池,配置項對應(yīng)關(guān)系如下圖

? ? 7、serverRpc:RaftServerRpc - reft服務(wù)底層通信組件
????????serverRpc是對RaftServer的底層通信組件,包含三種協(xié)議的RPC的具體實現(xiàn)邏輯。涉及到Raft節(jié)點的底層通信,這里不想洗介紹。??
? ? 8、impls:ImplMap - raft代理服務(wù)具體代理對象
? ? ? ? impls就是對proxy具體代理對象的封裝,通過一個CucurrentHashMap對象注冊分組和具體的Raft服務(wù)。為后期具體的業(yè)務(wù)邏輯提供指定分組的具體服務(wù)對象。proxy在處理客戶端請求時,通過請求中包含的分組信息選擇具體的服務(wù)處理請求。這也決定了所有的客戶端請求都必須要包含請求處理的所在分組。
? ? 9、id:RaftPeerId - 節(jié)點信息,就是一個簡單的節(jié)點唯一命名? ? ? ??
? ? ? ? 單純的節(jié)點名稱,只是當(dāng)前服務(wù)節(jié)點的標(biāo)識符。
三、初始化

如圖2.4所示,proxy的啟動涉及到8個類共32個操作。
1、Counter通過RaftServer內(nèi)部靜態(tài)類Builder構(gòu)建一個RaftServer構(gòu)建器
2、第3~11通過RaftServer構(gòu)建器設(shè)置:所屬分組、配置信息、節(jié)點信息、分組對應(yīng)的狀態(tài)機,并與最后執(zhí)行build進行構(gòu)建。
3、第12步是通過構(gòu)建器的靜態(tài)方法執(zhí)行proxy的構(gòu)建
4、第13步RaftServer$Builder使用反射的方式調(diào)用ServerImplUtils#newRaftServer方法。將porxy的構(gòu)建交由ServerImplUtils執(zhí)行。
5、從ServerImplUtils的生命線看,ServerImplUtils主要做了兩件事
? ? 1、第15步通過RaftServerProxy的構(gòu)建器,構(gòu)建proxy的實例。
? ? ? ? 在執(zhí)行proxy的構(gòu)造器是,主要初始化上邊介紹的屬性。
? ? 2、第23步初始化proxy的分組,在初始化分組時,通過proxy內(nèi)部類ImplMap屬性注冊分組對的真實Raft服務(wù)(RaftServerImpl)
? ? ? ? 添加分組實際上也是proxy的初始化的Raft服務(wù)的核心服務(wù)RaftServerImpl,proyx只是起到了一個代理服務(wù)和服務(wù)管理的作用,真實的業(yè)務(wù)處理器還是交給了RaftServerImpl執(zhí)行。
四、啟動


proxy的啟動比較簡單,只是啟動proxy中的各個組件
1、第2步執(zhí)行圖2.6中第一行業(yè)務(wù)邏輯,通過getImpls()獲取所有分組信息,并在executor線程池中分別執(zhí)行每個分組中注冊的RaftServerImpl實例的start方法,異步并行的啟動多個分組(可惜的是,到現(xiàn)在為止還未看到有直接多分組啟動的方式)。
2、第3步設(shè)置lifeCycle生命周期狀態(tài)控制器的狀態(tài),在設(shè)置狀態(tài)變更之前通過方法參數(shù)傳遞需要執(zhí)行的定制操作(這里的定制操作就是啟動對應(yīng)的底層通信組件),在組件正常啟動后設(shè)置lifeCycle的狀態(tài)。
3、第8步啟動Raft服務(wù)的監(jiān)控器-pauseMonitor,pasuseMonitor只是收集Raft在運行中的狀態(tài)和執(zhí)行情況信息,和業(yè)務(wù)無關(guān)。