一、通信组件
在Netty中有网络通信层负责网络之间的通信,在Netty中的网络通信层中存在
Bootstrap以及ServerBootstrap两个组件。
1.1、ServerBootstrap
ServerBootstrap用于服务端,会绑定两个EventLoopGroup,分别为
BossEventLoopGroup以及WorkerEventLoopGroup,Boss用于接收新的客户端,Worker用户处理连接。
EventLoopGroup boss = new NioEventLoopGroup(1);
EventLoopGroup work = new NioEventLoopGroup();
1.2、Bootstrap
Bootstrap用于客户端,只会绑定一个EventLoopGroup。
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(boss, work)
.channel(NioServerSocketChannel.class)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childHandler(new ChannelInitializer() {
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline channelPipeline = ch.pipeline();
channelPipeline.addLast(new JSONDecoder());
channelPipeline.addLast(new JSONEncoder());
channelPipeline.addLast(new ServerHandler());
}
});
1.3、Channel
在Netty中还存在Channel组件,这个组件用于数据的传输,Channel中提供了
一些网络的操作,如bind、registry、connect、read、write、flush等。
通过Channel这个组件作为网络通信的载体,提供与底层Socket交互的能力。
如上代码中为ServerBootstrap创建了NioServerSocketChannel。
二、线程调度
Netty的线程调度问题依赖于Reactor,Reactor下有两个对应的组件分别为
EventLoopGroup以及EventLoop。
2.1、EventLoopGroup
EventLoopGroup本质是一个线程池,主要负责接收I/O请求,并分配线程处理请求。
2.2、EventLoop
EventLoop则负责处理EventLoopGroup分配给它的请求。
EventLoopGroup与EventLoop以及Channel的关系是,一个EventLoopGroup包含多个EventLoop。
每个EventLoop负责处理Channel内的I/O事件,EventLoop同一时间会与一个线程绑定,每个EventLoop负责处理多个Channel,选择哪个Channel处理是由Selector负责循环决定的,并且每建立一个Channel,EventLoopGroup会选择一个EventLoop与其绑定.
三、数据处理
3.1、ChannelPipeline
在Netty中负责处理ChannelHandler的是ChannelPipeline,它可以对Channel的数据进行拦截以及处理,如在Dubbo中进行数据序列化以及反序列化都是通过ChannelPipeline处理的。
ChannelPipeline p = ch.pipeline();
p.addLast(new JSONDecoder());
p.addLast(new JSONEncoder());
p.addLast(client);
四、Netty的流程如下:
-
1、服务端启动初始化时,BossEventLoopGroup和WorkerEventLoopGroup分别负责监听网络连接事件,当有新的网络连接事件到达时则将Channel注册到WorkerEventLoopGroup
-
2、WorkerEventLoopGroup会被分配一个EventLoop负责处理该Channel的读写事件,每个EventLoop都是单线程的,通过Selector进行事件循环。
-
3、当客户端发起I/O读写事件时,服务端的EventLoop会进行数据读取,然后通过Pipeline触发各种监听器进行数据的加工以及处理。
-
4、当数据写回客户端时,将处理结果在ChannelPipeline的ChannelOutboundHandler中传播,最后到达客户端.
Server端实现:
public void startServer() {
try {
EventLoopGroup boss = new NioEventLoopGroup(1);
EventLoopGroup work = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(boss, work)
.channel(NioServerSocketChannel.class)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childHandler(new ChannelInitializer() {
@Override
protected void initChannel(Channel ch) throws Exception{
ChannelPipeline channelPipeline = ch.pipeline();
channelPipeline.addLast(new JSONDecoder());
channelPipeline.addLast(new JSONEncoder());
channelPipeline.addLast(new ServerHandler());
}
});
ChannelFuture future = bootstrap.bind(ip,port).sync();
if (future .isSuccess()){
System.out.println("server start");
}
} catch (Exception e) {
e.printStackTrace();
}
}
客户端实现:
public void initClient() {
EventLoopGroup group = new NioEventLoopGroup();
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(new JSONDecoder());
p.addLast(new JSONEncoder());
p.addLast(new ClientHandler());
}
});
try {
ChannelFuture f = b.connect(ip,port).sync();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
我是陈汤姆,bye了个bye!!!当然了如果有兴趣可以关注我的公众号啊!!