文档章节

Netty5源码分析--0.核心领域概念

geecoodeer
 geecoodeer
发布于 2014/01/15 13:06
字数 1550
阅读 4069
收藏 22

Netty是什么

由于通用的协议或者实现有时不能满足各种各样的需求,比如我们通常不会用一个HTTP Server来同时进行传输大文件,email以及近实时的消息如金融信息和多玩家游戏数据。我们需要一个高度优化的协议实现,来满足一些特定的需求。

Netty是一个异步,事件驱动的网络应用框架,并且提供了一些工具来帮助迅速地开发高性能,高扩展性的服务端和客户端。


核心领域概念介绍

隐喻

Channel 公路,双向道,分为去路和来路。隐喻为网络连接。

ChannelPipeline,公路管理部门,可以设置收费站,关卡等设施对车辆进行检查。

ByteBuf 车辆。隐喻为网络连接中的数据。

Handler 收费站,关卡;可以对公路上的车辆进行各种处理。


Channel

顶层接口,因为有不同的通讯协议,比如TCP、UDP、rxtx等等以及不同的通讯模型,如OIO,NIO,AIO;所以针对这些不同的实现来提供一个统一的接口,在必要的时候,进行向下转型(Downcast),方便扩展。

该接口提供如下功能: 当前channel的状态(比如是否open,connected) 当前channel的配置参数(比如receive buffer size) 当前channel支持的操作(比如read, write, connect, and bind)

另外,仍然需要值的一提是,Netty中的所有I/O操作都是异步的。这意味着这些I/O方法被调用时,会立即返回ChannelFuture,并不保证这些I/O操作实际完成(比如将数据已经发送到对端)。ChannelFuture会告诉你这个I/O操作结果是成功,失败还是取消。

Channel有一个parent。比如,SocketChannelServerSocketChannel的"accept方法"的返回值(ServerSocketChannel中并没有accept方法,但是在ServerSocket中是存在的)。所以,SocketChannel的 parent()返回ServerSocketChannel

ChannelPipeline

ChannelPipeline,顾名思义,意为“Channel的流水线”,处理了Channel中所有的I/O事件和请求。ChannelPipeline该类通过了实现Intercepting Filter pattern,结合ChannelHandler接口的实现类,提供了类似将流水线的工作分成多个步骤的功能。每个ChannelHandler接口的实现类完成了一定的功能,并且可以灵活地在流水线上增加,替换,删除Handler,极大地提高了框架的灵活性。

每个Channel在实例化时,会自动创建一个ChannelPipeline实例。

Inbound 通常用来表示从外界读入数据,OutBound通常用来表示将数据写出到外界。在TCP/IP协议栈中,数据需要从操作系统的栈读入,数据写出时也需要经过操作系统的TCP/IP栈。在Netty的实现中,只有一个Handler链,将时间触发,数据发送和数据接收结合在一起。但这个也是有点费解。

在触发Inbound I/O Event时,handler依照从0到N-1顺序被netty框架触发;在触发Outbound I/O Event时,handler依照从N-1到0顺序被netty框架触发。

Inbound event传播的方法 :

  • ChannelHandlerContext.fireChannelRegistered()
  • ChannelHandlerContext.fireChannelActive()
  • ChannelHandlerContext.fireChannelRead(Object)
  • ChannelHandlerContext.fireChannelReadComplete()
  • ChannelHandlerContext.fireExceptionCaught(Throwable)
  • ChannelHandlerContext.fireUserEventTriggered(Object)
  • ChannelHandlerContext.fireChannelWritabilityChanged()
  • ChannelHandlerContext.fireChannelInactive()

Outbound event 传播的方法 :

  • ChannelHandlerContext.bind(SocketAddress, ChannelPromise)
  • ChannelHandlerContext.connect(SocketAddress, SocketAddress, ChannelPromise)
  • ChannelHandlerContext.write(Object, ChannelPromise)
  • ChannelHandlerContext.flush()
  • ChannelHandlerContext.read()
  • ChannelHandlerContext.disconnect(ChannelPromise)
  • ChannelHandlerContext.close(ChannelPromise)

ChannelPipeline是线程安全的,所以ChannelHandler可以在任意时刻被增加,移除和替换。

EventLoopGroup 和 EventLoop

类继承关系如下,JUC.ScheduledExecutorService<--EventExecutorGroup<--EventLoopGroup<--EventLoop。这个"<--"表示是符号的右边继承符号的左边接口,下同。

JUC.ScheduledExecutorService是JUC框架的线程调度框架。

EventExecutorGroup增加了next()children()方法;另外还Deprecated了父接口的shutdown()shutdownNow()方法,新增了isShuttingDown()shutdownGracefully()shutdownGracefully()terminationFuture()

EventLoopGroup 覆写了EventExecutorGroupEventLoop next()方法。

EventLoop在继承了EventLoopGroup的同时,也继承了EventExecutor接口。所以这里补充介绍下EventExecutor类,它继承了EventExecutorGroup,另外,它主要新增了EventExecutorGroup parent()方法和boolean inEventLoop(Thread thread)方法。

EventLoop自身主要新增了 ChannelHandlerInvoker asInvoker()方法,它主要负责处理所有I/O操作。

从职责上讲,EventLoop表示事件循环的意思,也就是死循环来捕获不同的事件,比如说是否可读,可写等等。EventExecutorGroup则表示一组EventLoop,所以它里面才有next()children()方法。另外,这几个类有点乱,尤其是父接口EventExecutorGroup依赖了子接口EventLoop,违反了DIP原则。

Future,ChannelFuture 和 ChannelPromise

ChannelFuture表示实际的I/O操作还未发生。因为在netty中,所有的I/O操作(如read, write, connect,和bind)都是异步的。类继承关系如下,JUC.Future<--Future<--ChannelFuture<--ChannelPromise

Future继承了JUC框架里的Future接口,还主要新增了isSuccess(),isCancellable(),cause()方法;此外还新增了注册Future完成的时候触发对应的Listener的功能

ChannelFuture主要新增了Channel channel()方法。

ChannelPromise在继承ChannelFuture的同时,还继承了Promise接口。该Promise主要增加了对Future的写方法,如 Promise<V> setSuccess(V result)等。也就是说,ChannelPromise基本是ChannelFuturePromise的结合体。

也就是说,ChannelFuture不仅细化了JUC.Future语义,可以方便知道到底是成功,取消还是异常,还提供了Channel channel()ChannelPromise则可以根据程序的运行结果设置一些业务含义。另外,也可以观察到,在子接口里仅仅把父接口方法返回值覆写了,然后什么都不做。这样一定程度上避免了强制转型的尴尬。

ByteBuf

ByteBuf支持随机和顺序访问内部的字节。它具有readerIndex和writerIndex。它们的关系如下:

  +-------------------+------------------+------------------+
  | discardable bytes |  readable bytes  |  writable bytes  |
  |                   |     (CONTENT)    |                  |
  +-------------------+------------------+------------------+
  |                   |                  |                  |
  0      <=      readerIndex   <=   writerIndex    <=    capacity

建议使用 Unpooled等helper方法来创建ByteBuf对象,而不是直接使用ByteBuf的实现的构造器。在5.0版本,建议使用PooledByteBufAllocator来创建ByteBuf对象。

Bootstrap 和 ServerBootstrap

Bootstrap这个词在计算机中,通常表示某个框架开始执行的第一段代码。详见What is bootstrapping?

在Netty中,Bootstrap是客户端启动类,ServerBootstrap是服务端启动类,用来帮助程序员迅速开始工作。


参考

User Guide For 5.x

© 著作权归作者所有

共有 人打赏支持
geecoodeer
粉丝 154
博文 22
码字总数 63454
作品 0
南京
程序员
加载中

评论(3)

徐顺
徐顺
很不错,简洁,清晰。
安啦佱
lz写的很实用
demoadmin
demoadmin
赞!!!
netty 中遇到的一个坑 SimpleInboundHandler,记录一下

本来是打算用netty的handler来做业务处理,把业务分散到多个handler来处理,这样子系统看上去就比较模块化了,方便扩展和拆除,但netty5的 handler的请求传递是有“坑”的,不能说是错误,只...

coder4j
2016/06/04
929
4
请教一个关于netty启动过程疑问:子线程的无限循环的具体代码在哪儿,谢谢了

@geecoodeer 你好,想跟你请教个问题: 关于netty的,我看了你的文章http://my.oschina.net/geecoodeer/blog/193237()Netty5源码分析--1.服务端启动过程详解,自己也在看这个源码就是从看其启...

gaoyongbo026
2016/08/08
54
0
Netty工具类HashedWheelTimer源码走读(一)

简单介绍. A Timer optimized for approximated I/O timeout scheduling. 关于Timer的介绍可以看看这篇文章, 写得不错 : http://novoland.github.io/%E5%B9%B6%E5%8F%91/2014/07/26/%E5%AE%9......

德胜
2015/08/07
0
0
Netty5源码分析--4.总结

JAVA NIO 复习 请先参考我之前的博文JAVA学习笔记--3.Network IO的 NIO(NonBlocking IO) SOCKET 章节。这里主要讲下JAVA NIO其中几个比较被忽略的细节,不求全,欢迎补充。 API Select 当调...

geecoodeer
2014/01/17
0
18
领域驱动设计(DDD)部分核心概念的个人理解

原文:领域驱动设计(DDD)部分核心概念的个人理解 领域驱动设计(DDD)是一种基于模型驱动的软件设计方式。它以领域为核心,分析领域中的问题,通过建立一个领域模型来有效的解决领域中的核心...

杰克.陈
2017/12/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Shell特殊符号总结以及cut,sort,wc,uniq,tee,tr,split命令

特殊符号总结一 * 任意个任意字符 ? 任意一个字符 # 注释字符 \ 脱义字符 | 管道符 # #号后的备注被忽略[root@centos01 ~]# ls a.txt # 备注 a.txt[root@centos01 ~]# a=1[root@centos01...

野雪球
28分钟前
1
0
OSChina 周二乱弹 —— 程序员圣衣

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @达尔文:分享Skeeter Davis的单曲《The End of the World》 《The End of the World》- Skeeter Davis 手机党少年们想听歌,请使劲儿戳(这里...

小小编辑
43分钟前
4
0
[ python import module ] 导入模块

import moudle_name ----> import module_name.py ---> import module_name.py文件路径 -----> sys.path (这里进行查找文件) # from app.web import Personimport app.web.Person as Pe......

_______-
昨天
3
0
Redis性能问题排查解决手册

一、性能相关的数据指标 通过Redis-cli命令行界面访问到Redis服务器,然后使用info命令获取所有与Redis服务相关的信息。通过这些信息来分析文章后面提到的一些性能指标。 nfo命令输出的数据可...

IT--小哥
昨天
1
0
mixin混入

①新建mixin.js文件 const mixin = { methods: { /** * 分页公共方法 */ handleSizeChange(val) { this.pageData.size = val; this.query(); }, hand......

不负好时光
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部