感谢网友【黄亿华】投递本稿。

Netty和Mina是Java世界非常知名的通讯框架。它们都出自同一个作者,Mina诞生略早,属于Apache基金会,而Netty开始在Jboss名下,后来出来自立门户netty.io。关于Mina已有@FrankHui的Mina系列文章,我正好最近也要做一些网络方面的开发,就研究一下Netty的源码,顺便分享出来了。 Netty目前有两个分支:4.x和3.x。4.0分支重写了很多东西,并对项目进行了分包,规模比较庞大,入手会困难一些,而3.x版本则已经被广泛使用。本系列文章针对netty 3.7.0 final。3.x和4.0的区别可以参考这篇文章:http://www.oschina.net/translate/netty-4-0-new-and-noteworthy?print。

起:Netty是什么

大概用Netty的,无论新手还是老手,都知道它是一个“网络通讯框架”。所谓框架,基本上都是一个作用:基于底层API,提供更便捷的编程模型。那么”通讯框架”到底做了什么事情呢?回答这个问题并不太容易,我们不妨反过来看看,不使用netty,直接基于NIO编写网络程序,你需要做什么(以Server端TCP连接为例,这里我们使用Reactor模型):

监听端口,建立Socket连接

建立线程,处理内容

读取Socket内容,并对协议进行解析

进行逻辑处理

回写响应内容

如果是多次交互的应用(SMTP、FTP),则需要保持连接多进行几次交互

关闭连接

建立线程是一个比较耗时的操作,同时维护线程本身也有一些开销,所以我们会需要多线程机制,幸好JDK已经有很方便的多线程框架了,这里我们不需要花很多心思。 此外,因为TCP连接的特性,我们还要使用连接池来进行管理:

建立TCP连接是比较耗时的操作,对于频繁的通讯,保持连接效果更好

对于并发请求,可能需要建立多个连接

维护多个连接后,每次通讯,需要选择某一可用连接

连接超时和关闭机制

想想就觉得很复杂了!实际上,基于NIO直接实现这部分东西,即使是老手也容易出现错误,而使用Netty之后,你只需要关注逻辑处理部分就可以了。

承:体验Netty

这里我们引用Netty的example包里的一个例子,一个简单的EchoServer,它接受客户端输入,并将输入原样返回。其主要代码如下:

public void run() {

// Configure the server.

ServerBootstrap bootstrap = new ServerBootstrap(

new NioServerSocketChannelFactory(

Executors.newCachedThreadPool(),

Executors.newCachedThreadPool()));

// Set up the pipeline factory.

bootstrap.setPipelineFactory(new ChannelPipelineFactory() {

public ChannelPipeline getPipeline() throws Exception {

return Channels.pipeline(new EchoServerHandler());

}

});

// Bind and start to accept incoming connections.

bootstrap.bind(new InetSocketAddress(port));

}

这里EchoServerHandler是其业务逻辑的实现者,大致代码如下:

public class EchoServerHandler extends SimpleChannelUpstreamHandler {

@Override

public void messageReceived(

ChannelHandlerContext ctx, MessageEvent e) {

// Send back the received message to the remote peer.

e.getChannel().write(e.getMessage());

}

}

还是挺简单的,不是吗?

转:Netty背后的事件驱动机制

完成了以上一段代码,我们算是与Netty进行了第一次亲密接触。如果想深入学习呢?

首先推荐Netty的官方User Guide:http://netty.io/3.7/guide/。其次,阅读源码是了解一个开源工具非常好的手段,但是Java世界的框架大多追求大而全,功能完备,如果逐个阅读,难免迷失方向,Netty也并不例外。相反,抓住几个重点对象,理解其领域概念及设计思想,从而理清其脉络,相当于打通了任督二脉,以后的阅读就不再困难了。

理解Netty的关键点在哪呢?我觉得,除了NIO的相关知识,另一个就是事件驱动的设计思想。什么叫事件驱动?我们回头看看EchoServerHandler的代码,其中的参数:public void messageReceived(ChannelHandlerContext ctx, MessageEvent e),MessageEvent就是一个事件。这个事件携带了一些信息,例如这里e.getMessage()就是消息的内容,而EchoServerHandler则描述了处理这种事件的方式。一旦某个事件触发,相应的Handler则会被调用,并进行处理。这种事件机制在UI编程里广泛应用,而Netty则将其应用到了网络编程领域。

在Netty里,所有事件都来自ChannelEvent接口,这些事件涵盖监听端口、建立连接、读写数据等网络通讯的各个阶段。而事件的处理者就是ChannelHandler,这样,不但是业务逻辑,连网络通讯流程中底层的处理,都可以通过实现ChannelHandler来完成了。事实上,Netty内部的连接处理、协议编解码、超时等机制,都是通过handler完成的。当博主弄明白其中的奥妙时,不得不佩服这种设计! 下图描述了Netty进行事件处理的流程。Channel是连接的通道,是ChannelEvent的产生者,而ChannelPipeline可以理解为ChannelHandler的集合。

合:开启Netty源码之门

理解了Netty的事件驱动机制,我们现在可以来研究Netty的各个模块了。Netty的包结构如下:

org

└── jboss

└── netty

├── bootstrap 配置并启动服务的类

├── buffer 缓冲相关类,对NIO Buffer做了一些封装

├── channel 核心部分,处理连接

├── container 连接其他容器的代码

├── example 使用示例

├── handler 基于handler的扩展部分,实现协议编解码等附加功能

├── logging 日志

└── util 工具类

在这里面,channel和handler两部分比较复杂。我们不妨与Netty官方的结构图对照一下,来了解其功能。

具体的解释可以看这里:http://netty.io/3.7/guide/#architecture。图中可以看到,除了之前说到的事件驱动机制之外,Netty的核心功能还包括两部分:

Zero-Copy-Capable Rich Byte Buffer 零拷贝的Buffer。为什么叫零拷贝?因为在数据传输时,最终处理的数据会需要对单个传输层的报文,进行组合或者拆分。NIO原生的ByteBuffer要做到这件事,需要对ByteBuffer内容进行拷贝,产生新的ByteBuffer,而Netty通过提供Composite(组合)和Slice(切分)两种Buffer来实现零拷贝。这部分代码在org.jboss.netty.buffer包中。

Universal Communication API 统一的通讯API。因为Java的Old I/O和New I/O,使用了互不兼容的API,而Netty则提供了统一的API(org.jboss.netty.channel.Channel)来封装这两种I/O模型。这部分代码在org.jboss.netty.channel包中。

此外,Protocol Support功能通过handler机制实现。 接下来的文章,我们会根据模块,详细的对Netty源码进行分析。 最后附上Netty那点事系列文章/代码的Github地址:https://github.com/code4craft/netty-learning 参考资料:

python netty_Netty源码解读(一)概述相关推荐

  1. Java Review - PriorityQueue源码解读

    文章目录 Pre PriorityQueue 概述 PriorityQueue 继承关系 PriorityQueue通过用数组表示的小顶堆实现 时间复杂度 构造函数 方法 add()和offer() ...

  2. print python 带回车_python标准库threading源码解读【二】

    紧接着上一篇文章继续解析源码 甘蔗:python标准库threading源码解读[一]​zhuanlan.zhihu.com 目录 Event的介绍和用法 Event源码解析 以后的内容尽量少一点并且 ...

  3. python库源码分析_python第三方库Faker源码解读

    源码背景 Faker是一个Python第三方库,GITHUB开源项目,主要用于创建伪数据创建的数据包含地理信息类.基础信息类.个人账户信息类.网络基础信息类.浏览器信息类.文件信息类.数字类 文本加密 ...

  4. python源码解读

    文章目录 准备工作 Python整体结构 源码目录 Python对象 Python内对象 类型对象 对象的创建 类型的类型 Python中的整数对象 小整形对象 大整数对象 Python中的字符串对象 ...

  5. Alamofire源码解读系列(一)之概述和使用

    尽管Alamofire的github文档已经做了很详细的说明,我还是想重新梳理一遍它的各种用法,以及这些方法的一些设计思想 前言 因为之前写过一个AFNetworking的源码解读,所以就已经比较了解 ...

  6. Python源码解读之零 Python源码整体架构

    今天打算开一个新的系列,本系列将和大家一起对Python的源码进行分析,有参考陈儒的<Python 源码剖析>(强烈推荐这本书),做到知其然知其所以然. 总体架构 首先我们先从总体结构看一 ...

  7. PyTorch 源码解读之即时编译篇

    点击上方"AI遇见机器学习",选择"星标"公众号 重磅干货,第一时间送达 作者丨OpenMMLab 来源丨https://zhuanlan.zhihu.com/ ...

  8. Alamofire源码解读系列(九)之响应封装(Response)

    本篇主要带来Alamofire中Response的解读 前言 在每篇文章的前言部分,我都会把我认为的本篇最重要的内容提前讲一下.我更想同大家分享这些顶级框架在设计和编码层次究竟有哪些过人的地方?当然, ...

  9. spring-session源码解读 sesion

    2019独角兽企业重金招聘Python工程师标准>>> spring-session源码解读 sesion 博客分类: java spring 摘要: session通用策略 Ses ...

最新文章

  1. 铁轨问题 判断是否为出栈顺序
  2. Android复习08【内容提供者】
  3. 洛谷 P3853 [TJOI2007]路标设置
  4. historyReverser array reverse
  5. Python 创建和使用类
  6. C语言指针学习(续)
  7. 数据结构之并查集:并查集解决案例, Python——21
  8. python2.7 end=号报错_python2 post 上传压缩文件编码报错
  9. 苏州大学计算机组成与结构,苏州大学计算机组成结构期末.docx
  10. AC日记——[USACO10MAR]仓配置Barn Allocation 洛谷 P1937
  11. [SQL SERVER 2005]数据库差异备份及还原
  12. 360云计算|2019年度精选文章
  13. FPGA时钟激励编写(方法二)
  14. 重定义 UIImagePickerController
  15. (三)Mybatis总结之动态sql
  16. 冈萨雷斯 数字图像处理 插图 打包下载 原tif版 + png版
  17. Otsu算法原理与python实现
  18. 教您在Excel中批量生成条形码
  19. 科研狗citavi/mendeley+word使用技巧外加读论文瞎琢磨
  20. (一)移动端前端开发-移动端基础

热门文章

  1. (十三) 构建dubbo分布式平台-dubbo管控台安装
  2. MVC 源码系列之路由(一)
  3. CodeFirst 的编程方式
  4. 对查找的结果进行删除
  5. Leetcode | Minimum/Maximum Depth of Binary Tree
  6. Android开发自定义的View
  7. 多DHCP服务器的作用域 及备用DHCP服务器(一)
  8. 从MSSQL添加对Oracle的链接服务器的存储过程
  9. 使用Flink时从Kafka中读取Array[Byte]类型的Schema
  10. android:listView Button 焦点问题