简介

Netty为什么这么优秀,它在JDK本身的NIO基础上又做了什么改进呢?它的架构和工作流程如何呢?请走进今天的netty系列文章之:netty架构概述。

netty架构图

netty的主要作用就是提供一个简单的NIO框架可以和上层的各种协议相结合,最终实现高性能的服务器。下面是netty官网提供的架构图:

从上图可以看到netty的核心主要分成三部分,分别是可扩展的event model、统一的API、和强大的Byte Buffer。这三个特性是netty的制胜法宝。

下面会从这几个方面对netty的特性进行详细说明,务必让读者了解到netty的优秀之处。

丰富的Buffer数据机构

首先从最底层的Buffer数据结构开始,netty提供了一个io.netty.buffer的包,该包里面定义了各种类型的ByteBuf和其衍生的类型。

netty Buffer的基础是ByteBuf类,这是一个抽象类,其他的Buffer类基本上都是由该类衍生而得的,这个类也定义了netty整体Buffer的基调。

netty重写ByteBuf其目的是让最底层的ByteBuf比JDK自带的更快更适合扩展。具体而言,netty的ByteBuf要比JDK中的ByteBuffer要快,同时,扩展也更加容易,大家可以根据需要Buf进行自定义。另外netty有一些内置的复合缓冲区类型,所以可以实现透明的零拷贝。对于动态缓冲区类型来说,可以和StringBuffer一样按需扩展,非常好用。

零拷贝

什么是零拷贝呢?零拷贝的意思是在需要拷贝的时候不做拷贝。我们知道数据在使用底层协议进行传输的过程中是会被封装成为一个个的包进行传输。当传输的数据过大,一个包放不下的时候,还需要对数据进行拆分,目的方在接收到数据之后,需要对收到的数据进行组装,一般情况下这个组装的操作是对数据的拷贝,将拆分过后的对象拷贝到一个长的数据空间中。

比如下面的例子所示,将底层的TCP包组合称为顶层的HTTP包,但是并没有进行拷贝:

具体怎么拷贝呢?在上一篇文章中,我们知道netty提供了一个工具类方法Unpooled,这个工具类中有很多wrapped开头的方法,我们举几个例子:

 public static ByteBuf wrappedBuffer(byte[]... arrays) {
return wrappedBuffer(arrays.length, arrays);
} public static ByteBuf wrappedBuffer(ByteBuf... buffers) {
return wrappedBuffer(buffers.length, buffers);
} public static ByteBuf wrappedBuffer(ByteBuffer... buffers) {
return wrappedBuffer(buffers.length, buffers);
}

上面三个方法分别是封装byte数组、封装ByteBuf和封装ByteBuffer,这些方法都是零拷贝。大家可以在实际的项目中根据实际情况,自行选用。

统一的API

一般来说,在传统的JDK的IO API中,根据传输类型或者协议的不同,使用的API也是不同的。我们需要对不同的传输方式开发不同的应用程序,不能做到统一。这样的结果就是无法平滑的迁移,并且在程序扩展的时候需要进行额外的处理。

什么是传输方式呢?这里是指以什么样的方式来实现IO,比如传统的阻塞型IO,我们可以称之为OIO,java的new IO可以称之为NIO,异步IO可以称之为AIO等等。

并且JDK中的传统IO和NIO是割裂的,如果在最开始你使用的是传统IO,那么当你的客户数目增长到一定的程度准备切换到NIO的时候,就会发现切换起来异常复杂,因为他们是割裂的。

为了解决这个问题,netty提供了一个统一的类Channel来提供统一的API。

先看下Channel中定义的方法:

从上图我们可以看到使用Channel可以判断channel当前的状态,可以对其进行参数配置,可以对其进行I/O操作,还有和channel相关的ChannelPipeline用来处理channel关联的IO请求和事件。

使用Channel就可以对NIO的TCP/IP,OIO的TCP/IP,OIO的UDP/IP和本地传输都能提供很好的支持。

传输方式的切换,只需要进行很小的成本替换。

当然,如果你对现有的实现都不满意的话,还可以对核心API进行自定义扩展。

事件驱动

netty是一个事件驱动的框架,事件驱动框架的基础就是事件模型,Netty专门为IO定义了一个非常有效的事件模型。可以在不破坏现有代码的情况下实现自己的事件类型。netty中自定义的事件类型通过严格的类型层次结构跟其他事件类型区分开来,所以可扩展性很强。

netty中的事件驱动是由ChannelEvent、ChannelHandler和ChannelPipeline共同作用的结果。其中ChannelEvent表示发生的事件,ChannelHandler定义了如何对事件进行处理,而ChannelPipeline类似一个拦截器,可以让用户自行对定义好的ChannelHandler进行控制,从而达到控制事件处理的结果。

我们看一个简单的自定义Handler:

public class MyHandler extends SimpleChannelInboundHandler<Object> {

    @Override
public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
// 对消息进行处理
ByteBuf in = (ByteBuf) msg;
try {
log.info("收到消息:{}",in.toString(io.netty.util.CharsetUtil.US_ASCII));
}finally {
ReferenceCountUtil.release(msg);
}
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
//异常处理
cause.printStackTrace();
ctx.close();
}
}

上面的例子中,我们定义了如何对接收到的消息和异常进行处理。在后续的文章中我们会详细对ChannelEvent、ChannelHandler和ChannelPipeline之间的交互使用进行介绍。

其他优秀的特性

除了上面提到的三大核心特性之外,netty还有其他几个优点,方便程序员的开发工作。

比如对SSL / TLS的支持,对HTTP协议的实现,对WebSockets 实现和Google Protocol Buffers的实现等等,表明netty在各个方面多个场景都有很强的应用能力。

总结

netty是由三个核心组件构成:缓冲区、通道和事件模型,通过理解这三个核心组件是如何相互工作的,那么再去理解建立在netty之上的高级功能就不难了。

本文的例子可以参考:learn-netty4

本文已收录于 http://www.flydean.com/03-netty-architecture/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

netty系列之:netty架构概述的更多相关文章

  1. 【读后感】Netty 系列之 Netty 高性能之道 - 相比 Mina 怎样 ?

    [读后感]Netty 系列之 Netty 高性能之道 - 相比 Mina 怎样 ? 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商 ...

  2. Netty 系列之 Netty 高性能之道 高性能的三个主题 Netty使得开发者能够轻松地接受大量打开的套接字 Java 序列化

    Netty系列之Netty高性能之道 https://www.infoq.cn/article/netty-high-performance 李林锋 2014 年 5 月 29 日 话题:性能调优语言 ...

  3. Netty 系列之 Netty 高性能之道

    1. 背景 1.1. 惊人的性能数据 最近一个圈内朋友通过私信告诉我,通过使用 Netty4 + Thrift 压缩二进制编解码技术,他们实现了 10 W TPS(1 K 的复杂 POJO 对象)的跨 ...

  4. Netty系列之Netty高性能之道

    转载自http://www.infoq.com/cn/articles/netty-high-performance 1. 背景 1.1. 惊人的性能数据 最近一个圈内朋友通过私信告诉我,通过使用Ne ...

  5. 转:Netty系列之Netty高性能之道

    1. 背景 1.1. 惊人的性能数据 最近一个圈内朋友通过私信告诉我,通过使用Netty4 + Thrift压缩二进制编解码技术,他们实现了10W TPS(1K的复杂POJO对象)的跨节点远程服务调用 ...

  6. Netty系列之Netty百万级推送服务设计要点

    1. 背景 1.1. 话题来源 最近很多从事移动互联网和物联网开发的同学给我发邮件或者微博私信我,咨询推送服务相关的问题.问题五花八门,在帮助大家答疑解惑的过程中,我也对问题进行了总结,大概可以归纳为 ...

  7. 【netty】Netty系列之Netty百万级推送服务设计要点

    1. 背景 1.1. 话题来源 最近很多从事移动互联网和物联网开发的同学给我发邮件或者微博私信我,咨询推送服务相关的问题.问题五花八门,在帮助大家答疑解惑的过程中,我也对问题进行了总结,大概可以归纳为 ...

  8. Netty系列之Netty线程模型

    Reference: http://www.infoq.com/cn/articles/netty-threading-model 1. 背景 1.1. Java线程模型的演进 1.1.1. 单线程 ...

  9. Netty系列之Netty百万级推送服务设计要点(转)

    1. 背景 1.1. 话题来源 最近很多从事移动互联网和物联网开发的同学给我发邮件或者微博私信我,咨询推送服务相关的问题.问题五花八门,在帮助大家答疑解惑的过程中,我也对问题进行了总结,大概可以归纳为 ...

随机推荐

  1. 携程二面:讲讲 MySQL 中的 WAL 策略和 CheckPoint 技术

    前段时间我在准备暑期实习嘛,这是当时面携程的时候二面的一道问题,我一脸懵逼,赶紧道歉,不好意思不知道没了解过,面试官又解释说 redo log,我寻思着 redo log 我知道啊,WAL 是啥?给面 ...

  2. vue 快速入门 系列 —— vue loader 上

    其他章节请看: vue 快速入门 系列 vue loader 上 通过前面"webpack 系列"的学习,我们知道如何用 webpack 实现一个不成熟的脚手架,比如提供开发环境和 ...

  3. external-attacher源码分析(1)-main方法与启动参数分析

    更多 ceph-csi 其他源码分析,请查看下面这篇博文:kubernetes ceph-csi分析目录导航 摘要 ceph-csi分析-external-attacher源码分析.external- ...

  4. Redis高并发快的3大原因详解

    1. Redis的高并发和快速的原因 1.redis是基于内存的,内存的读写速度非常快: 2.redis是单线程的,省去了很多上下文切换线程的时间: 3.redis使用多路复用技术,可以处理并发的连接 ...

  5. 配置本地yum源以及挂载镜像

    配置本地yum源以及挂载镜像(centos7.6) 配置yum源 # cd /etc/yum.repos.d 可以备份或者删除里面的文件 新建文件 # touch /etc/yum.repos.d/l ...

  6. 4、saltstack的使用

    官方文档地址:http://repo.saltstack.com/#rhel 4.1.saltstatck介绍: 用户要一致,这里使用的是root用户: 用于批量管理成百上千的服务器: 并行的分发,使 ...

  7. 6、基本数据类型(list)

    6.1.列表: 1.li = [1, 12, 9, "age", ["孙子涵", ["19", 10], "张涵予"], ...

  8. HDU 4821 2013长春现场赛hash

    题意: 一个字符串S  问其中有几个子串能满足以下条件: 1.长度为M*L 2.可以被分成M个L长的小串  每个串都不一样 分析: hash方法,一个种子base,打表出nbase[i]表示base的 ...

  9. Postman团队协作开发

    介绍 Postman是一款强大的API开发调试软件,它跨平台(真正跨平台,支持linux/mac os/windows),同时还提供浏览器插件,可以说是一个良心软件, 今天主要说一下Postman团队 ...

  10. linux学习之路第六天(文件目录类第二部分)

    文件目录类 1.cat指令 作用:查看文件内容,是以只读的方式打开. 基本语法 cat [选项] 要查看的文件 常用选项 -n; 使用细节: cat只能浏览文件,而不能修改文件,通常会和more一起使 ...