给你一台4路E7-4820V2(32核心64线程),512G内存的服务器,你该如何编程才能支持百万长连接?

最直接的想法是采用BIO的模式,为每个连接新建一个线程,在一一对应的线程中直接处理连接上的数据请求。

但在Java中,新建线程的开销非常昂贵(默认情况下每个线程会占据1M多的内存,百万连接就是1T内存,这显然是不可接受的)

优化点的想法是使用Java NIO,用一个线程来处理所有客户端的请求。

但是根据我之前的测试,单个线程最多同时处理5w/s的echo message,此时单个core已经跑满,如果再接着加大负载会导致请求堆积。

进一步的优化是将线程分离,使用一个线程作为acceptor,一堆线程作为worker

acceptor监听服务端口的accept事件,如果有accept事件被触发,说明有客户端连接进来,acceptor获取连接(Channel)并将其分派给某个worker,worker监听这个Channel的read事件,一旦Channel可读,worker就会做出相应的处理。

也就是说将连接均分到各个worker,减轻压力,也可以让多个core被利用起来,使单机处理百万长连接成为可能。

这就是所谓Reactor模型了,也是Netty所采用的线程模型。(还有更进一步的主从多线程模型,用于处理认证较为耗时的情况,这里不做介绍)

借用一下Doug Lea老爷子的示例图:

用这个思想分析一下Netty的示例代码:

    public void go(int port) {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);//acceptor线程
EventLoopGroup workerGroup = new NioEventLoopGroup();//worker线程组
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
@Override
public void channelRead(ChannelHandlerContext ctx,
Object msg) { //ehco to client
ctx.write(msg);
ctx.flush();
}
});
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true); ChannelFuture f = b.bind(port).sync();
f.channel().closeFuture().sync();
} catch (Exception e) {
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}

可以猜出所谓的bossGroup就是Reactor模型中的acceptor,负责处理客户端产生的TCP连接请求,workerGroup则是worker,真正负责IO读写操作。具体实现我们后续再做分析。

Netty源码学习(一)Netty线程模型的更多相关文章

  1. 【Netty源码分析】Reactor线程模型

    1. 背景 1.1. Java线程模型的演进 1.1.1. 单线程 时间回到十几年前,那时主流的CPU都还是单核(除了商用高性能的小机),CPU的核心频率是机器最重要的指标之一. 在Java领域当时比 ...

  2. Netty源码分析之Reactor线程模型详解

    上一篇文章,分析了Netty服务端启动的初始化过程,今天我们来分析一下Netty中的Reactor线程模型 在分析源码之前,我们先分析,哪些地方用到了EventLoop? NioServerSocke ...

  3. 【Netty源码学习】ServerBootStrap

    上一篇博客[Netty源码学习]BootStrap中我们介绍了客户端使用的启动服务,接下来我们介绍一下服务端使用的启动服务. 总体来说ServerBootStrap有两个主要功能: (1)调用父类Ab ...

  4. Netty 源码学习——EventLoop

    Netty 源码学习--EventLoop 在前面 Netty 源码学习--客户端流程分析中我们已经知道了一个 EventLoop 大概的流程,这一章我们来详细的看一看. NioEventLoopGr ...

  5. Netty 源码学习——客户端流程分析

    Netty 源码学习--客户端流程分析 友情提醒: 需要观看者具备一些 NIO 的知识,否则看起来有的地方可能会不明白. 使用版本依赖 <dependency> <groupId&g ...

  6. Netty源码学习系列之4-ServerBootstrap的bind方法

    前言 今天研究ServerBootstrap的bind方法,该方法可以说是netty的重中之重.核心中的核心.前两节的NioEventLoopGroup和ServerBootstrap的初始化就是为b ...

  7. 【Netty源码学习】DefaultChannelPipeline(三)

    上一篇博客中[Netty源码学习]ChannelPipeline(二)我们介绍了接口ChannelPipeline的提供的方法,接下来我们分析一下其实现类DefaultChannelPipeline具 ...

  8. 【Netty源码学习】ChannelPipeline(一)

    ChannelPipeline类似于一个管道,管道中存放的是一系列对读取数据进行业务操作的ChannelHandler. 1.ChannelPipeline的结构图: 在之前的博客[Netty源码学习 ...

  9. Java并发包源码学习系列:线程池ScheduledThreadPoolExecutor源码解析

    目录 ScheduledThreadPoolExecutor概述 类图结构 ScheduledExecutorService ScheduledFutureTask FutureTask schedu ...

  10. JUC源码学习笔记5——线程池,FutureTask,Executor框架源码解析

    JUC源码学习笔记5--线程池,FutureTask,Executor框架源码解析 源码基于JDK8 参考了美团技术博客 https://tech.meituan.com/2020/04/02/jav ...

随机推荐

  1. grunt简记

    grunt和gulp都是前端自动化的工具,grunt更成熟,插件社区全.大:gulp比较年轻,性能更好,更简单容易.具体使用哪种可根据实际项目组来决定. 创建任务 grunt默认执行的是default ...

  2. groupNoAdj

    public boolean groupNoAdj(int start, int[] nums, int target) { if( start >= nums.length){ return ...

  3. unity3d中C#与JS的一些区别

    unity3d目前支持C#和JS两种脚本语言. 学习过程中发现很多教程使用的是JS语言,自己还是用C#比较多,unity原生使用的是Mono,使用C#会更加接近unity的编程思想. 1.方法的定义, ...

  4. 《Cracking the Coding Interview》——第9章:递归和动态规划——题目1

    2014-03-20 02:55 题目:小朋友跳台阶,每次跳1层或2层,那么跳N层总共有多少种跳法. 解法:斐波那契数列. 代码: // 9.1 A child can run up the stai ...

  5. asp.net 身份验证-Form 身份验证

    一. .net身份验证简介 1.身份验证就是检测用户是否登录及所访问的资源是否有权限.当我们在访问一个受保护网络资源时,往往需要输入用户名.密码信息,或通过其他证书.第三方身份验证等方式.验证(Aut ...

  6. .gitignore 中文文件夹无效

    有个文件夹名如:测试 在.gitignore中添加  /测试/   但运行命令git status后发现还是被追踪到了 一番搜索后终于发现.gitignore文件编码是GBK的,重新将文件保存成utf ...

  7. eclipse进阶功法

    先选择要操作的行,在同时按shift+alt+a,会将所选中的文字括起来,鼠标会变成十字图标,按住鼠标左键,在相应输入文字的位置上下拖动,会出现一个竖杠,此时即可开始输入文字了,并且所选中行都有.

  8. serial console

    适用于: agent_ipmitool_socat pxe_ipmitool_socat 修改driver方式:更换ironic node的driver类型 yum install -y socat ...

  9. 使用ADO.NET 实体数据模型连接MySql

    原文:使用ADO.NET 实体数据模型连接MySql 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/a123_z/article/details/8 ...

  10. Eclipse中一个Maven工程的目录结构 (MacOS)

    1. 为什么写这篇文章 在之前的javaSE开发中,没有很关注Eclipse工程目录下的环境,总是看见一个src就点进去新建一个包再写一个class.以后的日子中也没有机会注意到一个工程到底是怎么组织 ...