![f69372a02e95a710a1db2c08a514fd97.png](https://i-blog.csdnimg.cn/blog_migrate/9d4bef9ca25c25992fda41a3ef8c7952.jpeg)
从Reactor设计模式说起
Netty借鉴了Reactor设计模式来实现事件驱动。关于Reactor,最早在Douglas的书籍《Pattern-Oriented Software Architecture Volume 2: Patterns for Concurrent and Networked Objects. Volume 2》中提出:
The reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers.
翻译:Reactor设计模式是一种事件处理模式,在该模式下,来自一个或多个输入源的请求会被并发的投递到一个服务处理器中。服务处理器随后对传入请求进行I/O多路复用,并将它们同步分发给相关的请求处理程序。
Reactor设计模式中有一些核心概念必须提前了解:
- Event:来自Client端的请求会被抽象为可连接、可写、可读等事件,以便交给相应的处理器来处理事件
- Demultiplexer:Demultiplexer为多路复用的含义。在Java NIO中,Selector扮演了Demultiplexer的角色。在多路复用技术下,不再像BIO中那样每一个客户端都需要打开一个Channel,再交给一个独立的线程处理。在NIO中,客户端的请求会共用一个SelectableChannel,来自客户端的所有请求被看做是事件,由Selector监听并转发给Dispatcher进行后续处理
- Dispatcher:每个事件都会有一个特定的Handler进行处理,这个映射关系需要提前绑定(或注册),当事件通过多路复用被转过来后,在分发器中转交给绑定的Handler
- Handler:负责处理这个事件
Demultiplexer与Dispatcher构成了物理上的Reactor。
可以说Reactor是netty中最为核心的内容,因此可以针对Netty对Reactor模式的应用展开分析。不难看到netty也是吸收了前人相当多的优秀经验才能完成这样一款优秀的技术框架。
Demultiplexer
Netty中是什么来扮演Demultiplexer的呢?Reactor是一种Server端的架构,因此在分析源码的时候,直接从Server侧的源码开始分析。我们从官网上的Demo代码入手开启源码分析之路:
// class CommonServer
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new PrintServerHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
// Bind and start to accept incoming connections.
ChannelFuture f = b.bind(port).sync();
// Wait until the server socket is closed.
// In this example, this does not happen, but you can do that to gracefully
// shut down your server.
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
// class PrintServerHandler
public class PrintServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf in = (ByteBuf) msg;
try {
while (in.isReadable()) {
System.out.print((char) in.readByte());
System.out.