Netty高性能大容量Socket并发(一):Netty性能测试
来源:互联网 发布:simulink一端口多输入 编辑:程序博客网 时间:2024/05/22 05:14
Netty性能测试
Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。Netty 是一个基于NIO的客户,服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户,服务端应用。Netty相当简化和流线化了网络应用的编程开发过程,例如,TCP和UDP的socket服务开发。
Netty简化socket编程,并没有使写出来的Socket效率变低,我写了一个所有都使用默认配置的服务端,模拟最常用的RPC方案,传输协议使用4字节长度加json串的方式来传输,测试服务端的通讯效率,测试结果如下。
从测试结果看,Netty性能是非常高的,在所有使用默认配置的情况下,单台服务器能够达到4万次请求解析,作为RPC框架是足够用的。还有一个有趣的现象是每次都创建连接和重用连接的差别不大,性能损耗对应用层几乎没影响,但是大家如果在应用环境中使用每次新建的情况,一定要进行压测,确认没影响后再使用。
测试用例说明
- 部署1台Netty服务器,部署8台并发测试客户端,每个客户端跑1024个并发;
- 分为1次连接请求1000次数据和1次连接请求1次数据循环1000次;
- Netty服务器为Cent OS 6.5 64位,阿里云8核16G内存,JVM使用默认配置,没有进行任何调优;
- 并发客户端为Windows Server 2008 R2 64位企业版,阿里云8核16G内存,NET Framework 4.5运行环境,没有进行任何调优;
- 通讯数据格式为:4字节长度+JSON串,服务器负责接收JSON串,进行解析和返回;
Netty服务端代码
主程序入口
public class AppNettyServer { public static void main(String[] args) throws Exception { System.out.print("Hello Netty\r\n"); int port = 9090; if (args != null && args.length > 0) { try { port = Integer.valueOf(args[0]); } catch (NumberFormatException e) { System.out.print("Invalid Port, Start Default Port: 9090"); } } try { NettyCommandServer commandServer = new NettyCommandServer(); System.out.print("Start listen socket, port " + port + "\r\n"); commandServer.bind(port); } catch (Exception e) { System.out.print(e.getMessage()); } }}
Netty服务端初始化
public class NettyCommandServer { public static InternalLogger logger = InternalLoggerFactory.getInstance(NettyCommandServer.class); public void bind(int port) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup); serverBootstrap.channel(NioServerSocketChannel.class); serverBootstrap.option(ChannelOption.SO_BACKLOG, 1024); serverBootstrap.handler(new LoggingHandler()); serverBootstrap.childHandler(new NettyChannelHandler()); ChannelFuture channelFuture = serverBootstrap.bind(port).sync(); channelFuture.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } private class NettyChannelHandler extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast(new LengthFieldBasedFrameDecoder(ByteOrder.BIG_ENDIAN, 64 * 1024, 0, 4, 0, 4, true)); socketChannel.pipeline().addLast(new StringDecoder(Charset.forName("UTF-8"))); socketChannel.pipeline().addLast(new NettyCommandHandler()); } }}
通讯协议解析数据
public class NettyCommandHandler extends ChannelHandlerAdapter { private int counter = 0; @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { try { String body = (String) msg; JsonDataObject request = JsonUtil.fromJson(body, JsonDataObject.class); counter = counter + 1; JsonDataObject response = new JsonDataObject(); response.setCode(0); response.setMsg("Success"); response.setData(counter+""); String respJson = JsonUtil.toJson(response); byte[] respUtf8 = respJson.getBytes("UTF-8"); int respLength = respUtf8.length; ByteBuf respLengthBuf = PooledByteBufAllocator.DEFAULT.buffer(4); respLengthBuf.writeInt(respLength); respLengthBuf.order(ByteOrder.BIG_ENDIAN); ctx.write(respLengthBuf); ByteBuf resp = PooledByteBufAllocator.DEFAULT.buffer(respUtf8.length); resp.writeBytes(respUtf8); ctx.write(resp); } catch (Exception e) { NettyCommandServer.logger.error(e.getMessage() + "\r\n"); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); pw.flush(); sw.flush(); NettyCommandServer.logger.error(sw.toString()); } } @Override public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { ctx.close(); }}C#客户端代码
public class SocketClient : Object { private TcpClient tcpClient; public SocketClient() { tcpClient = new TcpClient(); tcpClient.Client.Blocking = true; } public void Connect(string host, int port) { tcpClient.Connect(host, port); } public void Disconnect() { tcpClient.Close(); } public string SendJson(string json) { byte[] bufferUTF8 = Encoding.UTF8.GetBytes(json); int jsonLength = System.Net.IPAddress.HostToNetworkOrder(bufferUTF8.Length); //转换为网络字节顺序,大头结构 byte[] bufferLength = BitConverter.GetBytes(jsonLength); tcpClient.Client.Send(bufferLength, 0, bufferLength.Length, SocketFlags.None); //发送4字节长度 tcpClient.Client.Send(bufferUTF8, 0, bufferUTF8.Length, SocketFlags.None); //发送Json串内容 byte[] bufferRecvLength = new byte[sizeof(int)]; tcpClient.Client.Receive(bufferRecvLength, sizeof(int), SocketFlags.None); //获取长度 int recvLength = BitConverter.ToInt32(bufferRecvLength, 0); recvLength = System.Net.IPAddress.NetworkToHostOrder(recvLength); //转为本地字节顺序 byte[] bufferRecvUtf8 = new byte[recvLength]; tcpClient.Client.Receive(bufferRecvUtf8, recvLength, SocketFlags.None); string recvCommand = Encoding.UTF8.GetString(bufferRecvUtf8, 0, recvLength); return recvCommand; } }
测试DEMO下载地址:下载地址
免责声明:此代码只是为了演示Netty性能测试,仅用于学习和研究,切勿用于商业用途。水平有限,错误在所难免,欢迎指正和指导。邮箱地址:fansheng_hx@163.com。
2 0
- Netty高性能大容量Socket并发(一):Netty性能测试
- Netty高性能大容量Socket并发
- Netty高性能大容量Socket并发 一
- Netty高性能大容量Socket并发(二):Netty简介
- Netty高性能大容量Socket并发 二
- Netty高性能并发
- DELPHI高性能大容量SOCKET并发(八):断点续传
- C#高性能大容量SOCKET并发(九):断点续传
- DELPHI高性能大容量SOCKET并发(一):IOCP完成端口例子介绍
- 高性能大容量SOCKET并发(一):IOCP完成端口例子介绍
- C#高性能大容量SOCKET并发(一):IOCP完成端口例子介绍
- C#高性能大容量SOCKET并发(一):IOCP完成端口例子介绍
- Netty实现高性能高并发
- DELPHI高性能大容量SOCKET并发(十):IOCP完成端口性能优化
- Netty开发中间件:高并发性能优化
- 高性能netty
- Netty高性能解决方案
- DELPHI高性能大容量SOCKET并发(二):IOCP完成端口控件封装
- 数字信号及分辨率
- HDU 2544 最短路
- zcmu1672
- oracle导数据
- toolBar主题设置
- Netty高性能大容量Socket并发(一):Netty性能测试
- InsetDrawable
- PERMISSION_UNFINISHED
- STM32低功耗模式--STOP模式
- 苹果IOS开发者账号总结
- NinePatchDrawable
- 捕获鼠标滚轮
- 敏捷开发之Scrum扫盲篇
- 【tornado】localhost与127.0.0.1设置cookie的异同