千家信息网

Netty NIO框架性能压测之如何实现长链接

发表于:2025-02-02 作者:千家信息网编辑
千家信息网最后更新 2025年02月02日,这篇文章将为大家详细讲解有关Netty NIO框架性能压测之如何实现长链接,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。压测准备需要将ulimit -n 改大,否则
千家信息网最后更新 2025年02月02日Netty NIO框架性能压测之如何实现长链接

这篇文章将为大家详细讲解有关Netty NIO框架性能压测之如何实现长链接,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

压测准备
  1. 需要将ulimit -n 改大,否则nio链接开不大。

  2. 准备4台机器(1台netty服务器,3台压测机)

  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 channel = new HashMap();         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     cachedMem:       4149076     189828    3959248          0      13196      95484-/+ buffers/cache:      81148    4067928Swap:      2096472        208    2096264Total:     6245548     190036    6055512 -- 执行 chat server之后             total       used       free     shared    buffers     cachedMem:       4149076     207236    3941840          0      13216      96244-/+ buffers/cache:      97776    4051300Swap:      2096472        208    2096264Total:     6245548     207444    6038104 -- 59471 个nio连接之后             total       used       free     shared    buffers     cachedMem:       4149076     474244    3674832          0      13328      96132-/+ buffers/cache:     364784    3784292Swap:      2096472        208    2096264Total:     6245548     474452    5771096

结论:

  1. Netty nio 可以轻松将链接开到6W,每个线程大概损坏5k左右的系统内存

后续压测方案
  1. 编写Java客户端做内容实时双向推送

  2. 使用100台机器每台机器起1000个线程来模拟客户端进行压测

关于"Netty NIO框架性能压测之如何实现长链接"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

0