转载:Netty(二) 从线程模型的角度看 Netty 为什么是高性能的?

传统 IO

在 Netty 以及 NIO 出现之前,我们写 IO 应用其实用的都是用 java.io.* 下所提供的包。

比如下面的伪代码:

ServeSocket serverSocket = new ServeSocket(8080);
Socket socket = serverSocket.accept() ;
BufferReader in = .... ; String request ; while((request = in.readLine()) != null){
new Thread(new Task()).start()
}

大概是这样,其实主要想表达的是:这样一个线程只能处理一个连接

如果是 100 个客户端连接那就得开 100 个线程,1000 那就得 1000 个线程。

要知道线程资源非常宝贵,每次的创建都会带来消耗,而且每个线程还得为它分配对应的栈内存。

即便是我们给 JVM 足够的内存,大量线程所带来的上下文切换也是受不了的。

并且传统 IO 是阻塞模式,每一次的响应必须的是发起 IO 请求,处理请求完成再同时返回,直接的结果就是性能差,吞吐量低。

Reactor 模型

因此业界常用的高性能 IO 模型是 Reactor

它是一种异步、非阻塞的事件驱动模型。

通常也表现为以下三种方式:

单线程

从图中可以看出:

它是由一个线程来接收客户端的连接,并将该请求分发到对应的事件处理 handler 中,整个过程完全是异步非阻塞的;并且完全不存在共享资源的问题。所以理论上来说吞吐量也还不错。

但由于是一个线程,对多核 CPU 利用率不高,一旦有大量的客户端连接上来性能必然下降,甚至会有大量请求无法响应。
最坏的情况是一旦这个线程哪里没有处理好进入了死循环那整个服务都将不可用!

多线程

因此产生了多线程模型。

其实最大的改进就是将原有的事件处理改为了多线程。

可以基于 Java 自身的线程池实现,这样在大量请求的处理上性能提示是巨大的。

虽然如此,但理论上来说依然有一个地方是单点的;那就是处理客户端连接的线程。

因为大多数服务端应用或多或少在连接时都会处理一些业务,如鉴权之类的,当连接的客户端越来越多时这一个线程依然会存在性能问题。

于是又有了下面的线程模型。

主从多线程

该模型将客户端连接那一块的线程也改为多线程,称为主线程。

同时也是多个子线程来处理事件响应,这样无论是连接还是事件都是高性能的。

Netty 实现

以上谈了这么多其实 Netty 的线程模型与之的类似。

boss 就相当于 Reactor 模型中处理客户端连接的线程池。

work 自然就是处理事件的线程池了。

那么如何来实现上文的三种模式呢?其实也很简单:

单线程模型:

private EventLoopGroup group = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap()
.group(group)
.childHandler(new HeartbeatInitializer());

多线程模型:

private EventLoopGroup boss = new NioEventLoopGroup(1);
private EventLoopGroup work = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap()
.group(boss,work)
.childHandler(new HeartbeatInitializer());

主从多线程:

private EventLoopGroup boss = new NioEventLoopGroup();
private EventLoopGroup work = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap()
.group(boss,work)
.childHandler(new HeartbeatInitializer());

总结

其实看过了 Netty 的线程模型之后能否对我们平时做高性能应用带来点启发呢?

我认为是可以的:

  • 接口同步转异步处理。
  • 回调通知结果。
  • 多线程提高并发效率。

无非也就是这些,只是做了这些之后就会带来其他问题:

  • 异步之后事务如何保证?
  • 回调失败的情况?
  • 多线程所带来的上下文切换、共享资源的问题。

这就是一个博弈的过程,想要做到一个尽量高效的应用是需要不断磨合试错的。

重要注意点

boss 线程池是处理 accept事件的,不管线程池多大,只会使用一个线程,既然只使用一个线程为什么要用线程池呢?主要是异常的情况下,线程die了,可以再创建一个新线程,epoll模型知道吗?那什么情况下boss线程池可以使用多个线程呢?那就是当ServerBootstrap bind多个端口时。每个端口都有一个线程eventloop accept事件。

从线程模型的角度看Netty的高性能的更多相关文章

  1. Netty(二) 从线程模型的角度看 Netty 为什么是高性能的?

    前言 在之前的 SpringBoot 整合长连接心跳机制 一文中认识了 Netty. 但其实只是能用,为什么要用 Netty?它有哪些优势?这些其实都不清楚. 本文就来从历史源头说道说道. 传统 IO ...

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

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

  3. Netty系列之Netty线程模型

    Reference: http://www.infoq.com/cn/articles/netty-threading-model 1. 背景 1.1. Java线程模型的演进 1.1.1. 单线程 ...

  4. netty源码解解析(4.0)-4 线程模型-概览

    netty线程体系概览 netty的高并发能力很大程度上由它的线程模型决定的,netty定义了两种类型的线程: I/O线程: EventLoop, EventLoopGroup.一个EventLoop ...

  5. 深入Netty逻辑架构,从Reactor线程模型开始

    本文是Netty系列第6篇 上一篇文章我们从一个Netty的使用Demo,了解了用Netty构建一个Server服务端应用的基本方式.并且从这个Demo出发,简述了Netty的逻辑架构,并对Chann ...

  6. 看我是如何处理自定义线程模型---java

    看过我之前文章的园友可能知道我是做游戏开发,我的很多思路和出发点是按照游戏思路来处理的,所以和web的话可能会有冲突,不相符合. 来说说为啥我要自定义线程模型呢? 按照我做的mmorpg或者mmoar ...

  7. Java后端进阶-网络编程(Netty线程模型)

    前言 我们在使用Netty进行服务端开发的时候,一般来说会定义两个NioEventLoopGroup线程池,一个"bossGroup"线程池去负责处理客户端连接,一个"w ...

  8. Vert.x 线程模型揭秘

    来源:鸟窝, colobu.com/2016/03/31/vertx-thread-model/ 如有好文章投稿,请点击 → 这里了解详情 Vert.x是一个在JVM开发reactive应用的框架,可 ...

  9. 【C#】COM线程模型-套间 ApartmentState

    线程模式是微软的COM基础中的极其重要的概念.一定要吃透!初始一个STA套间实际上是相当于开了一个消息窗口,所有调用经此窗口过程调度到组件内. [STAThread] 可以理解成CoInitializ ...

随机推荐

  1. 异步加载script,提高前端性能(defer和async属性的区别)

    一.异步加载script的好处 为了加快首屏响应速度,前端会采用代码切割.按需加载等方式优化性能.异步加载script也是一种前端优化的手段. 就好比如果我的页面其中一个功能需要打开地图,但是地图的j ...

  2. CentOS6.5下安装、配置SSH

    1.登录CentOS 6.5系统,使用root用户登录,如果为非root用户则执行 su 或 su - 或 su root 或 su - root 输入root密码切换为root用户. 2.查看SSH ...

  3. 前端阶段_html部分2后台frame的初始构架案例

    1.<frameset cols="25%,75%">          把页面分为1:3,并且使用frame的同时应该删除body标签 2.<frame src ...

  4. C#连接数据库open函数失败

    错误信息:在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误.未找到或无法访问服务器.请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接. (provider ...

  5. Eclipse搭建maven项目的流程,聚合所有的子模块项目

    Eclipse搭建maven项目的流程 2018年03月01日 15:47:03 阅读数:22 1:搭建parent工程,用来聚合所有的子模块项目 2:搭建公共使用的模块common 这里你要点击空白 ...

  6. Hexo 的next主题下添加网易云音乐作BGM

    首先,你要看看你选中的歌能不能在网页版的网易云音乐生成外链,因为版权保护原因,有些音乐是生不成外链的,比如这样的: 所以,选些可以生成外链的音乐.生成对应的外链 比如这里的重点是HTML代码中的src ...

  7. 力扣 (LeetCode)657. 机器人能否返回原点

    在二维平面上,有一个机器人从原点 (0, 0) 开始.给出它的移动顺序,判断这个机器人在完成移动后是否在 (0, 0) 处结束. 移动顺序由字符串表示.字符 move[i] 表示其第 i 次移动.机器 ...

  8. Windows上安装运行hadoop

    0.自己编译安装步骤在这里,有英文版本连接:<英文传送门>. 自己编译尝试后不成功,换为下面使用别人编译好的版本的方法.参考博客:<初学hadoop,windows下安装> 1 ...

  9. 第 7 章 多主机管理 - 045 - 安装 Docker Machine

    安装 Docker Machine 先安装docker 官方安装docker-machine的文档地址:https://docs.docker.com/machine/install-machine/ ...

  10. Java从内存流中读取byte数组

    Java中通过servlet接收二进制数据,然后将二进制数据流读取为byte数组.开始使用:byte[] bs = new byte[request.getContentLength()];reque ...