java高并发实战Netty+协程(Fiber)|系列1(续)|事件驱动模式和零拷贝
上次讲到事件驱动模式,今天我们来好好分析下netty的事件模式的几个类型。
先从NIO讲起,
JAVA NIO方面Selector给Reactor模式提供了基础,Netty结合Selector和Reactor模式设计了高效的线程模型。
这里有个题外话,reactor英文的含义是什么?我们可以稍微了解下:
- n.核反应堆
- 网络反应器;电抗器;反应者
- 变形复数:reactors;
中文翻译是反应者,在我们这个语境,翻译成反应者或响应者,都是正解。就把它想象成KFC的前台服务员好,她就是一个响应者,也叫reactor.
现在我们来看下Reactor模式图:

如上图所示,所谓的reactor模式,就是我们上篇文章所说的,KFC前后服务员加后台服务员的模式。
前台服务员(同时代表上图的demultiplexer和dispatcher)只负责接待客户的点汉堡的请求和订单分派,做汉堡的活让后台台服务员(代表上图的handler)去做。
做好后,后台再通知前台,由前台转交给客户。
这个很好理解。
好,那我们现在来看看Java NIO的reactor的几个模式:单线程模式,多线程模式,主从模式。
先看单线程模式:

如上图所示,所谓单线程模式,只有一个线程(acceptor)去处理客户的请求,然后,这个线程还要做read,send等工作,相当于是个多面手。
就好像KFC前台后台都只有一个服务员。
这个模式,如果客户只有一个的话,是可以处理。但如果,是用餐高峰期,一下子来了十个客户,那就不好处理了。
怎么办?
很自然,我们可以增加后台服务员,并且因为后台的工作比较多,后台服务员可以多个。这就是多线程模式。
再看多线程模式图:

如上图所示,用线程池(多个服务员)去处理read,decode,compute,encode任务。
就好像,前台一个服务员只负责下订单,然后把订单信息分派给多个后台服务员,同时服务多个客户,速度和效率也明显好很多,客户也不用等待太久。
那如果,这个时间来了几十个客户,如果只有一个前台服务员,这时,也处理不过来,怎么办?
很自然,增加前台服务员的数量。当然我们也不需要增加太多(毕竟有人力成本),现在我们只增加一位好了。
两位服务员,一主一从,我们就叫主从模式。
我们来看主从模式图:

如上图,将Reactor分成两部分,mainReactor负责监听server socket,accept新连接;并将建立的socket分派给subReactor。subReactor负责多路分离已连接的socket,读写网络数据,对业务处理功能,其扔给worker线程池完成。通常,subReactor个数上可与CPU个数等同。
还是用KFC的例子来说明,其中mainReactor是服务员小黄,她只负责下订单。subReactor就是服务员小张,他呢,只服务根据订单信息分派给后台服务员,并负责把汉堡和饮料放在托盘递给客户。
以上就是reactor模式说明,希望你已经明白了!
说完了Reactor的三种模型,那么Netty是哪一种呢?其实Netty的线程模型是Reactor模型的变种,那就是去掉线程池的第三种形式的变种,这也是Netty NIO的默认模式。Netty中Reactor模式的参与者主要有下面一些组件:
Selector
EventLoopGroup/EventLoop
ChannelPipeline
Selector即为NIO中提供的SelectableChannel多路复用器,充当着demultiplexer的角色,就像专门下订单的前台服务员。
ChannelPipeline负责安排Handler的顺序及其执行。因为后台工作多且杂,需要一个后台管理员负责管理和编排后台服务员的工作。这个后台管理员就是ChannelPipeline。
EventLoop的目的是为Channel处理IO操作,一个EventLoop可以为多个Channel服务。EventLoop就是后台服务员,一个后台服务员可以同时做几份汉堡。
EventLoopGroup会包含多个EventLoop。EventLoopGroup就是后台服务员的班组,几个后台服务员一个班组,一个班组固定处理一个固定 的后台工作。
明天继续。
s
java高并发实战Netty+协程(Fiber)|系列1(续)|事件驱动模式和零拷贝的更多相关文章
- java高并发实战Netty+协程(Fiber)|系列1|事件驱动模式和零拷贝
今天开始写一些高并发实战系列. 本系列主要讲两大主流框架: Netty和Quasar(java纤程库) 先介绍netty吧,netty是业界比较成熟的高性能异步NIO框架. 简单来说,它就是对NIO2 ...
- 用Swoole4 打造高并发的PHP协程Mysql连接池
码云代码仓库:https://gitee.com/tanjiajun/MysqlPool 代码仓库:https://github.com/asbectJ/swoole4.git 前言 在写这篇文章之前 ...
- Java高并发实战,锁的优化
锁优化 这里的锁优化主要是指 JVM 对 synchronized 的优化. 自旋锁 互斥同步进入阻塞状态的开销都很大,应该尽量避免.在许多应用中,共享数据的锁定状态只会持续很短的一段时间.自旋锁的思 ...
- java高并发实战(三)——Java内存模型和线程安全
转自:https://blog.csdn.net/gududedabai/article/details/80816488
- java高并发实战(二)——线程(并行程序)基础
转自:https://blog.csdn.net/gududedabai/article/details/80815666
- java高并发实战(一)——为什么需要并发
转自:https://blog.csdn.net/gududedabai/article/details/80813592
- 从菜鸟到大神:Java高并发核心编程(连载视频)
任何事情是有套路的,学习是如此, Java的学习,更是如此. 本文,为大家揭示 Java学习的套路 背景 Java高并发.分布式的中间件非常多,网上也有很多组件的源码视频.原理视频,汗牛塞屋了. 作为 ...
- 高级java高并发,高性能,分布式,高可用,负载均衡,系统架构实战
java架构师.集群.高可用.高可扩 展.高性能.高并发.性能优化.Spring boot.Redis.ActiveMQ.Nginx.Mycat.Netty.Jvm大型分布 式项目实战 视频课程包含: ...
- Netty Redis 亿级流量 高并发 实战 (长文 修正版)
目录 疯狂创客圈 Java 分布式聊天室[ 亿级流量]实战系列之 -30[ 博客园 总入口 ] 写在前面 1.1. 快速的能力提升,巨大的应用价值 1.1.1. 飞速提升能力,并且满足实际开发要求 1 ...
随机推荐
- Spring Data JPA 动态拼接条件的通用设计模式
import java.sql.Timestamp;import java.util.ArrayList;import java.util.List;import javax.persistence. ...
- 关于函数中参数kwarg.setdefault()的用法
1.kwarg.setdefault() setdefault()是给字典传递一个默认值 当给字典传递数据时 setdefault()是字典默认的一个参数,当有新的数据时,就会使用新的数据
- Java Map集合 遍历 五种方式(包含 Lambda 表达式遍历)
示例代码如下: package com.miracle.luna.lambda; import java.util.HashMap; import java.util.Iterator; import ...
- 转载 STM32 使用Cubemx 建一个USB(HID)设备下位机,实现数据收发
STM32 使用Cubemx 建一个USB(HID)设备下位机,实现数据收发 本文转载自 https://www.cnblogs.com/xingboy/p/9913963.html 这里我主要说一 ...
- git clone 指定分支操作
服务器迁移,而且原来本地开发是在同一个目录中切换不同的分支,感觉有点挫,于是打算一个文件目录对应一个分支,这样不会有太大的文件差异. 记录下来本次操作,可能以后还会用到. git初始化一般是这样. g ...
- Oracle 笔记(四)
PLSQL编程[语法.plsql控制语句.异常.游标.触发器.存储过程] 1. PLSQL的语法–块编程 a) 概念:procedural language s ...
- Cocos2d-X多线程(2) 线程的互斥量std::mutex和线程锁
多个线程同时访问共享资源时,经常会出现冲突等.为了避免这种情况的发生,可以使用互斥量,当一个线程锁住了互斥量后,其他线程必须等待这个互斥量解锁后才能访问它. thread提供了四种不同的互斥量: 1. ...
- CF-Div.3-B. Minimize the Permutation【模拟·需要清醒的脑子】
题目传送门 根据字典序,是个人都会想到依次把目前最小的数尽量往前面移动,直到它不能再往前移动,或者已经到了它的期望位置(就是排列的那个位置 比如$i$就应该在位置$i$)为止. 所以我刚开始是这么写的 ...
- 【Java基础】Java创建对象的五种方式
Java中创建(实例化)对象的五种方式 1.用new语句直接创建对象,这是最常见的创建对象的方法. 2.通过工厂方法返回对象,如:String str = String.valueOf(23); 3. ...
- 将Lambda表达式作为参数传递并解析-在构造函数参数列表中使用Lambda表达式
public class DemoClass { /// <summary> /// 通过Lambda表达式,在构造函数中赋初始值 /// </summary> /// < ...