上一篇文章中讲到了分布式部署之后,各个模块要通过网络进行通信,那么如何通信,用什么协议呢?
可选的方案有http tcp/ip(socket)等
基于http协议,xml报文传输
客户端具体框架为httpclient,服务端为struts2
客户端和服务端的通信在内网
该方案我们实行过一段时间,发现存在性能问题,首先是短连接,在并发量较大的时候,开启大量的tcp连接,这样连接资源容易耗尽,客户端首先成为瓶颈,tps上不去。
我总结的几点原因:
1.每次通信都重新开启新的tcp连接,握手协议耗时间
2.tcp是慢启动,TCP 数据传输的性能还取决于 TCP 连接的使用期(age)。TCP 连接会随着时间进行自我“调谐”,起初会限制连接的最大速度,如果数据成功传输,会随着时间的推移提高传输的速度。这种调谐被称为 TCP 慢启动(slow start),用于防止因特网的突
然过载和拥塞
3.http协议是在tcp协议上封装了一层,因此还存在解析协议的消耗,如果直接用tcp协议进行传输,效率将要高一点
据说http1.1可以实现长连接,但是没有用java客户端试过,后续再研究。
主要开发任务在客户端,我是用Mina做的长连接异步通信,
我自己编写代码实现了一个,有时间贴出来分享一下,如果有想了解Mina使用技术的,可以先看我的Mina系列博客http://www.cnblogs.com/tangyanbo/p/4297377.html
这里我做了相关的性能测试,下面把测试结果贴出来一下:
短连接测试
场景描述
socket 发送消息到服务端,接收到响应后关闭
结果:
一段时间过后,会出现死掉的现象,连接会被耗尽
服务器cpu |
2线程 3000Mhz |
服务器cpu使用率 |
110% |
客户端cpu |
4线程 2400Mhz |
客户端cpu使用率 |
95% |
客户端执行线程数 |
500 |
每秒并发数 |
1800 |
长连接异步通讯测试
场景描述
客户端开启2个长连接,与服务端通信
服务器cpu |
2线程 3000Mhz |
服务器cpu使用率 |
100%-150% |
客户端cpu |
4线程 2400Mhz |
客户端cpu使用率 |
60% |
客户端连接数 |
2 |
客户端执行线程数 |
500 |
每秒通过事务数 |
16000 |
性能明显提升,而且状态稳定,cpu利用率较低
这里大家会有个问题,为什么要用异步通信,不能是同步
这里其实我们先要搞清楚什么是同步通信,什么是异步通信
同步通信应该很好理解,这里我们以同一个socket连接为例,即多次请求都是从一个socket连接发送出去的。
Socket客户端发送一个请求,等待响应成功之后,再发送另一个请求,即在同一时间只能发送一个请求,加入我们的场景是这样的,发送的报文较小,服务端处理的速度较快,我们网站的大多数业务请求都是这样的,这样报文在网络中传输的时候,通道是很空闲的,通信的吞吐量将收到影响。
典型的同步通信是jdbc
还是以同一个socket连接为例,socket客户端发送一个请求之后,在响应还没到来的时候,可以继续发送另一个请求,具体场景是这样的,业务线程1发送请求,然后线程等待结果,业务线程2发送请求,然后等待结果,以此类推,但是socket输出通道可以一直发送消息,socket输入一直在接收消息,这样业务处理和通信逻辑是分离开来的互不干扰,且充分利用了通信通道,因为网络传输的速度比cpu和磁盘要慢的多,因此解约使用网络资源,将极大的提高系统吞吐量,当然要记住这里的使用场景,高并发,较小的报文传输,如果报文特别大,几十MB,那异步通信就没意义了
Mina是使用的NIO
这个网站上很多资料,我就简单的讲下,我们的场景是适合用NIO的,为什么呢?
我们的场景除了高并发,报文小,还有一个特点,就是客户端部署的点要远远多于服务端,因为越是底层的服务,可重用性越高,那么客户端就相对较多,服务端相对较少。
BIO的缺点
传统的BIO特点,有N个客户端连接服务端,服务端就需要开启N个线程来分别处理客户端的请求,而且很多时候客户端是空闲状态的,那么服务端给它开的线程也将空闲,造成了资源浪费,同时线程数还不够用。
NIO的优点
NIO很好的解决了这个问题,它使得服务端的一个线程可以处理多个客户端连接,只要协调的好,可以用较少的线程处理较多的客户端连接,使线程利用率得到很大的提高。