2 {
3 RentStreamResultRentTcpStream( int poolTypeKey, int serviceKey, out NetworkStreamstream, out int serverID); // poolTypeKey表示某个城市,serviceKey表示某项服务
4 void GiveBackTcpStream( int streamHashCode, int serverID); // 将tcp连接规还给连接池
5 void SetStreamDamaged( int streamHashCode, int serverID); // poolKey如果不易保存,则此处简单的传-1即可
6
7 event CallBackCountChangedActiveConnectionCountChanged;
8 event CallBackPoolStateChangedPoolStateChanged;
9 }
10
RentTcpStream 方法中的 serviceKey 参数反映了这样一个事实:与一个 AS 相连的多个 FS 中,每个 FS 加载的功能插件可以是不一样的。
比如,上图中的
3
个
FS
中只有
FS1
加载了前面介绍的“天气预测服务”插件,那么当一个“天气预测服务”请求到达
AS
时,
AS
就只能从与
FS1
之间的连接池中
Rent
一个
Tcp
连接,而不是从
FS2
或
FS3
。
RentTcpStream
方法的
out
参数
serverID
表明了这条连接是指向哪个
FS
的。
接下来考虑这样一个问题,当一个请求到来,这个请求可以被
FS1
、
FS2
、
FS3
处理,那么ITcpPoolsManager
到底返回哪个连接池中的连接了?答案是负载最小的那个
FS
上的连接。
这是怎么做到的了?其实很简单。每个
FS
都定时(比如一秒一次)地把自己的负载(
CPU
利用率和内存利用率)通知给
AS
,通知给
AS
的方式可以有多种,比如
.Net Remoting
。
ESFramework
中有一个称为连接池调度器
ITcpPoolScheduler
的东东,它记录了每个
FS
实时的负载。这样当一个请求到来时,连接池管理器ITcpPoolsManager会要求连接池调度器从众多的
FS
中选出一个“满足条件”且负载最小的
FS
。这里的“满足条件”主要指的是对应的
FS
上有能处理该请求的功能插件。实现这种调度需要的支持的各个相互协作的组件的联系图大致如下:
图中 I ServerPerfo rmanceMonitor 是用于监控本地服务器性能的组件,它可以定时发布本服务器的性能数据(主要是 CPU 利用率和内存利用率),其定义如下:
2 {
3 void Start();
4 void Stop();
5
6 int RefreshSpanSecs{ get ; set ;}
7
8 event CBackServerPerformanceServerPerformanceDataRefreshed;
9 }
11
12 public delegate void CBackServerPerformance(ServerPerformanceperformance);
13 public class ServerPerformance
14 {
15 public float CpuUsagePercent;
16 public float MemoryUsagePercent;
17 }
连接池调度器
ITcpPoolScheduler
的定义如下:
2 {
3 // 以下方法属性仅仅由多连接池管理者调用
4 int GetNextTcpPool( int poolTypeKey); // 返回的是某连接池的服务端点的serverID,如果没有可用的返回-1
5 int GetNextTcpPool( int poolTypeKey, int serviceKey);
6
7 void Initialize();
8 void Dispose(); // 还原到未初始化的状态
9 void SetServerState( int serverID, bool activated);
10 void AddServer( int serverID);
11 void RemoveServer( int serverID);
12
13
14 // 以下方法属性由外部指定或调用
15 void SetPerformance( int serverID, float cpuUsage, float memUsage);
16 ITcpPoolHelperTcpPoolHelper{ set ;}
17 }
为了使负载均衡的效果更好, ITcpPoolScheduler 可以实现的非常复杂,比如进行历史记录统计、分析、预测等。 ESFramework 给出了默认实现 TcpPoolScheduler 。
在组件联系图中还有一个IPoolEndPointsDisplayer
组件,它用于在
UI
上显示每个功能服务器的详细信息和性能数据。
2 {
3 void RegisterFs( int serverID, string serverName,IPEndPointipe, 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
的每个功能服务器,这将在后文中讲到。
除了
ITcpPool
接口,连接池管理器还实现了
ITcpPoolsManager
接口:
2 {
3 string TcpPoolSchedulerTypeString{ set ;} // "ESFramework.Network.TcpPool.TcpPoolScheduler,ESFramework"
4 ArrayListPoolEndPointList{ set ;} // 连接池的服务端PoolEndPointInfo列表
5 int ReconnectSpan{ get ; set ;} // 分钟
6
7 void Initialize(); // 初次建立连接池
8 void Dispose(); // 还原到没有初始化的状态
9 void AddPool(PoolEndPointInfoinfo);
10 void RemovePool( int serverID);
11
12 void DisposePoolConnections( int serverID); // 编号为serverID的服务器已停止,所以释放对应的Pool,但是不删除池,仍然定时重连
13 void ReconnectPool( int serverID); // 曾停止的服务器已启动完毕,所以可以重连了
14
15 /// <summary>
16 /// 可直接使用ESFramework.Network.TcpPool.PoolEndPointsDisplayer
17 /// </summary>
18 IPoolEndPointsDisplayerPoolEndPointsDisplayer{ set ;}
19
20 // 由ITcpPoolScheduler使用
21 void SetPerformance( int serverID, float cpuUsage, float memUsage);
22 ITcpPoolHelperTcpPoolHelper{ set ;} // 可由ESFramework.Architecture.LBS.FourTier.FsManager提供
23 }
AddPool 方法和 RemovePool 方法表明可以动态的添加 / 移除 Tcp 连接池。注意接口中的 SetPerformance 方法,这个方法将被 FS 管理器调用,用于把从 Remoting 接收到的 FS 的性能数据通知给 ITcpPoolsManager ,然后 ITcpPoolsManager 再把这些数据提交给 ITcpPoolScheduler 记录,当需要进行调度的时候, ITcpPoolScheduler 从这些记录中进行分析计算并找到负载最小的 FS 。 TcpPoolSchedulerTypeString 属性用于向连接池管理器提供调度者的实际类型,管理器将会通过反射创建调度者的实例。
还有一个需要设置的属性
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 }
由于这个接口提供了每个功能服务器详细信息,所以这个接口的实现可以直接由前面提到的
FS
管理器顺带实现。
ITcpPoolsManager
是一个比较复杂的组件,它需要涉及到多个组件的协作。所以如果看完这篇文章,仍然还有些不清楚的地方,是很正常的。在后面系列文章的继续讲述中,这些不清晰的地方会慢慢拨开迷雾。
感谢关注!
上篇文章:
ESFramework介绍之(10)-- Tcp连接池
转到:
ESFramework 可复用的通信框架(序)