让Netty Linux 突破100万的连接量

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了让Netty Linux 突破100万的连接量相关的知识,希望对你有一定的参考价值。

参考技术A 链接:https://www.jianshu.com/p/490e2981545c

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

1、如何模拟百万连接

2、突破局部文件句柄的限制

3、突破全局文件句柄的限制

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

下面通过优化要突破这个连接数。

优化

1、局部文件句柄限制

一个jvm进程最大能够打开的文件数.png

修改65535的这个限制

vi /etc/security/limits.conf

在文件末尾添加两行

*hard nofile 1000000

 soft nofile  1000000

soft和hard为两种限制方式,其中soft表示警告的限制,hard表示真正限制,nofile表示打开的最大文件数。整体表示任何用户一个进程能够打开1000000个文件。注意语句签名有

号 表示任何用户

shutdown -r now  重启linux

再次查看

已经修改生效了。

测试

最大连接数10万多.png

2、突破全局文件句柄的限制

cat /proc/sys/fs/file-max

file-max 表示在linux 中最终所有x线程能够打开的最大文件数

修改这个最大值:

sudo vi  /etc/sysctl.conf

在文件的末尾添加 fs.file-max=1000000

然后让文件生效 sudo sysctl -p

这个时候再查看一下全局最大文件句柄的数已经变成1000000了

测试

最大连接数36万多.png

注: 测试的服务器型号

cpu 相关配置

Java并发——Netty线程模型


BIO

Java并发——Netty线程模型

1.BIO即阻塞式IO,使用BIO模型,一般会为每个Socket分配一个独立的线程

  • 为了避免频繁创建和销毁线程,可以采用线程池,但Socket和线程之间的对应关系不会发生变化

2.BIO适用于Socket连接不是很多的场景,但现在上百万的连接是很常见的,而创建上百万个线程是不现实的

  • 因此BIO线程模型无法解决百万连接的问题

3.在互联网场景中,连接虽然很多,但每个连接上的请求并不频繁,因此线程大部分时间都在等待IO就绪


理想的线程模型

Java并发——Netty线程模型

1.用一个线程来处理多个连接,可以提高线程的利用率,降低所需要的线程

2.使用BIO相关的API是无法实现的,BIO相关的Socket读写操作都是阻塞式的

  • 一旦调用了阻塞式的API,在IO就绪前,调用线程会一直阻塞,也就无法处理其他的Socket连接

3.利用NIO相关的API能够实现一个线程处理多个连接,通过Reactor模式实现


Reactor模式

Java并发——Netty线程模型

1.Handle指的是IO句柄,在Java网络编程里,本质上是一个网络连接

2.Event Handler是事件处理器,handle_event()处理IO事件,每个Event Handler处理一个IO Handle

  • get_handle()方法可以返回这个IO Handle

  1. Synchronous Event Demultiplexer相当于操作系统提供的IO多路复用API

  • 例如POSIX标准里的select()以及Linux里的epoll()

4.Reactor是Reactor模式的核心

  • register_handler()和remove_handler()可以注册和删除一个事件处理器

  • handle_events()是核心

    • 通过同步事件多路选择器提供的select()方法监听网络事件

    • 当有网络事件就绪后,就遍历事件处理器来处理该网络事件

void Reactor::handle_events(){ // 通过同步事件多路选择器提供的select()方法监听网络事件 select(handlers); // 处理网络事件 for(h in handlers){ h.handle_event(); }}// 在主程序中启动事件循环while (true) { handle_events();}



Netty的线程模型


1.Netty参考了Reactor模式,Netty中最核心的概念是事件循环(EventLoop),即Reactor模式中的Reactor

  • 负责监听网络事件并调用事件处理器进行处理

  1. 在Netty 4.x中,网络连接 : EventLoop : Java线程 = N:1:1

  • 所以,一个网络连接只会对应到一个Java线程

  • 优点:对于一个网络连接的事件处理都是单线程的,这样能避免各种并发问题

EventLoopGroup

1.EventLoopGroup由一组EventLoop组成

  • 实际使用中,一般会创建两个EventLoopGroup,一个是bossGroup,一个是workerGroup

2.Socket处理TCP网络连接请求,是在一个独立的Socket中

  • 每当有一个TCP连接成功建立,都会创建一个新的Socket

  • 之后对TCP连接的读写都是由新创建处理的Socket完成的

  • 处理TCP连接请求和读写请求是通过两个不同的Socket完成的

3.在Netty中,bossGroup用来处理连接请求的,workerGroup用来处理读写请求的

  • bossGroup处理完连接请求后,会将这个连接提交给workerGroup来处理

  • workerGroup中会有多个EventLoop,通过均衡负载算法(轮询)来分配某一个EventLoop


Echo程序

public class Echo {
public static void main(String[] args) { // 事件处理器 EchoServerHandler serverHandler = new EchoServerHandler(); // boss线程组 EventLoopGroup bossGroup = new NioEventLoopGroup(1); // worker线程组 EventLoopGroup workerGroup = new NioEventLoopGroup(1);
try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast(serverHandler); } }); // 绑定端口号 ChannelFuture future = bootstrap.bind(9090).sync(); future.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { // 终止worker线程组 workerGroup.shutdownGracefully(); // 终止boss线程组 bossGroup.shutdownGracefully(); } }}
// Socket连接处理器class EchoServerHandler extends ChannelInboundHandlerAdapter {
// 处理读事件 @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ctx.write(msg); }
// 处理读完成事件 @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); }
// 处理异常事件 @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); }}


写在最后


以上是关于让Netty Linux 突破100万的连接量的主要内容,如果未能解决你的问题,请参考以下文章

java Netty NIO 如何突破 65536 个端口的限制?如何做到 10万~50万 长连接?

如何让单机下Netty支持百万长连接?

100万并发连接服务器笔记之Java Netty处理1M连接会怎么样

Java并发——Netty线程模型

netty如何处理同一个端口上来的多条不同协议的数据,不分端口的情况下。

netty系列之:让TCP连接快一点,再快一点