Netty in Action:传输

本章包含

OIO—阻塞传输

NIO—异步传输

本地传输—JVM内部的异步通信

嵌入式传输—测试你的ChannelHandler

经过一个网络的数据通常是同一种类型:字节。这些数据是如何移动的基本上取决于被我们称之为网络传输的概念,这个概念帮我们抽象了底层的数据传输机制。用户不关心细节,他们只关心他们的字节数据被可靠地传送和接收。

如果你有Java网络编程的经验,你也许会在某个时刻发现,你需要支持比预料还要多的并发连接。接下来,如果你试着从一个阻塞的传输方式切换到非阻塞的,你很可能会碰到一些问题,因为这两种网络API是很不一样的。

然而,Netty在它所有的传输实现上覆盖了一层通用的API,让这样一种转换比直接用JDK实现容易的多。

你生成的代码不会受传输实现细节的影响,你也不用大量地重构你的整个代码。简而言之,你花时间做了有效率的事。

在这一章,我们会学习这个通用的API,通过和JDK做对比来展现它更为强大的易用性。我们会解释Netty每种传输方式的实现细节和适合的用例。有了这些信息,你会发现更容易为你自己的应用选择最好的方式。

阅读本章唯一的先决条件是对Java编程有一定的了解。有网络框架和网络编程的经验就更好了,但不是必须的。

首先我们来看在一个真实的场景中传输是如何工作的。

4.1 案例学习:传输方式迁移

我们会用一个应用来开始传输的学习,这个应用仅仅接收一个连接,然后写“Hi!”到客户端,接着关闭这个连接。

4.1.1 不用Netty实现OIO和NIO

首先我们呈现的是这个应用只用了JDK API的阻塞(OIO)和异步(NIO)的版本。下面这段代码是阻塞的实现。如果你体验过用JDK进行网络编程的“乐趣”,那么这段代码会勾起你“美好的回忆”。

代码清单4.1 不用Netty的阻塞网络编程

这段代码足够处理中等数量的并发客户端。但是随着这个应用变得受欢迎,你会注意到它不能很好地支持上万的并发连接。于是你决定转换到异步网络编程,但是很快就发现异步的API是完全不同的,因此你不得不重写你的应用。

非阻塞的版本如下所示:

代码清单4.2 不用Netty的非阻塞网络编程

你可以看到,虽然这段代码和前一个版本做一样的事情,但是非常不一样。如果重新用非阻塞I/O实现这个简单的应用都需要全部重写代码,那么想想需要移植那些真正复杂的东西需要耗费的精力吧。

记住这个,让我们来看下用Netty来实现时,这个应用长什么样。

4.1.2 用Netty实现OIO和NIO

我们先写另一个阻塞版本,这次用Netty框架,如下所示。

代码清单4.3 采用Netty的阻塞网络编程

4.1.3 非阻塞的Netty版本

下面这个代码清单基本上和4.3一样,除了加粗显示的两行代码。这就是从阻塞(OIO)的传输方式转换到非阻塞(NIO)方式需要做的所有事情。

因为Netty为每种传输方式的实现提供了同样的API,所以不管你选择哪种方式,你的代码几乎不受影响。在所有的情况下,具体实现是由接口Channel,ChannelPipeline,和ChannelHandler定义的。

看过了一些基于Netty传输方式的好处后,让我们再来仔细看下传输API本身。

4.2 传输API

最核心的传输API是接口Channel,用于所有的I/O操作。Channel类层次结构如图4.1所示。

图4.1 Channel接口层次结构

This chapter requires login to view full content. You are viewing a preview.

Login to View Full Content

Course Curriculum

3

框架与 I/O:Spring、Netty 与 Web 容器

理解 Spring Boot 自动装配、AOP 与事务原理,掌握 Netty Reactor 模型及 Tomcat 连接处理机制,构建高内聚、易扩展的应用服务层。
4

高性能中间件:消息、缓存与存储

熟练运用 MySQL 索引/事务、Redis 缓存策略、Kafka/RocketMQ 消息可靠性,以及 ZooKeeper 分布式协调,搭建稳定、解耦的分布式数据底座。
6

云原生:容器化、可观测性与工程效能

通过 Docker/K8s 实现弹性部署,集成 Metrics/Logs/Traces 构建可观测体系,推动 DevOps 与自动化,让架构在云上持续交付与进化。