在學(xué)習(xí)Dubbo的時(shí)候需要學(xué)習(xí)Netty的流程等寓涨,在此做一個(gè)簡單的入門學(xué)習(xí)。Dubbo中使用的是Netty3颊亮,所以這里說的都是Netty3阀捅。
Netty3可以看成是對Reactor的實(shí)現(xiàn),所以先簡單看下Reactor模式婚瓜。
Reactor模式
Reactor模式是基于事件驅(qū)動的宝鼓,有以下幾種角色存在:
- Handle,句柄巴刻,用來表示打開的文件愚铡,打開的連接等,Java NIO中使用Channel來表示。
- Synchronous Event Demultiplexer沥寥,阻塞的等待發(fā)生在句柄上的一個(gè)或多個(gè)事件碍舍,就是監(jiān)聽事件的到來。Java NIO中使用Selector來表示邑雅。
- EventHandler接口片橡,來處理不同的請求事件。
- Concrete Event Handler淮野,EventHandler實(shí)現(xiàn)捧书。
- Initiation Dispatcher(Reactor),用來管理EventHandler骤星;有事件到來時(shí)分發(fā)事件到EventHandler上去處理经瓷。
Netty中的Reactor模式
Netty中使用了兩層Reactor,Main Reactor用于處理連接請求洞难,Sub Reactor用于處理請求連接之后的讀寫請求舆吮。
Netty中各類釋義
Channel
Reactor模式中使用Handle來表示打開的連接,也就是事件源队贱,在java nio中使用Channel來抽象事件源色冀,Netty中的Channel是自己的抽象。
ChannelEvent
在Netty中使用ChannelEvent來抽象在事件源中可以產(chǎn)生的各種事件柱嫌。
ChannelHandler
作用就是Reactor模式中的EventHandler锋恬,用來處理事件請求。有兩個(gè)子接口:
- ChannelDownstreamHandler编丘,處理從Netty內(nèi)部流向Socket的事件伶氢。
- ChannelUpstreamHandler,處理從Socket進(jìn)入Netty內(nèi)部的事件瘪吏。
ChannelPipeline
每個(gè)Channel都會有一個(gè)ChannelPipeline癣防,用來管理ChannelHandler。ChannelPipeline內(nèi)部有一個(gè)ChannelHandler的雙向鏈表掌眠,以Upstream為正方向蕾盯,Downstream為負(fù)方向。
NioSelector
對應(yīng)的是Reactor模式中的Synchronous Event Demultiplexer蓝丙,Java NIO使用Selector级遭,每個(gè)Channel都會把自己注冊到Selector上,Selector就可以監(jiān)聽Channel中發(fā)生的事件渺尘。當(dāng)有事件發(fā)生的時(shí)候挫鸽,會生成ChannelEvent實(shí)例,該事件會被發(fā)送到Channel對應(yīng)的ChannelPipeline中鸥跟,然后交給ChannelHandler處理丢郊。
NioSelector有兩個(gè)實(shí)現(xiàn):
- Boss盔沫,是Main Reactor,用來處理新連接加入的事件枫匾。
- Worker架诞,是Sub Reactor,用來處理各個(gè)連接的讀寫事件干茉。
ChannelSink
ChannelSink可以看成Handler最后的一個(gè)處于末尾的萬能handler谴忧,只有DownStream包含ChannelSink。
服務(wù)端例子
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();
}
}
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("服務(wù)端接收到消息:" + msg);
ChannelBuffer sendMsg = ChannelBuffers.dynamicBuffer();
sendMsg.writeBytes("我是服務(wù)器角虫,已經(jīng)接到消息".getBytes());
e.getChannel().write(sendMsg);
}else {
e.getChannel().write("我是服務(wù)器沾谓,收到了空消息");
}
e.getChannel().close();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
e.getCause();
e.getChannel().close();
}
}
ChannelFactory主要是用來產(chǎn)生Channel實(shí)例和ChannelSink實(shí)例。
ChannelPipelineFactory主要是用于具體傳輸數(shù)據(jù)的處理戳鹅,是我們自己實(shí)現(xiàn)具體內(nèi)容搏屑,一般我們是往里面添加Handler實(shí)現(xiàn)。
大概的流程是:
- 首先使用Boss和Worker兩個(gè)線程池來初始化一個(gè)ChannelFactory粉楚。
- 使用ChannelFactory來初始化一個(gè)ServerBootstrap實(shí)例。
- 為ServerBootstrap設(shè)置pipelineFactory亮垫,這里用來添加各種處理用的Handler模软。
- 使用Bind方法綁定并監(jiān)聽。
Handler處理順序
Handler跟Servlet中的Filter類似饮潦,在Netty中燃异,Handler存在于Pipeline中,是一個(gè)鏈狀的继蜡。
在Netty中存在兩種ChannelHandler回俐,一種是ChannelDownstreamHandler,另外一種是ChannelUpstreamHandler稀并,從Socket流向Netty內(nèi)部的數(shù)據(jù)經(jīng)過ChannelUpstreamHandler處理仅颇,而從Netty內(nèi)部流向Socket的數(shù)據(jù)由ChannelDownstreamHandler處理。
有關(guān)具體的分析和源碼分析碘举,等到dubbo分析完成之后忘瓦,再做。