Netty3服务端流程简介

在学习Dubbo的时候需要学习Netty的流程等,在此做一个简单的入门学习。Dubbo中使用的是Netty3,所以这里说的都是Netty3。

Netty3可以看成是对Reactor的实现,所以先简单看下Reactor模式。

Reactor模式

Reactor模式是基于事件驱动的,有以下几种角色存在:

  • Handle,句柄,用来表示打开的文件,打开的连接等,Java NIO中使用Channel来表示。
  • Synchronous Event Demultiplexer,阻塞的等待发生在句柄上的一个或多个事件,就是监听事件的到来。Java NIO中使用Selector来表示。
  • EventHandler接口,来处理不同的请求事件。
  • Concrete Event Handler,EventHandler实现。
  • Initiation Dispatcher(Reactor),用来管理EventHandler;有事件到来时分发事件到EventHandler上去处理。

Netty中的Reactor模式

Netty中使用了两层Reactor,Main Reactor用于处理连接请求,Sub Reactor用于处理请求连接之后的读写请求。

Netty中各类释义

Channel

Reactor模式中使用Handle来表示打开的连接,也就是事件源,在java nio中使用Channel来抽象事件源,Netty中的Channel是自己的抽象。

ChannelEvent

在Netty中使用ChannelEvent来抽象在事件源中可以产生的各种事件。

ChannelHandler

作用就是Reactor模式中的EventHandler,用来处理事件请求。有两个子接口:

  • ChannelDownstreamHandler,处理从Netty内部流向Socket的事件。
  • ChannelUpstreamHandler,处理从Socket进入Netty内部的事件。

ChannelPipeline

每个Channel都会有一个ChannelPipeline,用来管理ChannelHandler。ChannelPipeline内部有一个ChannelHandler的双向链表,以Upstream为正方向,Downstream为负方向。

NioSelector

对应的是Reactor模式中的Synchronous Event Demultiplexer,Java NIO使用Selector,每个Channel都会把自己注册到Selector上,Selector就可以监听Channel中发生的事件。当有事件发生的时候,会生成ChannelEvent实例,该事件会被发送到Channel对应的ChannelPipeline中,然后交给ChannelHandler处理。

NioSelector有两个实现:

  • Boss,是Main Reactor,用来处理新连接加入的事件。
  • Worker,是Sub Reactor,用来处理各个连接的读写事件。

ChannelSink

ChannelSink可以看成Handler最后的一个处于末尾的万能handler,只有DownStream包含ChannelSink。

服务端例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class NettyServerTest {

private final int port;

public NettyServerTest(int port){
this.port = port;
}

public void startServer(){
ChannelFactory channelFactory = new NioServerSocketChannelFactory(Executors.newCachedThreadPool(),Executors.newCachedThreadPool());
ServerBootstrap serverBootstrap = new ServerBootstrap(channelFactory);

serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(new ServerHandlerTest());
}
});

serverBootstrap.bind(new InetSocketAddress(port));
}

public static void main(String[] args) {
new NettyServerTest(8888).startServer();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class ServerHandlerTest extends SimpleChannelUpstreamHandler {
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
ChannelBuffer channelBuffer = (ChannelBuffer)e.getMessage();
String msg = channelBuffer.toString(Charset.defaultCharset());
if(msg != null && !"".equals(msg)){
System.out.println("服务端接收到消息:" + msg);
ChannelBuffer sendMsg = ChannelBuffers.dynamicBuffer();
sendMsg.writeBytes("我是服务器,已经接到消息".getBytes());
e.getChannel().write(sendMsg);
}else {
e.getChannel().write("我是服务器,收到了空消息");
}
e.getChannel().close();
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
e.getCause();
e.getChannel().close();
}
}

ChannelFactory主要是用来产生Channel实例和ChannelSink实例。

ChannelPipelineFactory主要是用于具体传输数据的处理,是我们自己实现具体内容,一般我们是往里面添加Handler实现。

大概的流程是:

  • 首先使用Boss和Worker两个线程池来初始化一个ChannelFactory。
  • 使用ChannelFactory来初始化一个ServerBootstrap实例。
  • 为ServerBootstrap设置pipelineFactory,这里用来添加各种处理用的Handler。
  • 使用Bind方法绑定并监听。

Handler处理顺序

Handler跟Servlet中的Filter类似,在Netty中,Handler存在于Pipeline中,是一个链状的。

在Netty中存在两种ChannelHandler,一种是ChannelDownstreamHandler,另外一种是ChannelUpstreamHandler,从Socket流向Netty内部的数据经过ChannelUpstreamHandler处理,而从Netty内部流向Socket的数据由ChannelDownstreamHandler处理。

有关具体的分析和源码分析,等到dubbo分析完成之后,再做。

坚持原创技术分享,您的支持将鼓励我继续创作!
Fork me on GitHub