博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Netty概述
阅读量:6896 次
发布时间:2019-06-27

本文共 3091 字,大约阅读时间需要 10 分钟。

hot3.png

1. 引言

1.1 Netty是什么

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

  1. 监听端口,建立Socket连接
  2. 建立线程,处理内容
  • (1)读取socket内容,并对协议进行解析
  • (2)进行逻辑处理
  • (3)回写响应内容
  • (4)如果是多次交互的应用(SMTP、FTP),则需要保持连接多进行几次交互
  1. 关闭连接,建立线程是一个比较耗时的操作,同时维护线程本身也有一些开销,所以我们会需要多线程机制,幸好JDK已经有很方便的多线程框架了,这里我们不需要花很多心思。 此外,因为TCP连接的特性,我们还要使用连接池来进行管理:
  • (1)建立TCP连接是比较耗时的操作,对于频繁的通讯,保持连接效果更好
  • (2)对于并发请求,可能需要建立多个连接
  • (3)维护多个连接后,每次通讯,需要选择某一可用连接
  • (4)连接超时和关闭机制

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

1.2 Netty初体验

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

// 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());    }}

还是挺简单的,不是吗?

2. Netty背后的事件驱动机制

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

首先推荐Netty的官方User Guide:

理解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的集合。

输入图片说明

3. Netty源码结构

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

org └── jboss └── netty ├── bootstrap 配置并启动服务的类 ├── buffer 缓冲相关类,对NIO Buffer做了一些封装 ├── channel 核心部分,处理连接 ├── container 连接其他容器的代码 ├── example 使用示例 ├── handler 基于handler的扩展部分,实现协议编解码等附加功能 ├── logging 日志 └── util 工具类

在这里面,channel和handler两部分比较复杂。我们不妨与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包中。

4. 参考资料

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

  • Netty 3.7 User Guide

  • What is Netty?

转载于:https://my.oschina.net/jimilee/blog/745366

你可能感兴趣的文章
ubuntu14.04 硬件型号查询
查看>>
分布式消息系统:Kafka
查看>>
Debian 7安装ALSA声卡驱动
查看>>
Java中的重写
查看>>
C# 程序结构
查看>>
mysql 主从一致性检查以及修复
查看>>
关于eWebEditorAPI
查看>>
生成文件的MD5、SHA、SHA256
查看>>
Go语言类型(布尔、整型、数组、切片、map等)
查看>>
根据段落编号自动添加书签的VBA
查看>>
JS(JavaScript)的j进一步了解9(更新中···)
查看>>
Hadoop源码阅读-HDFS-day2
查看>>
BZOJ2893:征服王(费用流)
查看>>
maven profile切换正式环境和测试环境
查看>>
无法启动WP Emulator
查看>>
杭电1856--More is better
查看>>
js选择排序
查看>>
gradle使用总结
查看>>
F - DFS枚举 CSU - 2087: Tragedy Words
查看>>
mongodb随机查询一条记录的正确方法!
查看>>