netty示例
maven依賴
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.22.Final</version>
</dependency>
echo服務(wù)器示例
public class EchoServer {
private int port;
public EchoServer(int port){
this.port = port;
}
public void run() throws Exception{
//bossGroup只負(fù)責(zé)接收客戶端的連接,不做復(fù)雜操作,為了減少資源占用,取值越小越好
EventLoopGroup bossGroup=new NioEventLoopGroup(1, new DefaultThreadFactory("netty-acceptor"));
//workerGroup作為worker,處理boss接收的連接的流量和將接收的連接注冊進(jìn)入這個worker
EventLoopGroup workerGroup=new NioEventLoopGroup(Math.max(1, Runtime.getRuntime().availableProcessors()-1), new DefaultThreadFactory("netty-worker"));
//longBizGroup作為耗時業(yè)務(wù)處理器
EventLoopGroup longBizGroup = new NioEventLoopGroup(100, new DefaultThreadFactory("netty-long-worker"));
try {
ServerBootstrap b=new ServerBootstrap(); //ServerBootstrap負(fù)責(zé)建立服務(wù)端
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class) //指定使用NioServerSocketChannel產(chǎn)生一個ServerChannel用來接收連接匪蝙,會在使用bossGroup的EventLoop中執(zhí)行
.childHandler(new ChannelInitializer<SocketChannel>() {//ChannelInitializer用于配置一個新的Channel用來處理數(shù)據(jù)讀寫,以及業(yè)務(wù)操作等
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline(); //處理器管道
pipeline.addLast(longBizGroup, new EchoServerHandler()); //配置自定義的處理器,并在指定的longBizGroup的EventLoop中執(zhí)行
};
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture f=b.bind(port).sync();
f.channel().closeFuture().sync();
}finally{
bossGroup.shutdownGracefully(); //資源優(yōu)雅釋放
workerGroup.shutdownGracefully();
}
}
public static class EchoServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
TimeUnit.MILLISECONDS.sleep(50); //模擬耗時任務(wù)
ctx.write(msg); //調(diào)用write方法來逐字返回接收到的信息
ctx.flush(); //只調(diào)用write是不會釋放的聪建,它會緩存,直到調(diào)用flush
//ctx.writeAndFlush(msg); //可以直接使用writeAndFlush(msg)
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
public static void main(String[] args) {
int port=8088;
try {
new EchoServer(port).run();
} catch (Exception e) {
e.printStackTrace();
}
}
}
echo服務(wù)器測試
telnet localhost 8088
hello
hello
IO模型
BIO模型
偽異步IO
NIO模型
基于NIO模型交掏,可以演變出以下四種reactor模型:
一妆偏、Reactor單線程模型: Reactor線程負(fù)責(zé)Accept新連接,網(wǎng)絡(luò)IO盅弛,并分派請求到處理器中執(zhí)行钱骂。
對應(yīng)的netty配置
EventLoopGroup reactorGroup = new NioEventLoopGroup(1);
serverBootstrap.group(reactorGroup,reactorGroup);
二、Reactor單線程+線程池模型: Reactor線程負(fù)責(zé)Accept新連接挪鹏,網(wǎng)絡(luò)IO见秽;線程池負(fù)責(zé)處理器執(zhí)行。
對應(yīng)的netty配置
EventLoopGroup reactorGroup = new NioEventLoopGroup(1);
serverBootstrap.group(reactorGroup,reactorGroup);
EventLoopGroup bizGroup = new NioEventLoopGroup(100);
pipeline.addLast(bizGroup, new XxxChannelHandler());
三讨盒、主從Reactor模型:主Reactor線程負(fù)責(zé)Accept新連接解取,從Reactor負(fù)責(zé)網(wǎng)絡(luò)IO和處理器執(zhí)行。
對應(yīng)的netty配置
EventLoopGroup acceptorGroup = new NioEventLoopGroup(1);
EventLoopGroup ioGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors());
serverBootstrap.group(acceptorGroup,ioGroup);
四返顺、主從Reactor+ 線程池模型: 主Reactor線程負(fù)責(zé)Accept新連接禀苦,從Reactor負(fù)責(zé)網(wǎng)絡(luò)IO,線程池負(fù)責(zé)處理器執(zhí)行遂鹊。
對應(yīng)的netty配置
EventLoopGroup acceptorGroup = new NioEventLoopGroup(1);
EventLoopGroup ioGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors());
serverBootstrap.group(acceptorGroup,ioGroup);
EventLoopGroup bizGroup = new NioEventLoopGroup(100);
pipeline.addLast(bizGroup, new XxxChannelHandler());
netty的EventLoop與Channel
netty的BIO模型下的EventLoop分配
netty的NIO模型下的EventLoop分配
EventLoop執(zhí)行邏輯