文档章节

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

geecoodeer
 geecoodeer
发布于 2014/01/15 13:06
字数 1550
阅读 4053
收藏 22
点赞 4
评论 3

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
粉丝 153
博文 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
DDD~概念中的DDD

概念中的DDD DDD: 领域驱动设计,它是对面向对象的的分析和设计(OOAD,Object Orient Analysis Design)的一个补充,对技术框架进行了分层规划,同时对每个类进行了策略和类型划...

mcy247
2017/12/05
0
0
sharding-jdbc源码分析—数据源

原文作者:阿飞Javaer 原文链接:https://www.jianshu.com/p/28b953c5d4b2 以剖析分库分表配置与实现,其部分源码如下: 接下来分析第一步,即如何创建ShardingDataSource; ①ShardingDataS...

飞哥-Javaer
05/03
0
0
ReactNative源码篇:源码初识

关于作者 郭孝星,程序员,吉他手,主要从事Android平台基础架构方面的工作,欢迎交流技术方面的问题,可以去我的Github提issue或者发邮件至guoxiaoxingse@163.com与我交流。 更多文章:git...

郭孝星
2017/09/28
0
0
【机器学习】---密度聚类从初识到应用

========================================================= 声明:由于不同平台阅读格式不一致(尤其源码部分),所以获取更多阅读体验!! 请关注本人博客园地址:http://www.cnblogs.com/...

LHWorldBlog
01/27
0
0
领域驱动设计的基础知识总结

1. 什么是领域(Domain) 我们所做的软件系统的目的都是来解决一系列问题,例如做一个电商系统来在线销售自己企业的产品;做一个灰度发布平台来提升服务的质量和稳定性。任何一个系统都会属于...

butterfly100
2017/11/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

回想过往,分析当下,着眼未来

好久没有真正的在纸质笔记本上写过东西了,感觉都快不会写字了,笔画都不知道怎么写了。接下来就说说咱们的正事。 2018年7月22日,我做了一个决定,那就是去参加安全培训(可能是我职业生涯中...

yeahlife
13分钟前
0
0
关于工作中的人际交往

关于工作中的人际交往 Intro 写了篇发泄情绪的博客,但不会发布出来。 大概就是,要么忍,要么滚。 以及一些不那么符合社会主义核心价值观,不满于大资本家与小资本家剥削的废话。

uniqptr
18分钟前
0
0
springMVC的流程

1.用户发送请求至前端控制器DispatcherServlet 2.DispatcherServlet收到请求调用HandlerMapping处理器映射器。 3.处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(...

JavaSon712
34分钟前
0
0
大数据教程(3.2):Linux系统软件安装之自动化脚本

博主前面文章有介绍过软件的安装,可以帮助IT人员顺利的完成功能软件安装;但是,对于我们运维人员或者需要管理软件安装的项目经理来说,有些应用一次行需要搭建很多台相同的软件环境(如tom...

em_aaron
52分钟前
0
0
Spring Boot 2.0.3 JDBC整合Oracle 12

整合步骤 1. Oracle驱动引入 Oracle驱动一般不能通过maven仓库直接下载得到,需自行下载并导入到项目的lib目录下,建议通过如下pom依赖引入下载的Oracle驱动 <!-- Oracle 驱动 -->...

OSC_fly
今天
0
0
java 8 并行流 - 1

下面创建一个并行流,与顺序流 //顺序流Stream.iterate(0L, i -> i + 1) .limit(Integer.MAX_VALUE) .reduce(0L, Long::sum);//并行流Stream.iterate(0L, i -> i......

Canaan_
今天
0
0
数据结构与算法5

二分法采用向下取整的方法 使用有序数组的好处是查找的速度比无序数组快的多,不好的方面是因为要将所有靠后的数据移开,所以速度较慢,有序数组和无序数组的删除操作都很慢。 有序数组在查找...

沉迷于编程的小菜菜
昨天
1
1
SpringBoot | 第十一章:Redis的集成和简单使用

前言 上几节讲了利用Mybatis-Plus这个第三方的ORM框架进行数据库访问,在实际工作中,在存储一些非结构化或者缓存一些临时数据及热点数据时,一般上都会用上mongodb和redis进行这方面的需求。...

oKong
昨天
5
0
对基于深度神经网络的Auto Encoder用于异常检测的一些思考

一、前言 现实中,大部分数据都是无标签的,人和动物多数情况下都是通过无监督学习获取概念,故而无监督学习拥有广阔的业务场景。举几个场景:网络流量是正常流量还是攻击流量、视频中的人的...

冷血狂魔
昨天
0
0
并发设计之A系统调用B系统

A-->B A在发送请求之前,用乐观锁,减少对B的重复调用,这样一定程度上是幂等性。 比如A系统支付功能,要调用B系统进行支付操作,但是前端对"支付"按钮不进行控制,即用户会不断多次点击支付...

汉斯-冯-拉特
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部