自己写的一个简单的TCP通信框架
?一个自己倒腾的简单的通信框架(目前只是基于请求响应模式),集成底层的API,目的在于提高通信层的开发效率。该通信框架包括如下几个功能:
?? ? ? ?1.服务端采用NIO模式,提高通信速率
?? ? ? ?2.内部提供可选连接池方式,尽可能的将连接重用,提高开发效率。
?? ? ? ?3.提供过滤器自定义
?? ? ? ?4.业务处理层自定义
?? ? ? ?5.提供负载均衡
?? ? ? ?6.连接选择器与消息选择器分离
?? ? ? ?7.客户端采用连接池模式,具有自动识别服务端是否存活的功能。
?
因为环境受限,自己在自己的机子上测试了一下,16分钟,8个客户端,一共640万次简单请求,错误率基本为0
机子的配置是:CPU:2.93G双核,内存:2G内存,操作系统:ununtu10.10
写的还不是很好,如果大家对java写通信方面的东西比较感兴趣的可以私信交流^_^
?
?
下个写一个小Demo,首先我们定义个服务端的业务对象ServerHandler实现框架的FPHandler接口,,主要是从客户端接收消息以后,将当前时间和客户端发送过来的消息一并发给客户端,代码如下:
package com.foolfish.Zfocomint.test;import java.io.IOException;import java.io.UnsupportedEncodingException;import java.text.SimpleDateFormat;import java.util.Date;import com.foolfish.comint.handler.FPHandler;import com.foolfish.comint.session.FPSession;/** * 服务端业务处理对象,实现自自FPHandler接口 * messRecv,接收消息时候触发的方法 * messSend,发送消息时候出发的方法 * sessionClosed,链接关闭触发的方法 * sessionCreated,链接创建出发的方法 * @author foolfish * */public class ServerHandler implements FPHandler{@Overridepublic void messRecv(FPSession session, byte[] mess) {try {// 处理接收客户端的消息String m = new String(mess,"utf-8");/************************************* * 此处可以做具体的业务处理,demo当中就省略了, * 只是简单的将客户端的信息返回 *************************************/// 向客户端回写信息String date = new SimpleDateFormat("yyyyMMdd HH:mm:ss").format(new Date());session.write(("服务端返回消息"+ date +m).getBytes("utf-8"));} catch (UnsupportedEncodingException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}@Overridepublic void messSend(FPSession session, byte[] mess) {// TODO Auto-generated method stub}@Overridepublic void sessionClosed(FPSession session) {// TODO Auto-generated method stub}@Overridepublic void sessionCreated(FPSession session) {// TODO Auto-generated method stub}}?
?
定义服务端的启动方法,ServerStart
public class ServerStart {public static void main(String[] args) throws Exception{// 启动服务端,采用NIO模式FPAcceptor acceptor = new FPNIOAcceptor();// 绑定业务处理类acceptor.setHandlerClass(ServerHandler.class);// 设置连接池大小acceptor.setPoolSize(10);// 设置是否采用连接池(默认使用单链接方式)acceptor.setIsPool(true);// 设置负载均衡器(该功能未做性能测试,功能已经完成)//acceptor.setLbServer(new InetSocketAddress("127.0.0.1", 4320));// 设置服务端口acceptor.setPort(4331);// 启动服务acceptor.startServer();}}?
?
下面定义个客户端:客户端使用一个while循环,不断向服务端发送消息(模拟不断的请求)
/** * @param args * @throws IOException * @throws FPComException */public static void main(String[] args){String line = "Hello";int i = 0;int j = 0;while(true){try {// 设置服务端的地址和端口号FPIOConnector conn = new FPIOConnector(true, new FPInetAddress("127.0.0.1", 4331));// 设定自动重发次数(对于延迟等错误情况可以选择自动重发)conn.setRetryCount(2);// 发送并接收返回的结果信息,并统计错误率System.out.println(new String(conn.request(line.getBytes("utf-8")),"utf-8")+"共请求"+(i++)+"次,错误"+(j)+"次");}catch (UnsupportedEncodingException e) {e.printStackTrace();} catch (FPComException e) {j++; continue;}}}?
?
?
运行服务端启动方法,ServerStart.java,然后运行客户端Client.java,就可以看到运行结果如下
服务端返回消息20110226 20:53:33Hello共请求5445次,错误0次服务端返回消息20110226 20:53:33Hello共请求5446次,错误0次服务端返回消息20110226 20:53:33Hello共请求5447次,错误0次服务端返回消息20110226 20:53:33Hello共请求5448次,错误0次服务端返回消息20110226 20:53:33Hello共请求5449次,错误0次服务端返回消息20110226 20:53:33Hello共请求5450次,错误0次服务端返回消息20110226 20:53:33Hello共请求5451次,错误0次服务端返回消息20110226 20:53:33Hello共请求5452次,错误0次服务端返回消息20110226 20:53:33Hello共请求5453次,错误0次服务端返回消息20110226 20:53:33Hello共请求5454次,错误0次服务端返回消息20110226 20:53:33Hello共请求5455次,错误0次服务端返回消息20110226 20:53:33Hello共请求5456次,错误0次服务端返回消息20110226 20:53:33Hello共请求5457次,错误0次服务端返回消息20110226 20:53:33Hello共请求5458次,错误0次服务端返回消息20110226 20:53:33Hello共请求5459次,错误0次服务端返回消息20110226 20:53:33Hello共请求5460次,错误0次服务端返回消息20110226 20:53:33Hello共请求5461次,错误0次服务端返回消息20110226 20:53:33Hello共请求5462次,错误0次服务端返回消息20110226 20:53:33Hello共请求5463次,错误0次服务端返回消息20110226 20:53:33Hello共请求5464次,错误0次服务端返回消息20110226 20:53:33Hello共请求5465次,错误0次服务端返回消息20110226 20:53:33Hello共请求5466次,错误0次服务端返回消息20110226 20:53:33Hello共请求5467次,错误0次服务端返回消息20110226 20:53:33Hello共请求5468次,错误0次?
?
20 楼 DAOException 2011-02-28 分离的北极熊 写道看代码,和我现在用mina进行封装的很类似我封装了底层的socket和nio,有空可以而多交流交流啊 21 楼 wubg 2011-02-28 能超出Mina框架,如果根本达不到其水平,或者只是借鉴,就没必要写什么“自忆写的” 22 楼 小哥1900 2011-02-28 JavaYwsEye 写道为啥要重复造轮子呢?有现成的不用???
有这个时间可以去做很多其它的事了!
你这种人标准的Loser吧 23 楼 corelengine 2011-02-28 对这个不懂,请问这个框架用在哪方面? 24 楼 hc_face 2011-02-28 楼主,很厉害啊,平时多造轮子,真正用的时候才能够有创造性!学习! 25 楼 ahuango 2011-02-28 楼主很有学习精神,但是有一件事不是很清楚。我一直认为NIO会节省资源,它会提高效率吗? 26 楼 DAOException 2011-02-28 ahuango 写道楼主很有学习精神,但是有一件事不是很清楚。我一直认为NIO会节省资源,它会提高效率吗?
NIO使用非阻塞的方式可以提高线程的利用率,原有的方式需要一条线程监管一条连接,相对来说比较消耗资源。不过这也要看具体的需求去做了,NIO使用方面稍微繁琐点~~。 27 楼 sky_sz 2011-02-28 留个脚印,以后学习 28 楼 zhaosong 2011-02-28 单从性能角度,如果每秒处理请求达不到2万,只能说是太一般了。更别说整体的稳定性和健壮性。 29 楼 DAOException 2011-02-28 zhaosong 写道单从性能角度,如果每秒处理请求达不到2万,只能说是太一般了。更别说整体的稳定性和健壮性。
仅仅做了一定量的压力测试,没有做最大压力的测试,晚上回去测试看看最多能抗多少~~~~~ 30 楼 cx6445 2011-02-28 DAOException 写道zhaosong 写道单从性能角度,如果每秒处理请求达不到2万,只能说是太一般了。更别说整体的稳定性和健壮性。
仅仅做了一定量的压力测试,没有做最大压力的测试,晚上回去测试看看最多能抗多少~~~~~
压测要分两台不同的机器,一台clinet和一台server,要评估每次RPC数据量大小,观察server的CPU占用和jvm的GC情况。一般情况下1K数据的RPC,5万以上的TPS没啥问题的。
31 楼 rocketball 2011-02-28 DAOException 写道zhaosong 写道单从性能角度,如果每秒处理请求达不到2万,只能说是太一般了。更别说整体的稳定性和健壮性。
仅仅做了一定量的压力测试,没有做最大压力的测试,晚上回去测试看看最多能抗多少~~~~~
你这种情况,线程池其实也没啥用处,你基本没有业务层。在decoder层是单线程的,多线程会增加调度的负荷。我在8核的电脑上对Mina做个一个简单的压力测试,有一点简单的业务逻辑(没有数据库操作),5w/s没有问题
32 楼 DAOException 2011-02-28 cx6445 写道DAOException 写道zhaosong 写道单从性能角度,如果每秒处理请求达不到2万,只能说是太一般了。更别说整体的稳定性和健壮性。
仅仅做了一定量的压力测试,没有做最大压力的测试,晚上回去测试看看最多能抗多少~~~~~
压测要分两台不同的机器,一台clinet和一台server,要评估每次RPC数据量大小,观察server的CPU占用和jvm的GC情况。一般情况下1K数据的RPC,5万以上的TPS没啥问题的。
谢谢指点,受教了 33 楼 DAOException 2011-02-28 rocketball 写道DAOException 写道zhaosong 写道单从性能角度,如果每秒处理请求达不到2万,只能说是太一般了。更别说整体的稳定性和健壮性。
仅仅做了一定量的压力测试,没有做最大压力的测试,晚上回去测试看看最多能抗多少~~~~~
你这种情况,线程池其实也没啥用处,你基本没有业务层。在decoder层是单线程的,多线程会增加调度的负荷。我在8核的电脑上对Mina做个一个简单的压力测试,有一点简单的业务逻辑(没有数据库操作),5w/s没有问题
嗯,我的压力测试业务层基本算是忽略了,这也体现不出线程池的优势了,反而增加了负担,谢谢你的提醒啊~~~ 34 楼 zhaosong 2011-03-01 开源框架中 mina还不是性能最好的。
其实只要理解了非堵塞机制,很好的把握工作线程和请求连接之间的平衡,针对业务来调整框架,性能都差不了。
主要还是看业务来写框架,不同的业务适用于不同的框架。 35 楼 bitray 2011-03-01 我想给你投支持,可是我点不了,不知道为什么。我只好在回复里支持你下。
很多人根本不了解实现,仅仅停留在应用层,有一个机会让我们了解,其实是非常感谢的 36 楼 bitray 2011-03-01 JavaYwsEye 写道为啥要重复造轮子呢?有现成的不用???
有这个时间可以去做很多其它的事了!
你了解轮子的构造吗?让你做一个轮子,钢结构的你能做吗?
仅仅停留在用轮子,不会生产轮子的境界,也不是什么高人
楼主不是在发明创造,而是在生产制造。你能制造一个吗?我不能,所以我想学。你会可以不学,呵呵 37 楼 wangdongjie03 2011-03-02 呵呵,用的地方不一样,楼上不用纠结 38 楼 littleJava 2011-03-03 JavaYwsEye 写道为啥要重复造轮子呢?有现成的不用???
有这个时间可以去做很多其它的事了!
每个框架的实现都有作者自己的想法,哪怕仅仅是为了练手。Spring很牛X,Guice就不应该存在?! 39 楼 littleJava 2011-03-03 DAOException 写道on-the-way 写道求源代码...
需要源码私信我~
希望楼主把源码公开,围观一个框架从无到有的慢慢成长还是很喜庆的