1、设计模式;
IO收发线程与EMPLOY任务线程必须分离设计,否则如果只考虑IO线程来处理所有事情的话,一旦出现某个业务接口运行较慢,势必造成对IO网络的堵塞,那么这样的后台服务又有什么用呢?
EMPLOY任务线程指派算法,要看具体业务来定,如果所有业务实现数据传输量大小差不多,反应时间长短都差不多的话,可以采取平均顺序分配的方式,否则可以按照业务具体调用来指派某一个或多个EMPLOY任务线程来处理。
如果再做的好一点的话,应该对每个EMPLOY任务线程进行监视,如按照已有任务队列长度来决定分配哪个线程。
2、性能保证;
必须保证正常通信过程中,各个连接、各个线程之间基本没有共享数据锁机制,否则性能肯定大打折扣;
对于Buffer访问机制,应该采取类似Linux内核技术的循环缓冲机制,其最大特点就是如果同时只有一个写线程和读线程时,此循环缓冲不用加任何互斥锁机制,这样性能才会保证;
对于socket本身进行的一些参数优化,如:设置SO_SNDBUF为零,可以减少用户态到内核态的复制CPU耗时。
3、错误处理;
IOCP最大的难点之一,就是在连接断开情况下的资源回收,推荐两种办法:
3.1、采取延时回收策略,在保证所有Buffer对象都在一定时间内回到队列后,再释放该连接的所有资源,前提是要看你的业务接口运行速度了,一般30秒左右应该足够了吧?!
3.2、采取即时回收策略,但是必须对多线程情况下考虑加入Buffer计数器,当所有Buffer被回收到当前连接对象后,并且EMPLOY任务线程中悬而未决的该连接任务个数为0时,马上进行回收处理。
4、容错机制;
主要是对包本身是否非法的检测,一般采取:4字节包头长度位+N字节数据位的协议模式,这样服务端只需每次解读包头来判断是否合法,
客户端API必须保证封包的正确性,一定要避免分片报文以杂序排列发到服务端;
如果服务端收到某连接有非法数据报文,应该主动关闭连接。
5、业务接入。
业务继承开发接口一般只需要关注三个方法:连接、断开连接、读取数据;
业务接口只需要继承并重载父类的读取数据方法,并在构造完回复数据后,调用父类的发送方法;
应该保证业务接口实现的高效性,避免一条鱼腥了一锅汤的情况发生。
性能测试建议样例:
1、每客户端平均0.5秒发个请求,报文大小100字节左右;
2、服务端回复1024字节;
3、连接个数10000;
4、服务器是R710,8核;
5、网络是千兆。
测试回应均值应不多于500微妙,好的可能达到100微妙以下,否则你的设计肯定有问题。
你的服务端设计一般只有两个锁机制:
1、每个连接对象的自锁,用来保持连接对象中一些变量的同步;
2、所有连接的集合,一般为MAP,用来insert、remove客户端连接时使用。
除此以外,你不应该再增加其他锁。