精华内容
下载资源
问答
  • 单机百万连接调优 实现单机的百万连接,瓶颈有以下几点: 如何模拟百万连接 突破局部文件句柄的限制 突破全局文件句柄的限制 在linux系统里面,单个进程打开的句柄数是非常有限的,一条TCP连接就对应一个文件句柄,...

    单机百万连接调优
    实现单机的百万连接,瓶颈有以下几点:

    如何模拟百万连接
    突破局部文件句柄的限制
    突破全局文件句柄的限制
    在linux系统里面,单个进程打开的句柄数是非常有限的,一条TCP连接就对应一个文件句柄,而对于我们应用程序来说,一个服务端默认建立的连接数是有限制的。

    如何模拟百万连接


    如上图所示,当服务端开启一个端口,客户端去连接,除去固定的端口,最多只能实现单机6W的连接,实现单机百万连接,最简单的方法,就是启动十几个客户端,然后去连接同一个端口,但是比较麻烦的。

    在服务端启动800~8100,而客户端依旧使用1025-65535范围内可用的端口号,让同一个端口号,可以连接Server的不同端口。这样的话,6W的端口可以连接Server的100个端口,累加起来就能实现近600W左右的连接,TCP是以一个四元组概念,以原IP、原端口号、目的IP、目的端口号来确定的,所以TCP连接可以如此设计。

    突破局部文件句柄的限制
    ulimit -n
    /etc/security/limits.conf
    首先在终端输入ulimit -n,查看一个进程能够打开的最大文件数,一条TCP连接,对应Linux系统里面是一个文件,所以服务端最大连接数会受限于这个数字,然后,在/etc/security/limits.conf文件中配置如下两行:

    hard nofile 1000000
    soft nofile  1000000
    soft和hard为两种限制方式,其中soft表示警告的限制,hard表示真正限制,nofile表示打开的最大文件数。

    突破全局文件句柄的限制
    cat /proc/sys/fs/file-max
    etc/sysctl.conf
    cat /proc/sys/fs/file-max查看我所有进程能够打开的最大文件数是多少,TCP连接,每一个连接代表一个文件,局部的不能大过全局的限制,然后进入etc/sysctl.conf,在该配置文件中添加fs.file-max = 1000000,file-max表示全局文件句柄数的限制,这里我设置为100W。然后,我通过简单DEMO进行模仿连接,最终结果大约在94W左右。

    实例代码
    Client端
    public class Client {
     
        private static final String SERVER_HOST = "192.168.1.42";
     
        public static void main(String[] args) {
            new Client().start(BEGIN_PORT, N_PORT);
        }
     
        public void start(final int beginPort, int nPort) {
            System.out.println("client starting....");
            EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
            final Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(eventLoopGroup);
            bootstrap.channel(NioSocketChannel.class);
            bootstrap.option(ChannelOption.SO_REUSEADDR, true);
            bootstrap.handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) {
                }
            });
            int index = 0;
            int port;
            while (!Thread.interrupted()) {
                port = beginPort + index;
                try {
                    ChannelFuture channelFuture = bootstrap.connect(SERVER_HOST, port);
                    channelFuture.addListener((ChannelFutureListener) future -> {
                        if (!future.isSuccess()) {
                            System.out.println("connect failed, exit!");
                            System.exit(0);
                        }
                    });
                    channelFuture.get();
                } catch (Exception e) {
                }
     
                if (++index == nPort) {
                    index = 0;
                }
            }
        }
    }
    Server端
    public final class Server {
     
        public static void main(String[] args) {
            new Server().start(BEGIN_PORT, N_PORT);
        }
     
        public void start(int beginPort, int nPort) {
            System.out.println("server starting....");
     
            EventLoopGroup bossGroup = new NioEventLoopGroup();
            EventLoopGroup workerGroup = new NioEventLoopGroup();
     
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup);
            bootstrap.channel(NioServerSocketChannel.class);
            bootstrap.childOption(ChannelOption.SO_REUSEADDR, true);
     
            bootstrap.childHandler(new ConnectionCountHandler());
     
     
            for (int i = 0; i < nPort; i++) {
                int port = beginPort + i;
                bootstrap.bind(port).addListener((ChannelFutureListener) future -> {
                    System.out.println("bind success in port: " + port);
                });
            }
            System.out.println("server started!");
        }
    }
    其中,BEGIN_PORT 和 N_PORT分别为8000和100。

    Handler
    @Sharable
    public class ConnectionCountHandler extends ChannelInboundHandlerAdapter {
     
        private AtomicInteger nConnection = new AtomicInteger();
     
        public ConnectionCountHandler() {
            Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> {
                System.out.println("connections: " + nConnection.get());
            }, 0, 2, TimeUnit.SECONDS);
     
        }
     
        @Override
        public void channelActive(ChannelHandlerContext ctx) {
            nConnection.incrementAndGet();
        }
     
        @Override
        public void channelInactive(ChannelHandlerContext ctx) {
            nConnection.decrementAndGet();
        }
     
    }
    上述简单DEMO,用于利用端口进行的模拟百万连接,然后各位看官按照,我后面介绍的突破局部文件句柄和全局文件句柄,则能基本实现百万连接,具体连接数最终受限于你个人所用的电脑硬件配置。

    Netty应用级别性能调优
    在一般Netty项目中,如果在channelHandler里面做一些业务复杂操作,比如数据库或者网络操作,通常情况下,请求比较快,在百分之十或者百分之一左右,这操作是非常耗时的,这时候,需要把这操作放在单独的线程池去处理,调整线程数的大小应该是我们首先想到的方法,但线程数的大小最终也将会存在一个上限。

    接下来,我简单概述下Netty应用级别的调优方式:

    第一种方式,在handler里面,自己创建线程池,在执行具体代码的时候,只需要针对特定代码到线程池去处理,而其他操作仍可以在netty提供的线程池里完成。
    另一种方式,在添加handler的时候,直接指定一个线程池,而不需要在handler里面指定一个线程池,对业务代码是无侵入的,但方法里的每行操作都是在单独的线程池里面,假若在该线程池里的某个方法内做内存分配,则就只在该业务线程池里进行分配,无法做到内存的共享。

    展开全文
  • Netty实现单机百万连接和应用级别性能调优 如何模拟Ntty百万连接 通常启动一个服务端会绑定一个端口例如 8000,当客户端去连接端口是有限制的最大是65535加上默认1024及以下的端口,就剩下1024-65535再扣除一些...

     

     

    Netty实现单机百万连接和应用级别性能调优

    如何模拟Ntty百万连接

    通常启动一个服务端会绑定一个端口例如 8000,当客户端去连接端口是有限制的最大是65535加上默认1024及以下的端口,就剩下1024-65535再扣除一些常用的端口,实际可用端口只有6W左右。那么如何实现单机百万连接?

    我们在服务端启动例如 8000-8100 这100个端口,100*6W这样就可以连接600W左右的连接,这里是TPC的一个基础的知识,虽然对于客户端来说是同一个端口号,但是对于Server是不同的端口号,由于TCP是一个私源组概念,也就是说它是由源IP源端口号加上目的IP目的端口号为确定的,当你源IP和源端口号是一样的但是你目的端口号不一样那么最终系统底层会把它当做两条TCP连接来处理,所以说我们这里取了个巧开了Server开启了100个端口号,这就是我们单机百万连接的准备工作,接下来看一下代码的实现

     

    统计时间Hanlder

    @Sharable
    public class ConnectionCountHandler extends ChannelInboundHandlerAdapter {
    
        private AtomicInteger nConnection = new AtomicInteger();
    
        public ConnectionCountHandler() {
            Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> {
                System.out.println("connections: " + nConnection.get());
            }, 0, 2, TimeUnit.SECONDS);
    
        }
    
        @Override
        public void channelActive(ChannelHandlerContext ctx) {
            nConnection.incrementAndGet();
        }
    
        @Override
        public void channelInactive(ChannelHandlerContext ctx) {
            nConnection.decrementAndGet();
        }
    
    }
    public class Constant {
        static final int BEGIN_PORT = 8000;
        static final int N_PORT = 100;
    }

     

    服务端

    public final class Server {
    
        public static void main(String[] args) {
            new Server().start(BEGIN_PORT, N_PORT);
        }
    
        public void start(int beginPort, int nPort) {
            System.out.println("server starting....");
    
            EventLoopGroup bossGroup = new NioEventLoopGroup();
            EventLoopGroup workerGroup = new NioEventLoopGroup();
    
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup);
            bootstrap.channel(NioServerSocketChannel.class);
            bootstrap.childOption(ChannelOption.SO_REUSEADDR, true);
    
            bootstrap.childHandler(new ConnectionCountHandler());
    
    
            for (int i = 0; i < nPort; i++) {
                int port = beginPort + i;
                bootstrap.bind(port).addListener((ChannelFutureListener) future -> {
                    System.out.println("bind success in port: " + port);
                });
            }
            System.out.println("server started!");
        }
    }


           

     

    客户端

    public class Client {
    
        private static final String SERVER_HOST = "192.168.1.42";
    
        public static void main(String[] args) {
            new Client().start(BEGIN_PORT, N_PORT);
        }
    
        public void start(final int beginPort, int nPort) {
            System.out.println("client starting....");
            EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
            final Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(eventLoopGroup);
            bootstrap.channel(NioSocketChannel.class);
            bootstrap.option(ChannelOption.SO_REUSEADDR, true);
            bootstrap.handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) {
                }
            });
    
    
            int index = 0;
            int port;
            while (!Thread.interrupted()) {
                port = beginPort + index;
                try {
                    ChannelFuture channelFuture = bootstrap.connect(SERVER_HOST, port);
                    channelFuture.addListener((ChannelFutureListener) future -> {
                        if (!future.isSuccess()) {
                            System.out.println("connect failed, exit!");
                            System.exit(0);
                        }
                    });
                    channelFuture.get();
                } catch (Exception e) {
                }
    
                if (++index == nPort) {
                    index = 0;
                }
            }
        }
    }

    我们将程序 Server打包到centos6.5系统上   配置是 CPU 4核 8G

    同样我们将程序 Client 打包另一台到centos6.5系统上  配置是 同样CPU 4核 8G

    然后我们在同目录下创建一个叫start.sh的程序

    java -jar server.jar 
    
    -Xms6.5
    
    -Xmx6.5
    -XX:NewSize=5.5g
    -XX:MaxnewSize=5.5g
    -XX:MaxDirectMemorySize=1g
    

    给JVM配置 6.5个G的堆内存和新生代5.5个G

    然后我们 ./start.sh启动服务端

    服务端会打印出Log

    bind success in port:8000

    bind success in port:8099 的log

    当前连接数为0

    connections:0

    然后运行客户端 ./start.sh

    此时回到服务端查看输出的日志是 connections:870一直就是870,

    也就是服务端最大支持到870个连接。

    突破局部文件句柄限制

    首先我们在server端的服务器上输入命令

    ulimit -n

    会出现1024的数字,表示linux一个进程能够打开的最文件数,由于一个TCP连接会对应linux系统的一个文件,所以我们就是受限于这个文件最大文件限制,为什么服务端连接数是870那,是因为除了连接数还有JVM打开的文件是我们的class类,1024扣去我们JVM打开的文件数剩下就是我们TCP的连接数。

    接下来我们来突破这个限制

    sudo vi /etc/security/limits.conf

     

    然后在这个文件末尾加上两行

    * hard nofile 1000000

    * soft nofile   1000000

    然后我们重启server服务器

     

    最终连接数停留在 9391

    这是为什么那,肯定是还有地方限制了连接数

    突破全局文件句柄限制

    cat /proc/sys/fs/file-max

    通过上面这个命令可以看到全局的限制

    看到我们这个liunx内核的限制是1W,不同的linux内核或者发行版本是不一样的,现在我们需要突破这个限制

    首先我们切换为root用户不然没有权限

    sudo  -s
    echo 2000> /proc/sys/fs/file-max
    exit

    我们首先改成20000个我们测试一下

    然后我们继续试验 启动我们的Server端 然后在启动我们的客户端

    最终停留在19356个连接数

    使用echo 来配置的  的话重启服务器就会 echo 2000> /proc/sys/fs/file-max 就会失效 还会变回原来的 10000

    我们需要修改 /etc/sysctl.conf

    sodu vi /etc/sysctl.conf
    

    我们在文件末尾加上

    fs.file-max=1000000

    接下来我们重启 liunx服务器

    然后我们启动服务器 然后启动客户端

    突破10W

    最终连接数定格在 94W左右

    然后我们看一下什么原因

    输入一下命令 htop 查看一下

    我们4个CPU都接近100%了所以没办法创建了,受限于我本机的机器性能。

    Netty应用级别的性能调优

    首先我们标准的应用程序代码

    服务端

    public class Server {
    
        public static void main(String[] args) {
    
            EventLoopGroup bossGroup = new NioEventLoopGroup();
            EventLoopGroup workerGroup = new NioEventLoopGroup();
    
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup);
            bootstrap.channel(NioServerSocketChannel.class);
            bootstrap.childOption(ChannelOption.SO_REUSEADDR, true);
    
    
            bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) {
                    ch.pipeline().addLast(new FixedLengthFrameDecoder(Long.BYTES));
                    ch.pipeline().addLast(ServerBusinessHandler.INSTANCE);
    //                ch.pipeline().addLast(ServerBusinessThreadPoolHandler.INSTANCE);
                }
            });
    
    
            bootstrap.bind(PORT).addListener((ChannelFutureListener) future -> System.out.println("bind success in port: " + PORT));
        }
    
    }
    @ChannelHandler.Sharable
    public class ServerBusinessHandler extends SimpleChannelInboundHandler<ByteBuf> {
        public static final ChannelHandler INSTANCE = new ServerBusinessHandler();
    
    
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) {
            ByteBuf data = Unpooled.directBuffer();
            data.writeBytes(msg);
            Object result = getResult(data);
            ctx.channel().writeAndFlush(result);
        }
    
        protected Object getResult(ByteBuf data) {
            // 90.0% == 1ms
            // 95.0% == 10ms  1000 50 > 10ms
            // 99.0% == 100ms 1000 10 > 100ms
            // 99.9% == 1000ms1000 1 > 1000ms
            int level = ThreadLocalRandom.current().nextInt(1, 1000);
    
            int time;
            if (level <= 900) {
                time = 1;
            } else if (level <= 950) {
                time = 10;
            } else if (level <= 990) {
                time = 100;
            } else {
                time = 1000;
            }
    
            try {
                Thread.sleep(time);
            } catch (InterruptedException e) {
            }
    
            return data;
        }
    
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            // ignore
        }
    }

    客户端

    public class Client {
    
        private static final String SERVER_HOST = "127.0.0.1";
    
        public static void main(String[] args) throws Exception {
            new Client().start(PORT);
        }
    
        public void start(int port) throws Exception {
            EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
            final Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(eventLoopGroup);
            bootstrap.channel(NioSocketChannel.class);
            bootstrap.option(ChannelOption.SO_REUSEADDR, true);
            bootstrap.handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) {
                    ch.pipeline().addLast(new FixedLengthFrameDecoder(Long.BYTES));
                    ch.pipeline().addLast(ClientBusinessHandler.INSTANCE);
                }
            });
    
            for (int i = 0; i < 1000; i++) {
                bootstrap.connect(SERVER_HOST, port).get();
            }
        }
    }
    
    @ChannelHandler.Sharable
    public class ClientBusinessHandler extends SimpleChannelInboundHandler<ByteBuf> {
        public static final ChannelHandler INSTANCE = new ClientBusinessHandler();
    
        private static AtomicLong beginTime = new AtomicLong(0);
        private static AtomicLong totalResponseTime = new AtomicLong(0);
        private static AtomicInteger totalRequest = new AtomicInteger(0);
    
        public static final Thread THREAD = new Thread(() -> {
            try {
                while (true) {
                    long duration = System.currentTimeMillis() - beginTime.get();
                    if (duration != 0) {
                        System.out.println("qps: " + 1000 * totalRequest.get() / duration + ", " + "avg response time: " + ((float) totalResponseTime.get()) / totalRequest.get());
                        Thread.sleep(2000);
                    }
                }
    
            } catch (InterruptedException ignored) {
            }
        });
    
        @Override
        public void channelActive(ChannelHandlerContext ctx) {
            ctx.executor().scheduleAtFixedRate(() -> {
    
                ByteBuf byteBuf = ctx.alloc().ioBuffer();
                byteBuf.writeLong(System.currentTimeMillis());
                ctx.channel().writeAndFlush(byteBuf);
    
            }, 0, 1, TimeUnit.SECONDS);
        }
    
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) {
            totalResponseTime.addAndGet(System.currentTimeMillis() - msg.readLong());
            totalRequest.incrementAndGet();
    
            if (beginTime.compareAndSet(0, System.currentTimeMillis())) {
                THREAD.start();
            }
        }
    
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            // ignore
        }
    }
    public class Constant {
        public static final int PORT = 8000;
    }
    

    上面的代码主要模拟了,Netty真实业务环境下的处理耗时和QPS

    我们启动服务器和客户端查看一下log

    真实的环境下我们的耗时时间越来越长

    首先我们服务端的Hander getResult方法就是我们模拟真是环境下的 例如 数据库读写,网络请求等等耗时的操作,

    最终性能都是在getResult这里被堵住了。

    Object result =getResult(data);

    ctx.channel().wrteAndFlush(result);

    这两行代码是把它扔到我们业务线程池里,业务线程池里面可以不断在后台运行运行完了给我们返回结果。

    我们改造一下代码

    在Server端代码中 

     

     

    我们新建一个Hander

    public class ServerBusinessThreadPoolHandler extends ServerBusinessHandler {
        public static final ChannelHandler INSTANCE = new ServerBusinessThreadPoolHandler();
        private static ExecutorService threadPool = Executors.newFixedThreadPool(1000);
    
    
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) {
            ByteBuf data = Unpooled.directBuffer();
            data.writeBytes(msg);
            threadPool.submit(() -> {
                Object result = getResult(data);
                ctx.channel().writeAndFlush(result);
            });
    
        }
    }
     ch.pipeline().addLast(ServerBusinessThreadPoolHandler.INSTANCE);

    然后我们在Server端添加注册这个Hander 

    注释掉原来的Hander

    然后我们启动程序查看性能

    最终耗时稳定在 250ms左右

           // 90.0% == 1ms
            // 95.0% == 10ms  1000 50 > 10ms
            // 99.0% == 100ms 1000 10 > 100ms
            // 99.9% == 1000ms1000 1 > 1000ms

    接下来继续调整,我们调整Hander的线程个数 我们吧业务线程调整到 20个线程

    然后我们启动程序

    现在我们QPS 1000左右 耗时在 18毫秒左右

    继续观察,由于有时候会被其他线程耗时堵着就会造成整体时间拉长。

    现在稳定在30-40毫秒左右

    继续调整线程数现在我们吧线程数调整为30

    然后我们启动程序观察

    这次耗时最终稳定在 15毫秒左右

    继续调整把线程数调为50

    耗时稍微高一点。

    具体的线程数我们需要在真实的环境下不断的调整来测试,这个需要我们一直不断的调整来测试,最终才能找到最合适的。

    展开全文
  • 19年架构师系列之高并发Netty教程打造单机百万连接架构视频
  • 19年架构师系列之高并发Netty教程打造单机百万连接架构视频 7年的开发架...

    扫码下载「CSDN程序员学院APP」,1000+技术好课免费看

    APP订阅课程,领取优惠,最少立减5元 ↓↓↓

    订阅后:请点击此处观看视频课程

     

    视频教程-19年架构师系列之高并发Netty教程打造单机百万连接架构视频-Java

    学习有效期:永久观看

    学习时长:642分钟

    学习计划:11天

    难度:

     

    口碑讲师带队学习,让你的问题不过夜」

    讲师姓名:张颜源

    开发组长/高级工程师/技术专家

    讲师介绍:7年的开发架构经验,曾就职于国内一线互联网公司,开发工程师,现在是某创业公司技术负责人, 擅长语言有node/java/python,专注于服务端研发,人工智能相关领域, 熟悉分布式高可用系统的架构,大数据处理,微信开放平台支付等业务

    ☛点击立即跟老师学习☚

     

    「你将学到什么?」

    高并发系列之百万连接Netty实战视频教程是2019年1月份录制,采用Netty4.X新版本+JDK8+IDEA,分为10章40多集,从零基础入门Netty到高级使用,最后项目实战打造单机支持百万连接的Netty服务及Linux内核参数优化;里面包含BAT经典面试题和知识拓展,还有赠送Netty文档干货资料,讲师技术交流群等,加客服QQ351228901

     

    「课程学习目录」

    第1章:高并发编程Netty实战课程介绍
    1.1-1高并发编程Netty框架实战课程介绍
    2.1-2异步事件驱动NIO框架Netty介绍
    3.1-3高并发编程Netty实战课程开发环境准备
    第2章:使用JDK自带BIO编写一个Client-Server通信
    1.2-1BIO网络编程实战之编写BioServer服务端
    2.2-2BIO网络编程实战之编写BioClient客服端
    3.2-3BIO编写Client/Server通信优缺点分析
    第3章:(面试核心)服务端网络编程常见网络IO模型讲解
    1.3-1最通俗的方式讲解 什么是阻塞/非阻塞,什么是同/异步
    2.3-2(BAT面试核心知识)Linux网络编程中的五种I/O模型讲解上集
    3.3-3(BAT面试核心知识)Linux网络编程中的五种I/O模型讲解下集
    4.3-4高并发编程必备知识IO多路复用技术select、poll讲解
    5.3-5高并发编程必备知识IO多路复用技术Epoll讲解和总结
    6.3-6Java的I/O演进历史
    7.3-7大话Netty线程模型和Reactor模式
    第4章:高并发网络编程Netty的第一个案例
    1.4-1讲解什么是Echo服务和Netty项目搭建
    2.4-2Netty实战之Echo服务-服务端程序编写实战
    3.4-3Netty实战之Echo服务-客户端程序编写实战
    4.4-4Netty实战之Echo服务演示和整个流程分析
    第5章:Netty案例实战分析之核心链路源码讲解
    1.5-1深入剖析EventLoop和EventLoopGroup线程模型
    2.5-2Netty启动引导类Bootstrap模块讲解
    3.5-3Netty核心组件Channel模块讲解
    4.5-4ChannelHandler和ChannelPipeline模块讲解
    5.5-5Netty核心模块指ChannelHandlerContext模块讲解
    6.5-6Netty案例实战常见问题之入站出站Handler执行顺序
    7.5-7Netty异步操作模块ChannelFuture讲解
    第6章:高并发架构之Netty网络数据传输编解码精讲
    1.6-1Netty网络传输知识之什么是编码、解码
    2.6-2数据协议处理之Netty解码器Decoder讲解
    3.6-3数据协议处理之Netty编码器Encoder讲解
    4.6-4数据协议处理之Netty编解码器类Codec讲解
    第7章:Netty核心知识之网络传输TCP粘包拆包
    1.7-1网络编程核心知识之TCP粘包拆包讲解
    2.7-2TCP半包读写常见解决方案
    3.7-3Netty自带解决TCP半包读写方案
    4.7-4Netty案例实战之半包读写问题演示
    5.7-5Netty案例实战之LineBasedFrameDecoder解决TCP半包读写
    6.7-6Netty案例实战之自定义分隔符解决TCP读写问题
    7.7-7自定义长度半包读写器LengthFieldBasedFrameDecoder讲解
    第8章:Netty源码分析之基础数据传输讲解和设计模式
    1.8-1Netty核心模块缓冲ByteBuf
    2.8-2Netty数据存储模块ByteBuf创建方法和常用的模式
    3.8-3Netty里面的设计模式应用分析
    第9章:使用Netty搭建单机百万连接测试实战
    1.9-1搭建单机百万连接的服务器实例的必备知识
    2.9-2Netty单机百万连接实战之服务端代码编写
    3.9-3Netty单机百万连接实战之客户端代码编写
    4.9-4阿里云服务器Netty单机百万连接部署实战
    5.9-5Netty单机百万连接Linux内核参数优化
    6.9-6互联网架构数据链路分析总结
    第10章:高并发系列之百万连接Netty实战课程总结
    1.高并发系列之百万连接Netty实战课程总结

     

    7项超值权益,保障学习质量」

    • 大咖讲解

    技术专家系统讲解传授编程思路与实战。

    • 答疑服务

    专属社群随时沟通与讲师答疑,扫清学习障碍,自学编程不再难。

    • 课程资料+课件

    超实用资料,覆盖核心知识,关键编程技能,方便练习巩固。(部分讲师考虑到版权问题,暂未上传附件,敬请谅解)

    • 常用开发实战

    企业常见开发实战案例,带你掌握Python在工作中的不同运用场景。

    • 大牛技术大会视频

    2019Python开发者大会视频免费观看,送你一个近距离感受互联网大佬的机会。

    • APP+PC随时随地学习

    满足不同场景,开发编程语言系统学习需求,不受空间、地域限制。

     

    「什么样的技术人适合学习?」

    • 想进入互联网技术行业,但是面对多门编程语言不知如何选择,0基础的你
    • 掌握开发、编程技术单一、冷门,迫切希望能够转型的你
    • 想进入大厂,但是编程经验不够丰富,没有竞争力,程序员找工作难。

     

    「悉心打造精品好课,11天学到大牛3年项目经验」

    【完善的技术体系】

    技术成长循序渐进,帮助用户轻松掌握

    掌握Java知识,扎实编码能力

    【清晰的课程脉络】

    浓缩大牛多年经验,全方位构建出系统化的技术知识脉络,同时注重实战操作。

    【仿佛在大厂实习般的课程设计】

    课程内容全面提升技术能力,系统学习大厂技术方法论,可复用在日后工作中。

     

    「你可以收获什么?」

    Netty零基础到高级教程

    基础知识+项目实战

     

    展开全文
  • 高并发系列之百万连接Netty实战视频教程是2019年1月份录制,采用Netty4.X新版本+JDK8+IDEA,分为10章40多集,从零基础入门Netty到高级使用,最后项目实战打造单机支持百万连接的Netty服务及Linux内核参数优化;...

    立即学习:https://edu.csdn.net/course/play/10634/237504?utm_source=blogtoedu

    单机百万连接Linux参数优化

    文件句柄沾满:Too many open files

    服务端FD数:

    • ulimit -n,局部文件句柄限制(单个进程最大FD(打开文件)数)不同系统有不同的默认值
    • 修改vim /etc/security/limits.conf
    • soft nofile 1000000
    • hard nofile 1000000
    • 重启生效
    • 全局FD数(所有进程最大打开的文件数,不同系统是不一样,可以直接echo 临时修改)
    • 查看命令:cat /proc/sys/fs/file-max
    • 永久修改全局文件句柄:vim /etc/sysctl.conf
    • 在最底部加入:fs.file-max = 1000000
    • 立刻生效:sysctl -p
    • reboot重启

    客户端同理修改并重启

     

    分配堆栈空间

    -Xms2.5g 最大堆内存(5g)

    -Xmx2.5g 最小堆内存(5g)

    -XX:NewSize=1g 新生代(3g)

    -XX:MaxNewSize=1g(3g)

     

    启动服务端和客户端

     

    lsof -i:8010 查看占用8010的连接数有多少

     

    展开全文
  • 高并发系列之百万连接Netty实战视频教程是2019年1月份录制,采用Netty4.X新版本+JDK8+IDEA,分为10章40多集,从零基础入门Netty到高级使用,最后项目实战打造单机支持百万连接的Netty服务及Linux内核参数优化;...
  • 高并发系列之百万连接Netty实战视频教程是2019年1月份录制,采用Netty4.X新版本+JDK8+IDEA,分为10章40多集,从零基础入门Netty到高级使用,最后项目实战打造单机支持百万连接的Netty服务及Linux内核参数优化;...
  • 高并发系列之百万连接Netty实战视频教程是2019年1月份录制,采用Netty4.X新版本+JDK8+IDEA,分为10章40多集,从零基础入门Netty到高级使用,最后项目实战打造单机支持百万连接的Netty服务及Linux内核参数优化;...
  • Netty_单机百万连接调优

    千次阅读 2018-10-10 17:43:27
    文章目录突破局部文件句柄限制1. 查看当前局部文件句柄限制2. 修改文件3. 添加内容:突破全局文件句柄限制1. 查看全局文件句柄限制2. 临时修改3. 永久修改4. 文件末尾,添加内容5.... 突破局部文件句柄限制 ...
  • 单机百万连接调优(Netty Demo)

    千次阅读 2019-05-13 17:40:30
    Netty Demo Constant.java public class Constant { static final int BEGIN_PORT = 8000; static final int N_PORT = 100;...Netty_单机百万连接调优 单服务器最大tcp连接数及调优汇总
  • 最近在用go语言做一个挂载大量长连接的推送服务器,虽然已经完成,但是内存占用情况让我不怎么满意,... 对于comet来说,单机能支撑大量的并发连接,是最优先考虑的事项。虽然现在业界已经有了很多数据,说单机支撑2...
  • 点击上方蓝字"开发内功修炼",关注并设为星标飞哥的硬核文章将第一时间送达~~~很多读者在看完百万 TCP 连接的系列文章之后,反馈问我有没有测试源码。也想亲自动手做出来体验...
  • 高并发系列之百万连接Netty实战视频教程是2019年1月份录制,采用Netty4.X新版本+JDK8+IDEA,分为10章40多集,从零基础入门Netty到高级使用,最后项目实战打造单机支持百万连接的Netty服务及Linux内核参数优化;...
  • 高并发系列之百万连接Netty实战视频教程是2019年1月份录制,采用Netty4.X新版本+JDK8+IDEA,分为10章40多集,从零基础入门Netty到高级使用,最后项目实战打造单机支持百万连接的Netty服务及Linux内核参数优化;...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,723
精华内容 3,089
关键字:

单机百万连接