netty源码分析(十八)Netty底层架构系统总结与应用实践
- 一个EventLoopGroup当中会包含一个或多个EventLoop。
- 一个EventLoop在它的整个生命周期当中都只会与唯一一个Thread进行绑定。
- 所有由EventLoop所处理的各种I/O事件都将在它所关联的那个Thread上进行处理。
- 一个Channel在它的整个生命周期中只会注册在一个EventLoop上。
- 一个EventLoop在运行过程中,会被分配给一个或多个Channel。
- 同一个Channel提交的任务执行顺序和提交顺序是一样的(先进去的先出来,任务队列)。
重要结论:在netty的实现当中一定是线程安全的,基于此我们可以存储存储一个channel的引用,并且在需要向远程端点发送数据时,通过这个引用来调用Channel相应的方法;即便当时有很多线程在使用它也不会出现多线程问题,而且消息一定会按照顺序发送出去。
重要结论:我们在业务开发中,不要将长时间执行的耗时任务放入到EventLoop的执行队列中,因为它将会一直阻塞该线程所对应的所有Channel上的其他执行任务,如果我们需要进行阻塞调用或是耗时的操作(实际开发中很常见),那么我们就需要使用一个专门的EventExecutor(业务线程池)。
通常会有2种实现方式:
1、在ChannelHandler的回调方法中,使用自己定义的业务线程池,这样就可以实现异步调用。
2、借助于netty提供的向ChannelPipeLine添加ChannelHandler时调用的addLast方法来传递EventExecutor。
说明:默认情况下(调用addLast(handler)),ChannelHandler中的回调方法都是由I/O线程所执行,如果调用了ChannelPipeline addLast(EventExecutorGroup group, ChannelHandler… handlers);方法,那么ChannelHandler中的回调方法就是由参数中的group线程组来执行。
netty的异步:
从上图可以看到,ChannelPromise继承了Promise 接口,而Promise是可以写的(writable),什么是可以写的,之前的Future都是get,isSuccess之类的方法,在ChannelPromise里边可以看到setSuccess(Void result)【setSuccess只能写一次,下一次写报错】之类的写方法。ChannelPromise字面意思是承诺的意思,不管是成功还是失败会承诺给你一个结果。
JDK所提供的Future只能通过手工方式检查执行结果,而这个操作是会阻塞的;Netty则对ChannelFuture进行了增强,这里涉及到的是观察者模式,通过ChannelFutureListener以回调的方式来获取执行结果,去除了手工检查阻塞的操作,值得注意的是:ChannelFutureListener的operationcomplete方法是由I/O线程执行的,因此要注意的是不要再这里执行耗时操作,否则需要需要通过另外的线程或线程池来执行。
举例:jdk的Future得到返回结果是使用get或者isDone获取,而这两个方式是阻塞的,即使是用超时时间的方法如果时间到了获取不到也是返回null,这些事情都是开发人员自己做的,而Netty解决了这个弊端,netty通过在Future上加入了监听器的模式,注册到Future上若干Listner,Future持有Channel,当某一个事件发生的时候,Future调用对应的Listner的方法,方法入参会有当前Future的引用,所以在Listener里边就会得到Future的Channel,之后在Listener里边得到Channel的数据进行处理,这也是上边说的不要再Listener的方法里边处理耗时的业务的原因。
再说一下ChannelHandler,ChannelHandler有入栈和出栈的Handler,就拿ChannelInboundHandlerAdapter 来说,我们要写一个入栈处理器,需要必须重写接口里边的所有方法,但是我们只用一部分方法,而Adapter是一种适配器模式,会把所有方法实现,我们在用的时候直接用适配的类(要么重写要么直接使用)去实现业务逻辑就可以了,大大方便了开发者以及减轻来了开发者的工作量。
1 |
public class ChannelInboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelInboundHandler {
|
ChannelInboundHandlerAdapter 的具体实现类有SimpleChannelInboundHandler,他和ChannelInboundHandlerAdapter 有什么区别呢?
1 |
public abstract class SimpleChannelInboundHandler<I> extends ChannelInboundHandlerAdapter |
很直观就是加了一个泛型I,I就是接受的消息的类型,比如String,Object等,而在ChannelInboundHandlerAdapter 里边四需要把消息 强制类型转换的,这是他们最大的区别。除此之外SimpleChannelInboundHandler会对消息执行ReferenceCountUtil.release(Object)和ReferenceCountUtil.retain(Object) 分别是释放一个消息引用和保持一个消息引用(流到下一个handler).
我们一般会使用ChannelInboundHandlerAdapter 和SimpleChannelInboundHandler处理入栈数据。
实际应用:
ReferenceCountUtil的release方法:
1 |
public static boolean release(Object msg) {
|
最终使用的是ReferenceCounted类操作的:
1 |
/** |
netty源码分析(十八)Netty底层架构系统总结与应用实践的更多相关文章
- ABP源码分析十八:UI Inputs
以下图中描述的接口和类都在Abp项目的Runtime/Validation, UI/Inputs目录下的.在当前版本的ABP(0.83)中这些接口和类并没有实际使用到.阅读代码时可以忽略,无需浪费时间 ...
- jQuery 源码分析(十八) ready事件详解
ready事件是当DOM文档树加载完成后执行一个函数(不包含图片,css等),因此它的触发要早于load事件.用法: $(document).ready(fun) ;fun是一个函数,这样当DOM树加 ...
- Vue.js 源码分析(十八) 指令篇 v-for 指令详解
我们可以用 v-for 指令基于一个数组or对象来渲染一个列表,有五种使用方法,如下: <!DOCTYPE html> <html lang="en"> & ...
- Netty源码分析 (八)----- write过程 源码分析
上一篇文章主要讲了netty的read过程,本文主要分析一下write和writeAndFlush. 主要内容 本文分以下几个部分阐述一个java对象最后是如何转变成字节流,写到socket缓冲区中去 ...
- Netty源码分析第1章(Netty启动流程)---->第4节: 注册多路复用
Netty源码分析第一章:Netty启动流程 第四节:注册多路复用 回顾下以上的小节, 我们知道了channel的的创建和初始化过程, 那么channel是如何注册到selector中的呢?我们继 ...
- Netty源码分析第1章(Netty启动流程)---->第5节: 绑定端口
Netty源码分析第一章:Netty启动步骤 第五节:绑定端口 上一小节我们学习了channel注册在selector的步骤, 仅仅做了注册但并没有监听事件, 事件是如何监听的呢? 我们继续跟第一小节 ...
- Netty源码分析第1章(Netty启动流程)---->第3节: 服务端channel初始化
Netty源码分析第一章:Netty启动流程 第三节:服务端channel初始化 回顾上一小节的initAndRegister()方法: final ChannelFuture initAndRe ...
- netty源码分析系列文章
netty源码分析系列文章 nettynetty源码阅读netty源码分析 想在年终之际将对netty研究的笔记记录下来,先看netty3,然后有时间了再写netty4的,希望对大家有所帮助,这个是 ...
- Netty源码分析-- 处理客户端接入请求(八)
这一节我们来一起看下,一个客户端接入进来是什么情况.首先我们根据之前的分析,先启动服务端,然后打一个断点. 这个断点打在哪里呢?就是NioEventLoop上的select方法上. 然后我们启动一个客 ...
随机推荐
- 十、GUI编程
GUI图形用户界面编程 GUI编程类似“搭积木”,将一个个组件放到窗口中,并通过增加“事件处理”,完成一个个程序.例如:记事本.word.画图工具等. tkinter模块 tkinter是 ...
- easyExcel入门
1.easyExcel是处理excel的阿里开源的框架,类似poi.官网地址:https://github.com/alibaba/easyexcel 2.为什么用easyExcel? 1).占用内存 ...
- numpy(二)
1.集合操作 包含去重,交,并,差集操作 2.排序.搜索和计数 sort,where,argmin,argmax,count_nonzero,argwhere 3.线性代数 np.linalg库,包含 ...
- 洛谷 P3808 【模板】AC自动机(简单版)
传送门:https://www.luogu.org/problem/P3808 题解:是一个AC自动机的裸题了,注释加在代码里面了 #include<bits/stdc++.h> usin ...
- 吴裕雄--天生自然 PYTHON3开发学习:集合
fruits = {"apple", "banana", "cherry"} fruits.add("orange") ...
- js时间与日期
var box = new Date(); //创建了一个日期对象:构造方法里面可以传参数,指定时间.如果没有传,就是默认当前时间alert(box); alert(Date.parse('4/12/ ...
- TPO6-1 Powering the Industrial Revolution
By 1800 more than a thousand steam engines were in use in the British Isles, and Britain retained a ...
- Opencv笔记(十六)——认识轮廓
什么是轮廓? 轮廓可以简单认为成连续的点(连着边界)连在一起的曲线,具有相同的颜色或者灰度.轮廓在形状分析和物体的检测和识别中很有用.谈起轮廓不免想到边缘,它们确实很像.简单的说,轮廓是连续的,边缘并 ...
- rework-发出你的心声
生意人虚张声势的时候会给人什么感觉?都是些僵硬的措辞.官方的腔调.虚伪的友善.法律术语等.你一定看过这些玩意儿,就好像是机器人写出来的东西,这些公司在向你发话,而不是和你对话. 这种专业主义面具让人觉 ...
- mysql,user表中各字段的含义
1.查询user表 select * from mysql.user 2.修改用户密码 ALTER user ' 3.user表中各字段的含义 Select_priv:用户可以通过SELECT命令选择 ...