压测准备
- 需要将ulimit -n 改大,否则nio链接开不大。
- 准备4台机器(1台netty服务器,3台压测机)
- 使用apache的ab做压测工具
开始干活
压测代码:
package org.dueam.sample.netty; package org.dueam.sample.netty; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.InetSocketAddress; import java.util.HashMap; import java.util.Map; import java.util.Random; import java.util.concurrent.Executors; import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.DynamicChannelBuffer; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelFactory; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelStateEvent; import org.jboss.netty.channel.ExceptionEvent; import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.channel.SimpleChannelHandler; import org.jboss.netty.channel.ChannelHandler.Sharable; import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; public class ChatServer { public static void main(String[] args) throws Exception { if(args.length <1){ args = new String[]{"9876","true"}; } ChannelFactory factory = new NioServerSocketChannelFactory(Executors .newCachedThreadPool(), Executors.newCachedThreadPool()); ServerBootstrap bootstrap = new ServerBootstrap(factory); ChatServerHandler handler = new ChatServerHandler(); ChannelPipeline pipeline = bootstrap.getPipeline(); pipeline.addLast("chat", handler); bootstrap.setOption("child.tcpNoDelay", true); bootstrap.setOption("child.keepAlive", true); int port = Integer.valueOf(args[0]); bootstrap.bind(new InetSocketAddress(port)); boolean fillChat = "true".equals(args[1]); if (fillChat) { ChannelManagerThread cmt = new ChannelManagerThread(); cmt.start(); } BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); while (true) { String command = br.readLine(); if ("dump".equals(command)) { System.out.println("当前活着的数量:" + channel.size()); } else if ("help".equals(command)) { System.out.println("命令列表:"); System.out.println("dump:打印当前情况"); System.out.println("help:帮助文档"); } } } final static Random random = new Random(); static int max = 0; static class ChannelManagerThread extends Thread { @Override public void run() { while (true) { try { if(max < channel.size()){ max = channel.size() ; System.out.println("live:"+channel.size()); } for (Channel s : channel.values()) { if (random.nextInt(100)>70) { ChannelBuffer cb = new DynamicChannelBuffer(256); cb.writeBytes("Hey!有人来找你了!".getBytes()); s.write(cb); } } sleep(500); } catch (InterruptedException e) { } } } } final static Map<Integer, Channel> channel = new HashMap<Integer, Channel>(); static void log(String message) { System.out.println(message); } @Sharable static class ChatServerHandler extends SimpleChannelHandler { @Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) { Channel ch = e.getChannel(); ChannelBuffer cb = new DynamicChannelBuffer(256); cb.writeBytes("Hell!你来了啊!".getBytes()); ch.write(cb); channel.put(e.getChannel().getId(), e.getChannel()); } @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) { } @Override public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) { e.getCause().printStackTrace(); channel.remove(e.getChannel().getId()); log("remove channel by exception! id:" + e.getChannel().getId()); e.getChannel().close(); } @Override public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { channel.remove(e.getChannel().getId()); log("remove channel by exception! id:" + e.getChannel().getId()); } } }
压测方式:
#加大超时和并发量,并使用keep-alive的方式保持住端口 ./ab -n 20000 -c 20000 -k -t 999999999 -r http://192.168.216.30:9876/
压测结果
内存损耗:
[root@cap216030 ~]# free -k -t -s 10 -- 原始内存 total used free shared buffers cached Mem: 4149076 189828 3959248 0 13196 95484 -/+ buffers/cache: 81148 4067928 Swap: 2096472 208 2096264 Total: 6245548 190036 6055512 -- 执行 chat server之后 total used free shared buffers cached Mem: 4149076 207236 3941840 0 13216 96244 -/+ buffers/cache: 97776 4051300 Swap: 2096472 208 2096264 Total: 6245548 207444 6038104 -- 59471 个nio连接之后 total used free shared buffers cached Mem: 4149076 474244 3674832 0 13328 96132 -/+ buffers/cache: 364784 3784292 Swap: 2096472 208 2096264 Total: 6245548 474452 5771096
结论:
- Netty nio 可以轻松将链接开到6W,每个线程大概损坏5k左右的系统内存
后续压测方案
- 编写Java客户端做内容实时双向推送
- 使用100台机器每台机器起1000个线程来模拟客户端进行压测
原文转自 http://dueam.org/
相关推荐
Java异步NIO框架Netty实现高性能高并发无标题笔记 1. 背景 1.1. 惊人的性能数据 最近一个圈内朋友通过私信告诉我,通过使用Netty4 + Thrift压缩二进制编解码技术,他们实现了10W TPS(1K的复杂POJO对象)的跨 节点...
资源名称:Java_NIO框架Netty教程资源截图: 资源太大,传百度网盘了,链接在附件中,有需要的同学自取。
Netty是一个高性能、异步事件驱动的NIO框架,它提供了对TCP、UDP和文件传输的支持,作为一个异步NIO框架,Netty的所有IO操作都是异步非阻塞的,通过Future-Listener机制,用户可以方便的主动获取或者通过通知机制...
netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty...
netty 新NIO框架 文档,在jetty项目中用到了该框架。 netty更注重IO读写,效率很高。更支持servlet1.0异步的websocket。值得一看
netty nio 封装java nio用于网络分布式数据传输。
基于netty的nio使用demo源码
包含了Netty,NIO AIO,Mina知识的详解以及netty结合spring protocolbuf的源码
Java高并发编程代码(Netty NIO 实例)
NIO 框架 netty 与 mina
NULL 博文链接:https://gjp014.iteye.com/blog/2390925
Java NIO框架Netty教程 很好的东西!
介绍JavaNIO框架netty的特点和如何使用等,可以多多学习。
本书详细的介绍了NIO框架netty的使用,并附有详细的使用案例,本书讲解通俗易懂,适合初学者快速入门。
t-io是基于aio(nio2)的网络编程框架,和netty属于同类,但t-io更注重开发一线工程师的感受,提供了大量和业务相关的API。基于t-io来开发IM、TCP私有协议、RPC、游戏服务器端、推送服务、实时监控、物联网、UDP、...
jaca视频教程 jaca游戏服务器端开发 Netty NIO AIO Mina视频教程 课程目录: 一、Netty快速入门教程 01、第一课NIO 02、第二课netty服务端 03、第三课netty客户端 04、第四课netty线程模型源码分析(一) 05、...
netty的长连接.. 连接断开之后 自动重连demo
Android Studio 开发Netty网络访问框架,实现了客户端、服务端两种访问方式,支持发送心跳数据,使用Handler实现外部数据交互,有调用Demo,在实际项目中使用暂时没有问题
1、下载后导入eclipse(maven工程) 2、先运行ServerTest 3、再运行ClientTest,即可看到输出结果 4、保证可用,亲手编写,欢迎大家指正不足