初始化并啟動Netty服務端過程如下:
public static void main(String[] args) {
// 創(chuàng)建mainReactor
NioEventLoopGroup boosGroup = new NioEventLoopGroup();
// 創(chuàng)建工作線程組
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
final ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap
// 組裝NioEventLoopGroup
.group(boosGroup, workerGroup)
// 設(shè)置channel類型為NIO類型
.channel(NioServerSocketChannel.class)
// 設(shè)置連接配置參數(shù)
.option(ChannelOption.SO_BACKLOG, 1024)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childOption(ChannelOption.TCP_NODELAY, true)
// 配置入站、出站事件handler
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) {
// 配置入站、出站事件channel
ch.pipeline().addLast(...);
ch.pipeline().addLast(...);
}
});
// 綁定端口
int port = 8080;
serverBootstrap.bind(port).addListener(future -> {
if (future.isSuccess()) {
System.out.println(new Date() + ": 端口[" + port + "]綁定成功!");
} else {
System.err.println("端口[" + port + "]綁定失敗!");
}
});
}
基本過程如下:
- 初始化創(chuàng)建2個NioEventLoopGroup拧烦,其中boosGroup用于Accetpt連接建立事件并分發(fā)請求,
workerGroup用于處理I/O讀寫事件和業(yè)務邏輯- 基于ServerBootstrap(服務端啟動引導類)谁帕,配置EventLoopGroup上渴、Channel類型,連接參數(shù)元暴、配置入站篷扩、出站事件handler
- 綁定端口,開始工作
結(jié)合上面的介紹的Netty Reactor模型茉盏,介紹服務端Netty的工作架構(gòu)圖:
server端包含1個Boss NioEventLoopGroup和1個Worker NioEventLoopGroup鉴未,NioEventLoopGroup相當于1個事件循環(huán)組,這個組里包含多個事件循環(huán)NioEventLoop鸠姨,每個NioEventLoop包含1個selector和1個事件循環(huán)線程铜秆。
每個Boss NioEventLoop循環(huán)執(zhí)行的任務包含3步:
- 輪詢accept事件
- 處理accept I/O事件,與Client建立連接讶迁,生成NioSocketChannel羽峰,并將NioSocketChannel注冊到某個Worker NioEventLoop的Selector上
- 處理任務隊列中的任務,runAllTasks添瓷。任務隊列中的任務包括用戶調(diào)用eventloop.execute或schedule執(zhí)行的任務梅屉,或者其它線程提交到該eventloop的任務。
每個Worker NioEventLoop循環(huán)執(zhí)行的任務包含3步:
- 輪詢read鳞贷、write事件坯汤;
- 處I/O事件,即read搀愧、write事件惰聂,在NioSocketChannel可讀、可寫事件發(fā)生時進行處理
- 處理任務隊列中的任務咱筛,runAllTasks搓幌。
其中任務隊列中的task有3種典型使用場景
1. 用戶程序自定義的普通任務
ctx.channel().eventLoop().execute(new Runnable() {
@Override
public void run() {
//...
}
});
2. 非當前reactor線程調(diào)用channel的各種方法
例如在推送系統(tǒng)的業(yè)務線程里面,根據(jù)用戶的標識迅箩,找到對應的channel引用溉愁,然后調(diào)用write類方法向該用戶推送消息,就會進入到這種場景饲趋。最終的write會提交到任務隊列中后被異步消費拐揭。
3. 用戶自定義定時任務
ctx.channel().eventLoop().schedule(new Runnable() {
@Override
public void run() {
}
}, 60, TimeUnit.SECONDS);
技術(shù)討論 & 疑問建議 & 個人博客
版權(quán)聲明: 本博客所有文章除特別聲明外撤蟆,均采用 CC BY-NC-SA 3.0 許可協(xié)議,轉(zhuǎn)載請注明出處堂污!