Bootstrap 、ServerBootStrap
Bootstrap 意思是引導,一個netty應用通常由一個Bootstrap開始,它主要作用是配置整個Netty程序,串聯各個組件。Bootstrap、ServerBootStrap 分別對應客戶端啓動引導類與服務啓動引導類
客戶端聲明:
Bootstrap bootstrap = new Bootstrap();
NioEventLoopGroup group = new NioEventLoopGroup();
bootstrap.group(group)
.channel(NioSocketChannel.class)
//對NioSocketChannel 可以綁定屬性
.attr(AttributeKey.newInstance("key"), "values")
//option可以設置tcp相關的屬性
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
.option(ChannelOption.SO_KEEPALIVE, true)
.option(ChannelOption.TCP_NODELAY, true)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new NettyClientHandler());
}
});
服務端聲明:
ServerBootstrap serverBootstrap = new ServerBootstrap();
//--|--線程模型
//-------|--賦值監聽端口,真正的跟客戶端處理會交給workerGroup
NioEventLoopGroup boss = new NioEventLoopGroup();
//-------|--新連接的線程組,表示處理每一條連接的數據讀寫的線程組
NioEventLoopGroup worker = new NioEventLoopGroup();
//----|連接處理邏輯
ChannelInitializer<NioSocketChannel> nioSocketChannel = new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
System.out.println("Server init ChannelInitializer");
nioSocketChannel.pipeline().addLast(new NettyServerHandler());
}
};
//--|引導類 based on 線程模型+I/O模型+讀寫處理邏輯
serverBootstrap
.group(boss, worker)//設置引導類
//--|I/O 模型
.channel(NioServerSocketChannel.class)
.hander(null)//該handler對應的是boosGroup
.childHandler(nioSocketChannel)//該handler對應的是workGroup
//--NioServerSocketChannel channelClass 設置附加屬性
.attr(AttributeKey.newInstance("ss_keys"), "values")
//--NioServerSocketChannel 設置附加TCP相關屬性
.option(ChannelOption.SO_BACKLOG, 1024)//線程隊列得到的連接個數
//----給每一條連接指定自定義屬性
.childAttr(AttributeKey.newInstance("s_keys"), "values")
//----給子連接提供TCP 比較基礎的設置
.childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE)
.childOption(ChannelOption.TCP_NODELAY, Boolean.TRUE);
Channel
- Netty網絡通信的組件,能夠用於執行網絡I/O操作
- 通過Channel可獲得當前網絡連接的通道狀態
- 通過Channel可獲得網絡連接的配置參數(如緩衝池大小)
- Channel提供異步的網絡I/O操作(如建立連接、讀寫、綁定端口),異步調用意味着任何I/O調用都會立即返回,並且不保證在調用結束時相關I/操作已經完成。
- 調用將同步返回一個ChannelFuture實例,通過註冊監聽器到ChannelFuture上,可以I/O操作成功、失敗或取消時等相關事件回調。
- 支持關聯I/O操作與對應的處理程序
- 不同協議、不同的阻塞類型的連接都有不同的Channel類型與之對應,常用的Channel類型有 :
7.1. NioSocketChannel ,異步的客戶端Tcp Socket。
7.2. NioServerSocketChannel , 異步的服務器端Tcp Socket連接。
7.3. NioDatagramChannel , 異步的UDP連接。
7.4. NioSctpChannel ,異步的客戶端Sctp連接。
7.5. NioSctpServerChannel ,異步的Sctp服務端連接,這些通道囊括了所有的UDP和TCP網絡I/O以及文件I/O。
Selector
- Netty基於Selector對象實現I/O多路複用,通過Selector一個線程可以監聽多個連接的Channel事件。
- 當向一個Selector中註冊Channel後,Selector內部的機制就可以自動不斷地查詢(Select)這些註冊的Channel是否有已就緒的I/O事件,已做到一個線程可以高效地管理多個Channel。
ChannelHandler 接口及其實現
- ChannelHandler 是一個接口,處理I/O事件或攔截I/O操作,並將其轉發其ChannelPipeline(業務處理鏈)中的下一個處理程序。
- ChannelHandler 本身並沒有提供很多方法,因爲這個接口有許多的方法需要實現,以做到子類去繼承實現。
如:channelRead 、channelReadComplete、channelActive。 - ChannelHandler 及子類
3.1 ChannelInboundHander 用於處理入棧I/O事件;
3.2 ChannelOutboundHander 用於處理出棧I/O事件;
3.3 ChannelInboundHandlerAdapter 適配器 -> 用於處理入棧I/O事件;
3.4 ChannelOutboundHandlerAdapter 適配器 -> 用於處理出棧I/O事件;
3.5 ChannelDuplexHandler 用於處理入棧與出棧事件。
Pipeline 和 ChannelPipeline
- ChannelPipeline是一個Handler的集合,負責處理和攔截inbound或者outbound的事件和操作,相當於一個貫穿Netty訂單鏈。ChannelPipeline是保存了ChannelHandler的list,用於處理或攔截Channel的入棧事件和出棧操作。
- ChannelPipeline實現了一種高級形式的攔截過濾器模式,使用戶可以掌控事件的處理方式,已經Channel中各個的ChannelHandler是如何相互交互的。
- 在Netty中每個Channel都有且僅有一個ChannelPipeline與之對應:
3.1 : 一個Channel包含了一個ChannelPipeline,而ChannelPipeline又維護了一個由ChannelHandlerContext組成的雙向鏈表,並且每個ChannelHanderContext中又關聯着一個ChannelHandler;
3.2 : 入站事件和出站事件在一個雙向鏈表中,入站事件會從鏈表head往後傳遞到最後一個入站handler,出站事件會從鏈表tail往前傳遞到最前面一個出站的handler,兩種類型的handler不會產生干擾;
ChannelHandlerContext
- 保存Channel相關的所有上下文信息,同時關聯一個ChannelHandler對象
- 既ChannelHanderContext中包含一個具體的事件處理器ChannelHandler,同時ChannelHandlerContext中也也綁定了對應的pipeline和Channel的信息,方便對ChannellHandler進行調用;
EventLoopGroup 和 NioEventLoopGroup
- EventLoopGroup 是一組Event的抽象 ,Netty爲了更好的利用多核CPU資源,一般會有多個EventLoop同時工作,每個EventLoop維護着一個Selector實例;
- EventLoopGroup提供next接口,可以從組裏面按照一定規則獲取其中一個EventLoop來處理任務。如BoosEventLoopGroup 和 WorkerEventLoopGroup。
- 通常一個服務端口既一個
ServerSocketChannel
對應一個Selector
和一個EventLoop
線程。 - BossEventLoop負責接收科幻的連接並將SocketChannel交給WorkerEventLoopGroup來進行IO處理。
BossEventLoopGroup通常是一個單線程的EventLoop,EventLoop維護着一個註冊了ServerSocketChannel的Selector實例,BossEventLoop不斷輪詢Selector將連接從事件中分離了出來,通常是 OP_ACCEPT 事件 ,然後將接收到的SocketChannel交給WorkerEventLoopGroup ,WorkerEventLoopGroup會由next選擇其中一個EventLoopGroup來將這個SocketChanel註冊到其維護的Selector,並對其後續的IO事件進行處理。
Unpooled
- Netty提供一個專門用來操作緩衝區(Netty的數據容器)的工具類
- 常用方法
public static ByteBuf copiedBuffer(CharSequence string , Charset charset)
@Test
public void test() {
//1 創建一個byte[10]
ByteBuf buffer = Unpooled.buffer(10);
//2 數據寫入
for (int i = 0; i < 10; i++) {
buffer.writeByte(i);
}
//3 數據讀取
for (int i = 0; i < buffer.capacity(); i++) {
System.out.println(buffer.getByte(i));
}
}
比起ByteBuffer,明顯少了惱人的flip()方法,是通過自身維護了readerIndex與writerIndex實現的;