C# 连接池开发,多连接高效应用开发,多连接自动维护管理。

本文将使用一个Github开源的组件库技术来实现连接池的操作,应用于一些情况下的频繁的网络连接操作。

github地址:https://github.com/dathlin/HslCommunication 如果喜欢可以star或是fork,还可以打赏支持,打赏请认准源代码项目。

本项目目前支持C#语言和java语言,C#语言的功能比较齐全,java版本的库还在开发及完善中。

nuget地址:https://www.nuget.org/packages/HslCommunication/       nuget     下载

github地址:https://github.com/dathlin/HslCommunication      fork      star                     如果喜欢可以star或是fork,还可以打赏支持。

 

 

组件的完整信息和API介绍参照:http://www.cnblogs.com/dathlin/p/7703805.html   组件的使用限制,更新日志,都在该页面里面。

 

为什么需要连接池


首先需要解决这个问题,我们为什么需要连接池,终极目的是是为了高效的数据访问,但并不是所有情况都需要进行连接池搭建的,举几个🌰吧

 

案例一:你有个后台线程每隔1s钟在读取PLC的数据,你和PLC的交互都在这个线程里面,那么完全是不需要进行连接池的。

案例二:你会在程序的多个线程(包括线程池里面)进行和PLC进行数据交互,频繁的读写操作,如果共用一个连接的性能达不到要求怎么办(通常在无线网络下,一次数据交互在30ms-100ms之间,网络波动较大)?,如果每次操作都创建连接,操作结束后关闭,这样也可以达到功能,只是损耗性能比较严重,无论是对PLC还是本机,通讯的效率也不是很理想,因为每次操作都是重新连接和关闭,这里的PLC实际上可以替换成数据库,Redis,其他任何的数据通信。

 

什么时候不能连接池


 

并不是所有的情况都可以使用连接池的,有个巨大的限制,如果服务器不支持多连接就很麻烦,比如说三菱PLC的服务器的端口,当然,一般的数据库,Redis,特殊的服务器都是支持。当然,有些特殊的服务器,支持的连接数是有上限的,没事,本组件也可以配置上限的连接数。

 

特性支持


 本功能类的设计之初,就是兼顾灵活性,为了支持其他所有的不同类型的数据通信,采用接口+泛型来实现,先构建一个通信封装类,再进行创建一个连接池管理器,再调用使用。

  1. 支持配置最大的连接数
  2. 支持设置连接过期时间
  3. 支持任意的其他类型的连接对象变成连接池

 

 

实战示例


 

此处举例访问西门子的PLC,所以第一步是创建一个连接的封装类,除了实现接口外,还需要定义真实的连接对象。

    public class SiemensConnector : HslCommunication.Algorithms.ConnectPool.IConnector
    {
        #region 构造方法

        public SiemensConnector( string ipAddress )
        {
            siemens = new HslCommunication.Profinet.Siemens.SiemensS7Net( HslCommunication.Profinet.Siemens.SiemensPLCS.S1200, ipAddress );
        }

        #endregion

        #region IConnector 实现


        /// <summary>
        /// 指示当前的连接是否在使用用
        /// </summary>
        public bool IsConnectUsing { get; set; }


        /// <summary>
        /// 唯一的GUID码
        /// </summary>
        public string GuidToken { get; set; }


        /// <summary>
        /// 最新一次使用的时间
        /// </summary>
        public DateTime LastUseTime { get; set; }


        /// <summary>
        /// 打开连接
        /// </summary>
        public void Open( )
        {
            // 设置常连接。如果是Redis,可以连接服务器,数据库也是一样
            siemens.ConnectServer( );
        }


        /// <summary>
        /// 关闭并释放
        /// </summary>
        public void Close( )
        {
            // 关闭连接
            siemens.ConnectClose( );
        }

        #endregion

        #region Public Member

        /// <summary>
        /// 获取当前的连接对象,方便进行数据交互
        /// </summary>
        /// <returns></returns>
        public HslCommunication.Profinet.Siemens.SiemensS7Net GetSiemens( )
        {
            return siemens;
        }

        #endregion


        #region Private Member

        private HslCommunication.Profinet.Siemens.SiemensS7Net siemens;        // 连接对象

        #endregion
    }

 

定义好之后,就可以创建真正的连接池对象了

private HslCommunication.Algorithms.ConnectPool.ConnectPool<SiemensConnector> siemensConnect = null;           // 西门子对象的连接池

  

然后初始化变量

siemensConnect = new HslCommunication.Algorithms.ConnectPool.ConnectPool<SiemensConnector>( ( ) => { return new SiemensConnector( "192.168.1.195" ); } );
            siemensConnect.MaxConnector = 10;         // 同时存在的最大连接数
            siemensConnect.ConectionExpireTime = 30;  // 连接多久不用就自动回收释放,单位秒

 

 

初始化的时候,有个地方需要注意,连接池需要知道一个信息,如何去创建一个新的连接对象,在这里可能创建默认的SiemesConnector就可以类,但是连接池的管理对象很有可能也是个接口,这时候就需要手动指示如何实例化一个新的对象。这种情况我在使用dapper的ORM的时候,支持mysql和sqlserver两种数据的时候就碰到过。

 

调用连接对象类,以下的代码可以出现在任何的后台线程:

            // 这里的代码在单线程程序情况下,没有什么效果,但是在多线程情况下可以显著提升性能。
            // 举例,此处要访问PLC的一个数据
            SiemensConnector connector = siemensConnect.GetAvailableConnector( );
            short m100 = connector.GetSiemens( ).ReadInt16( "M100" ).Content;

            // 使用完毕后归还连接
            siemensConnect.ReturnConnector( connector );

  

使用完后务必归还连接对象,如果想要获取连接池里已经被激活的连接数

int online = siemensConnect.UsedConnector;

  

还有,在获取连接对象后,进行操作的时候,务必不要抛出异常,

 

posted @ 2018-06-16 19:53  dathlin  阅读(8184)  评论(1编辑  收藏  举报