对于高性能的 RPC 框架,Netty 作为异步通信框架,几乎成为必备品 。例如,Dubbo 框架中通信组件,还有 RocketMQ 中生产者和消费者的通信,都使用了 Netty 。今天,我们来看看 Netty 的基本架构和原理 。
文章插图
Netty 的特点与 NIONetty 是一个异步的、基于事件驱动的网络应用框架,它可以用来开发高性能服务端和客户端 。
以前编写网络调用程序的时候,我们都会在客户端创建一个 Socket,通过这个 Socket 连接到服务端 。
服务端根据这个 Socket 创建一个 Thread,用来发出请求 。客户端在发起调用以后,需要等待服务端处理完成,才能继续后面的操作 。这样线程会出现等待的状态 。
如果客户端请求数越多,服务端创建的处理线程也会越多,JVM 如此多的线程并不是一件容易的事 。
文章插图
使用阻塞 I/O 处理多个连接
为了解决上述的问题,推出了 NIO 的概念,也就是(Non-blocking I/O) 。其中,Selector 机制就是 NIO 的核心 。
当每次客户端请求时,会创建一个 Socket Channel,并将其注册到 Selector 上(多路复用器) 。
然后,Selector 关注服务端 IO 读写事件,此时客户端并不用等待 IO 事件完成,可以继续做接下来的工作 。
一旦,服务端完成了 IO 读写操作,Selector 会接到通知,同时告诉客户端 IO 操作已经完成 。
接到通知的客户端,就可以通过 SocketChannel 获取需要的数据了 。
文章插图
NIO 机制与 Selector
上面描述的过程有点异步的意思,不过,Selector 实现的并不是真正意义上的异步操作 。
因为 Selector 需要通过线程阻塞的方式监听 IO 事件变更,只是这种方式没有让客户端等待,是 Selector 在等待 IO 返回,并且通知客户端去获取数据 。真正“异步 IO”(AIO)这里不展开介绍,有兴趣可以自行查找 。
说好了 NIO 再来谈谈 Netty,Netty 作为 NIO 的实现,它适用于服务器/客户端通讯的场景,以及针对于 TCP 协议下的高并发应用 。
对于开发者来说,它具有以下特点:
- 对 NIO 进行封装,开发者不需要关注 NIO 的底层原理,只需要调用 Netty 组件就能够完成工作 。
- 对网络调用透明,从 Socket 建立 TCP 连接到网络异常的处理都做了包装 。
- 对数据处理灵活,Netty 支持多种序列化框架,通过“ChannelHandler”机制,可以自定义“编/解码器” 。
- 对性能调优友好,Netty 提供了线程池模式以及 Buffer 的重用机制(对象池化),不需要构建复杂的多线程模型和操作队列 。
学习架构最容易的方式就是从实例入手,从客户端访问服务端的代码来看看 Netty 是如何运作的 。再一次介绍代码中调用的组件以及组件的工作原理 。
假设有一个客户端去调用一个服务端,假设服务端叫做 EchoServer,客户端叫做 EchoClient,用 Netty 架构实现代码如下 。
服务端代码
构建服务器端,假设服务器接受客户端传来的信息,然后在控制台打印 。首先,生成 EchoServer,在构造函数中传入需要监听的端口号 。
文章插图
构造函数中传入需要监听的端口号
接下来就是服务的启动方法:
文章插图
启动 NettyServer 的 Start 方法
Server 的启动方法涉及到了一些组件的调用,例如 EventLoopGroup,Channel 。这些会在后面详细讲解 。
这里有个大致的印象就好:
- 创建 EventLoopGroup 。
- 创建 ServerBootstrap 。
- 指定所使用的 NIO 传输 Channel 。
- 使用指定的端口设置套接字地址 。
- 添加一个 ServerHandler 到 Channel 的 ChannelPipeline 。
- 异步地绑定服务器;调用 sync() 方法阻塞等待直到绑定完成 。
- 获取 Channel 的 CloseFuture,并且阻塞当前线程直到它完成 。
- 关闭 EventLoopGroup,释放所有的资源 。
推荐阅读
- 学会使用 Spring Boot 的异步调用
- 脂肪通过什么排出?
- 用Apple Configurator 2从iOS复制软件
- 健康生活,从一杯清茶开始……
- 送茶叶代表什么意思?
- 程序安装包咋制作的?Qt程序打包三部曲,从应用程序到安装包
- 很多人学Spring框架,总觉得IOC模糊不清?
- 一个人如何开发一款app?
- 我的第一次安卓app开发经历
- 用python处理excel文件有多轻松?工作从未如此简单