負載均衡當(dāng)客戶端發(fā)起訪問請求時, 服務(wù)器端根據(jù)當(dāng)前負載情況選擇合適的服務(wù)器 響應(yīng)客戶端的請求。服務(wù)器端:a/ 服務(wù)注冊 -- 服務(wù)器啟動時向Zookeeper在/zookeeper/workservers節(jié)點目錄下注冊服務(wù)節(jié)點b/ 啟動Socket監(jiān)聽 客戶端的連接 -- 注冊服務(wù)器節(jié)點的同時 該服務(wù)器 針對自己在zookeepr上的服務(wù)節(jié)點進行監(jiān)聽 監(jiān)聽客戶端連接狀態(tài)(根據(jù)客戶端連接狀態(tài) 響應(yīng)對應(yīng)的負載更新操作)c/ 如果發(fā)生客戶端連接 Zookeeper 會寫入新的負載數(shù)據(jù)d/ 如果客戶端連接斷開 Zookeeper 會減少Zookeeper中節(jié)點的負載兩個主要功能:服務(wù)注冊:1/ RegistProvider -- interface? regist(Object object) 一般為ZookeeperRegistContext對象 從中提取ZkClient 在指定的ServerPath下創(chuàng)建臨時節(jié)點表征對應(yīng)的服務(wù)器正在服務(wù)中unregist(Object object) 2/ DefaultRegistProvider -- 實現(xiàn)RegistProvider接口 實現(xiàn)服務(wù)注冊regist(Object object) 一般為ZookeeperRegistContext對象 從中提取ZkClient 在指定的ServerPath下創(chuàng)建臨時節(jié)點表征對應(yīng)的服務(wù)器正在服務(wù)中unregist(Object object) 3/ ZookeeperRegistContext -- Zookeeper注冊上下文 server連接注意事項:zklient的序列化用的是什么序列化 則后續(xù)的連接傳輸時應(yīng)該也使用該序列化方式 否則解析不了公共類:ServerData:服務(wù)器的ip:port 以及對應(yīng)的負載注意事項:必須是真實的ip/port 使用netty的socket監(jiān)聽服務(wù)器啟動時 需要在zookeeper上進行服務(wù)注冊 寫入該服務(wù)器的ip:port 以及當(dāng)前負載客戶端連接時 首先讀取當(dāng)前所有服務(wù)器列表 然后根據(jù)負載選擇算法選擇唯一的一個服務(wù)器進行connect -- 讀取對應(yīng)的ServerData使用Channel 進行綁定至對應(yīng)的ip/port另一定要實現(xiàn)序列化接口 對象數(shù)據(jù)寫入zookeeper的節(jié)點 以及實現(xiàn)對比的Comparable接口其中定義balance 負載時 注意使用Integer? 否則后續(xù)使用無法使用compableTo方法負載更新:1/ BalanceUpdateProvider -- interface定義 increaseLoad(Integer step) 和 decreaseLoad(Integer step)2/ DefaultBalanceUpdateProvider -- 實現(xiàn)接口 實現(xiàn)負載更新實現(xiàn) increaseLoad(Integer step) 和 decreaseLoad(Integer step)更新指定服務(wù)器對應(yīng)目錄的負載時 首先讀取其負載 再針對當(dāng)前版本的數(shù)據(jù)進行負載更新 則同一個節(jié)點(一個服務(wù)器)的負載更新需要保持一定的獨立性針對一個服務(wù)器節(jié)點進行同步,即保證一個服務(wù)器操作的數(shù)據(jù)更新的有序進行 否則會導(dǎo)致bad version 異常這個服務(wù)器節(jié)點不能是static 屬于一個類的? 必須是多個相同DefaultBalanceUpdateProvider對應(yīng)的同一節(jié)點路徑在內(nèi)存中指定同一變量 則需要從外界傳遞過來? 不能是某一對象實例私有的 否則同步時沒用的3/ ServerHandler -- 處理客戶端請求 監(jiān)聽客戶端端口socket連接需要在客戶端增加 減少時 進行負載均衡的更新 因此需要實例化 實現(xiàn)BalanceUpdateProvider接口的對象 進行負載更新的操作 并且定義一次更新多少負載繼承自ChannelHandlerAdapter 包含成員變量 實現(xiàn)BalanceUpdateProvider接口的對象 重載其 channelActive(實現(xiàn)負載增加) 與 channelInactive方法(實現(xiàn)負載減少)Server -- interface 暴露對外接口 包含 bind方法(服務(wù)器端口的綁定 并開啟Socket監(jiān)聽) 為整個Server端最核心代碼ServerImpl -- 實現(xiàn)兩個方法 -- 服務(wù)器啟動時進行服務(wù)注冊(RegistProvider提供? 在DefaultRegistProvider類中結(jié)合ZookeeperRegistContext 實現(xiàn)服務(wù)的注冊)? ? ? ? ? ? ? 實現(xiàn) 端口監(jiān)聽和負載更新 通過ServerHandler實例對象 監(jiān)聽 管道激活(客戶端連接增加)和管道消極(客戶端連接減少) 在監(jiān)聽到管道激活時 實現(xiàn)負載增加(由BalanceUpdateProvider定義 DefaultBalanceUpdateProvider實現(xiàn))? 在監(jiān)聽到管道消極時 實現(xiàn)負載減少 (由BalanceUpdateProvider定義 DefaultBalanceUpdateProvider實現(xiàn))ServerRunner:多個服務(wù)器節(jié)點啟動,并綁定至相應(yīng)的服務(wù)器端口(ip port)實現(xiàn)socket監(jiān)聽監(jiān)聽線程的channelActive方法和channelInactive方法重寫為調(diào)用負載增加 負載減少定義多個服務(wù)器線程并啟動服務(wù)器線程 -- 服務(wù)器線程實現(xiàn)了 綁定監(jiān)聽Client:1/ 可用服務(wù)列表2/ 最合適的服務(wù)器3/ 與對應(yīng)服務(wù)器的通信1/ BalanceProvider負載均衡接口 支持泛型 申明 public T getBalanceItem();2/ AbstractBalanceProviderimplements BalanceProvider抽象類 實現(xiàn)BalanceProvider接口的getBalanceItem()方法? 并定義? protected abstract T balanceAlgorithm(Listitems);? protected abstract ListgetBalanceItems();3/ DefaultBalanceProvider 繼承 AbstractBalanceProvider負載均衡服務(wù)器選擇實現(xiàn)類? ? 獲取運行中的服務(wù)器列表的? 服務(wù)器節(jié)點數(shù)據(jù)的列表? 以及? 選擇負載最小的節(jié)點? ? 實現(xiàn):protected ServerData balanceAlgorithm(Listitems);? protected ListgetBalanceItems();4/ client 接口 定義連接和 取消連接兩個方法// 客戶端建立 與對應(yīng)服務(wù)器指定端口的 socket連接? 其中指定服務(wù)器 是由負載均衡算法選擇返回的? public void connect() throws Exception;// 連接斷開是指? 斷開指定的socket連接和指定的管道? public void disConnect() throws Exception;5/ clientImpl 實現(xiàn)Client接口成員變量:BalanceProviderprovider --為實現(xiàn)服務(wù)器選擇
EventLoopGroup -- 事件組
Channel -- socket連接通道
端口連接 獲取負載均衡算法選擇? bootstrap建立與對應(yīng)服務(wù)器指定端口的連接 -- bootstrap 打開socket通道? 建立起到 指定服務(wù)器ip:port的TCP 連接
public void connect(){};
斷開連接 -- 關(guān)閉通道 關(guān)閉事件組
public void disconnect(){};
ClientRunner:
客戶端運行程序,客戶端申請訪問請求時,首先負載均衡算法獲取對應(yīng)的服務(wù)器節(jié)點(首先獲取服務(wù)器列表 然后選擇負載最小的服務(wù)器節(jié)點 返回對應(yīng)的ip port)
客戶端通過socket連接到對應(yīng)的ip port 當(dāng)服務(wù)器端檢測到對應(yīng)服務(wù)器端口連接狀態(tài)的改變時 服務(wù)器端會做出相應(yīng)的響應(yīng)
定義多個客戶端線程? 在線程內(nèi)部實現(xiàn)客戶端對象實例化 并執(zhí)行連接操作
每個客戶端線程啟動運行中間 需要進行一定的延時操作,否則容易導(dǎo)致 數(shù)據(jù)同時讀取? 版本出現(xiàn)差錯
如果不在服務(wù)器端的 decreaseLoad increaseLoad 添加一個同步標志 (針對同一個服務(wù)器節(jié)點(服務(wù)器節(jié)點路徑) 進行同步? ) 也不添加延時 則會出現(xiàn) badversion異常
如果不用延時? 則同時獲取的最小balance 是一致的? 那么會導(dǎo)致本次連接全部一次性連接至該負載最小節(jié)點 導(dǎo)致網(wǎng)絡(luò)不平衡
另外需要注意:? 在最后一定要關(guān)閉連接和關(guān)閉線程釋放資源 client.disconnect? thread.interrupt? thread.join