[源] http://zhuweisky.cnblogs.com/archive/2006/03/16/351426.html
上文已經(jīng)講到,Tcp連接池管理器為我們的應(yīng)用進(jìn)行了很多復(fù)雜的管理,比如功能服務(wù)器的調(diào)度(實現(xiàn)FS的負(fù)載均衡)、連接池的動態(tài)添加/移除、控制每個連接池的相關(guān)參數(shù)在UI上的顯示等,并且連接池管理器與單個連接池?fù)碛幸粯拥慕涌?/span>ITcpPool。我們先回顧一下這個接口:
1 public interface ITcpPool
2 {
3 RentStreamResult RentTcpStream(int poolTypeKey ,int serviceKey ,out NetworkStream stream ,out int serverID) ;//poolTypeKey表示某個城市,serviceKey表示某項服務(wù)
4 void GiveBackTcpStream(int streamHashCode ,int serverID) ;//將tcp連接規(guī)還給連接池
5 void SetStreamDamaged(int streamHashCode ,int serverID) ;//poolKey如果不易保存,則此處簡單的傳-1即可
6
7 event CallBackCountChanged ActiveConnectionCountChanged ;
8 event CallBackPoolStateChanged PoolStateChanged ;
9 }
10
RentTcpStream方法中的serviceKey參數(shù)反映了這樣一個事實:與一個AS相連的多個FS中,每個FS加載的功能插件可以是不一樣的。

比如,上圖中的3個FS中只有FS1加載了前面介紹的“天氣預(yù)測服務(wù)”插件,那么當(dāng)一個“天氣預(yù)測服務(wù)”請求到達(dá)AS時,AS就只能從與FS1之間的連接池中Rent一個Tcp連接,而不是從FS2或FS3。RentTcpStream方法的out參數(shù)serverID表明了這條連接是指向哪個FS的。
接下來考慮這樣一個問題,當(dāng)一個請求到來,這個請求可以被FS1、FS2、FS3處理,那么ITcpPoolsManager到底返回哪個連接池中的連接了?答案是負(fù)載最小的那個FS上的連接。
這是怎么做到的了?其實很簡單。每個FS都定時(比如一秒一次)地把自己的負(fù)載(CPU利用率和內(nèi)存利用率)通知給AS,通知給AS的方式可以有多種,比如.Net Remoting。ESFramework中有一個稱為連接池調(diào)度器ITcpPoolScheduler的東東,它記錄了每個FS實時的負(fù)載。這樣當(dāng)一個請求到來時,連接池管理器ITcpPoolsManager會要求連接池調(diào)度器從眾多的FS中選出一個“滿足條件”且負(fù)載最小的FS。這里的“滿足條件”主要指的是對應(yīng)的FS上有能處理該請求的功能插件。實現(xiàn)這種調(diào)度需要的支持的各個相互協(xié)作的組件的聯(lián)系圖大致如下:
圖中IServerPerformanceMonitor是用于監(jiān)控本地服務(wù)器性能的組件,它可以定時發(fā)布本服務(wù)器的性能數(shù)據(jù)(主要是CPU利用率和內(nèi)存利用率),其定義如下:
1 public interface IServerPerformanceMonitor
2 {
3 void Start() ;
4 void Stop() ;
5
6 int RefreshSpanSecs{get ;set ;}
7
8 event CBackServerPerformance ServerPerformanceDataRefreshed ;
9 }
11
12 public delegate void CBackServerPerformance(ServerPerformance performance) ;
13 public class ServerPerformance
14 {
15 public float CpuUsagePercent ;
16 public float MemoryUsagePercent ;
17 }
連接池調(diào)度器ITcpPoolScheduler的定義如下:
1 public interface ITcpPoolScheduler
2 {
3 //以下方法屬性僅僅由多連接池管理者調(diào)用
4 int GetNextTcpPool(int poolTypeKey) ; //返回的是某連接池的服務(wù)端點的serverID ,如果沒有可用的返回-1
5 int GetNextTcpPool(int poolTypeKey ,int serviceKey) ;
6
7 void Initialize() ;
8 void Dispose() ;//還原到未初始化的狀態(tài)
9 void SetServerState(int serverID ,bool activated) ;
10 void AddServer(int serverID) ;
11 void RemoveServer(int serverID) ;
12
13
14 //以下方法屬性由外部指定或調(diào)用
15 void SetPerformance(int serverID ,float cpuUsage ,float memUsage) ;
16 ITcpPoolHelper TcpPoolHelper{set ;}
17 }
為了使負(fù)載均衡的效果更好,ITcpPoolScheduler可以實現(xiàn)的非常復(fù)雜,比如進(jìn)行歷史記錄統(tǒng)計、分析、預(yù)測等。ESFramework給出了默認(rèn)實現(xiàn)TcpPoolScheduler。
在組件聯(lián)系圖中還有一個IPoolEndPointsDisplayer組件,它用于在UI上顯示每個功能服務(wù)器的詳細(xì)信息和性能數(shù)據(jù)。
1 public interface IPoolEndPointsDisplayer
2 {
3 void RegisterFs(int serverID ,string serverName ,IPEndPoint ipe ,int exceptCount) ;
4 void UnRegisterFs(int serverID) ;
5 void SetFsState(int serverID ,bool activated) ;
6 void SetActiveCount(int serverID ,int activeCount) ;
7 void UpdateFsPerformance(int serverID ,float cpuUsage ,float memUsage) ;
8 void Clear() ;
9 }
FS管理器管理連接上本AS的每個功能服務(wù)器,這將在后文中講到。
除了ITcpPool接口,連接池管理器還實現(xiàn)了ITcpPoolsManager接口:
1 public interface ITcpPoolsManager :ITcpPool
2 {
3 string TcpPoolSchedulerTypeString{set ;} //"ESFramework.Network.TcpPool.TcpPoolScheduler ,ESFramework"
4 ArrayList PoolEndPointList{set ;} //連接池的服務(wù)端PoolEndPointInfo列表
5 int ReconnectSpan{get ;set ;} // 分鐘
6
7 void Initialize() ; //初次建立連接池
8 void Dispose() ; //還原到?jīng)]有初始化的狀態(tài)
9 void AddPool(PoolEndPointInfo info) ;
10 void RemovePool(int serverID) ;
11
12 void DisposePoolConnections(int serverID) ;//編號為serverID的服務(wù)器已停止,所以釋放對應(yīng)的Pool,但是不刪除池,仍然定時重連
13 void ReconnectPool(int serverID) ; //曾停止的服務(wù)器已啟動完畢,所以可以重連了
14
15 /// <summary>
16 /// 可直接使用 ESFramework.Network.TcpPool.PoolEndPointsDisplayer
17 /// </summary>
18 IPoolEndPointsDisplayer PoolEndPointsDisplayer{set ;}
19
20 //由ITcpPoolScheduler使用
21 void SetPerformance(int serverID ,float cpuUsage ,float memUsage) ;
22 ITcpPoolHelper TcpPoolHelper{set ;} //可由ESFramework.Architecture.LBS.FourTier.FsManager提供
23 }
AddPool方法和RemovePool方法表明可以動態(tài)的添加/移除Tcp連接池。注意接口中的SetPerformance方法,這個方法將被FS管理器調(diào)用,用于把從Remoting接收到的FS的性能數(shù)據(jù)通知給ITcpPoolsManager,然后ITcpPoolsManager再把這些數(shù)據(jù)提交給ITcpPoolScheduler記錄,當(dāng)需要進(jìn)行調(diào)度的時候,ITcpPoolScheduler從這些記錄中進(jìn)行分析計算并找到負(fù)載最小的FS。TcpPoolSchedulerTypeString屬性用于向連接池管理器提供調(diào)度者的實際類型,管理器將會通過反射創(chuàng)建調(diào)度者的實例。
還有一個需要設(shè)置的屬性ITcpPoolHelper:
1 public interface ITcpPoolHelper
2 {
3 bool ContainsService(int serverID ,int serviceKey) ;
4 bool ServerIsTheType(int serverID ,int destType) ;
5 bool ServerIsCompatible(int serverID ,int destType ,int serviceKey) ;
6 string GetServerNameByID(int serverID) ;
7 }
由于這個接口提供了每個功能服務(wù)器詳細(xì)信息,所以這個接口的實現(xiàn)可以直接由前面提到的FS管理器順帶實現(xiàn)。
ITcpPoolsManager是一個比較復(fù)雜的組件,它需要涉及到多個組件的協(xié)作。所以如果看完這篇文章,仍然還有些不清楚的地方,是很正常的。在后面系列文章的繼續(xù)講述中,這些不清晰的地方會慢慢撥開迷霧。
感謝關(guān)注。