zoukankan      html  css  js  c++  java
  • ESFramework介绍之(11)-- Tcp连接池管理器

        上文已经讲到,Tcp连接池管理器为我们的应用进行了很多复杂的管理,比如功能服务器的调度(实现FS的负载均衡)、连接池的动态添加/移除、控制每个连接池的相关参数在UI上的显示等,并且连接池管理器与单个连接池拥有一样的接口ITcpPool。我们先回顾一下这个接口: 
     1     public interface ITcpPool
     2     {
     3         RentStreamResult RentTcpStream(int poolTypeKey ,int serviceKey ,out NetworkStream stream ,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 CallBackCountChanged     ActiveConnectionCountChanged ;     
     8         event CallBackPoolStateChanged PoolStateChanged ;        
     9     }
    10 

        RentTcpStream方法中的serviceKey参数反映了这样一个事实:与一个AS相连的多个FS中,每个FS加载的功能插件可以是不一样的。



        比如,上图中的
    3FS中只有FS1加载了前面介绍的“天气预测服务”插件,那么当一个“天气预测服务”请求到达AS时,AS就只能从与FS1之间的连接池中Rent一个Tcp连接,而不是从FS2FS3RentTcpStream方法的out参数serverID表明了这条连接是指向哪个FS的。

        接下来考虑这样一个问题,当一个请求到来,这个请求可以被FS1FS2FS3处理,那么ITcpPoolsManager到底返回哪个连接池中的连接了?答案是负载最小的那个FS上的连接。
        这是怎么做到的了?其实很简单。每个FS都定时(比如一秒一次)地把自己的负载(CPU利用率和内存利用率)通知给AS,通知给AS的方式可以有多种,比如.Net RemotingESFramework中有一个称为连接池调度器ITcpPoolScheduler的东东,它记录了每个FS实时的负载。这样当一个请求到来时,连接池管理器ITcpPoolsManager会要求连接池调度器从众多的FS中选出一个“满足条件”且负载最小的FS。这里的“满足条件”主要指的是对应的FS上有能处理该请求的功能插件。实现这种调度需要的支持的各个相互协作的组件的联系图大致如下:


          
        图中IServerPerformanceMonitor是用于监控本地服务器性能的组件,它可以定时发布本服务器的性能数据(主要是CPU利用率和内存利用率),其定义如下:
     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     }    
     

    连接池调度器ITcpPoolScheduler的定义如下:

     1     public interface 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         ITcpPoolHelper    TcpPoolHelper{set ;}
    17     }

        为了使负载均衡的效果更好,ITcpPoolScheduler可以实现的非常复杂,比如进行历史记录统计、分析、预测等。ESFramework给出了默认实现TcpPoolScheduler

        在组件联系图中还有一个IPoolEndPointsDisplayer组件,它用于在UI上显示每个功能服务器的详细信息和性能数据。

    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的每个功能服务器,这将在后文中讲到。
        除了ITcpPool接口,连接池管理器还实现了ITcpPoolsManager接口:

     1     public interface ITcpPoolsManager :ITcpPool
     2     {
     3         string              TcpPoolSchedulerTypeString{set ;} //"ESFramework.Network.TcpPool.TcpPoolScheduler ,ESFramework"
     4         ArrayList         PoolEndPointList{set ;} //连接池的服务端PoolEndPointInfo列表        
     5         int                  ReconnectSpan{get ;set ;} // 分钟         
     6         
     7         void              Initialize() ;    //初次建立连接池
     8         void              Dispose() ; //还原到没有初始化的状态
     9         void              AddPool(PoolEndPointInfo info) ;
    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         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方法表明可以动态的添加/移除Tcp连接池。注意接口中的SetPerformance方法,这个方法将被FS管理器调用,用于把从Remoting接收到的FS的性能数据通知给ITcpPoolsManager,然后ITcpPoolsManager再把这些数据提交给ITcpPoolScheduler记录,当需要进行调度的时候,ITcpPoolScheduler从这些记录中进行分析计算并找到负载最小的FSTcpPoolSchedulerTypeString属性用于向连接池管理器提供调度者的实际类型,管理器将会通过反射创建调度者的实例。

    还有一个需要设置的属性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     }

        由于这个接口提供了每个功能服务器详细信息,所以这个接口的实现可以直接由前面提到的FS管理器顺带实现。

        ITcpPoolsManager
    是一个比较复杂的组件,它需要涉及到多个组件的协作。所以如果看完这篇文章,仍然还有些不清楚的地方,是很正常的。在后面系列文章的继续讲述中,这些不清晰的地方会慢慢拨开迷雾。

    感谢关注!

    上篇文章:ESFramework介绍之(10)-- Tcp连接池

    转到  :ESFramework 可复用的通信框架(序) 

  • 相关阅读:
    hello world之vivado程序解决方法
    FPGA的电源选择重要性分析
    RabbitMQ的简单使用
    RabbitMQ的相关概念
    Spring整合Quartz
    DisallowConcurrentExecution注解
    Quartz框架中的监听器
    JobStore使用
    quartz基本介绍
    java自定义注解
  • 原文地址:https://www.cnblogs.com/zhuweisky/p/351426.html
Copyright © 2011-2022 走看看