netty源码走读(服务端Channel创建流程)
Posted 大数据技术圈
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了netty源码走读(服务端Channel创建流程)相关的知识,希望对你有一定的参考价值。
概念:
NioEventLoop
:
Channel
:
ByteBuf
:
PipeLine
:
ChannelHandler
:
服务器端启动流程:
创建服务器端`Channel`->初始化服务器端`Channel`->注册`Selector`->端口绑定
创建服务器端Channel
从用户代码的bind()
方法入口,调用initAndRegister()
方法,在initAndRegister()
方法中,调用newChannel()
方法,创建服务器端Channel
.ChannelFuture future = bootstrap.bind(8090).sync();
整个调用过程逻辑相对比较清晰。
final ChannelFuture initAndRegister() {
Channel channel = null;
try {
channel = channelFactory.newChannel();
init(channel);
} catch (Throwable t) {
我们跟进newChannel()
方法,看一下Channel
的创建过程.
@Override
public T newChannel() {
try {
return clazz.getConstructor().newInstance();
} catch (Throwable t) {
throw new ChannelException("Unable to create Channel from class " + clazz, t);
}
}
Channel
的创建是以反射的方式创建。那我们就看一下clazz
对应的实例是谁,从而也就知道了反射后创建的Channel
的具体类型了。
public class ReflectiveChannelFactory<T extends Channel> implements ChannelFactory<T> {
private final Class<? extends T> clazz;
public ReflectiveChannelFactory(Class<? extends T> clazz) {
if (clazz == null) {
throw new NullPointerException("clazz");
}
this.clazz = clazz;
}
clazz
是从外部接收的一个Class
实例。既然是外部接收的,就看一下我们的Server
端代码
bootstrap.group(master,worker)
.channel(NioserverSocketChannel.class)
我们跟进channel()
方法
public B channel(Class<? extends C> channelClass) {
if (channelClass == null) {
throw new NullPointerException("channelClass");
}
return channelFactory(new ReflectiveChannelFactory<C>(channelClass));
}
我们传进去的channelClass
也就是NioServerSocketChannel.class
,交给了ReflectiveChannelFactory
。这样就知道了我们服务端创建的是NioServerSocketChannel
。我们跟进NioServerSocketChannel
类,看一下这个类的实例化过程。
由于在利用反射创建NioServerSocketChannel
时候,channel = channelFactory.newChannel();
没有传参进去,我们需要跟进NioServerSocketChannel
的无参构造函数。
public NioServerSocketChannel() {
this(newSocket(DEFAULT_SELECTOR_PROVIDER));
}
跟进this
构造函数
public NioServerSocketChannel(ServerSocketChannel channel) {
super(null, channel, SelectionKey.OP_ACCEPT);
config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}
抽丝剥茧,跟进newSocket()
方法,并将newSocket
的返回值ServerSocketChannel
作为参数传递给NioServerSocketChannel(ServerSocketChannel channel)
private static ServerSocketChannel newSocket(SelectorProvider provider) {
try {
return provider.openServerSocketChannel();
} catch (IOException e) {
throw new ChannelException("Failed to open a server socket.", e);
}
}
在newSocket
中,netty
和jdk
底层Socket
建立了连接。
在初始化NioServerSocketChannel
时,创建了NioServerSocketChannelConfig
,主要负责给创建的jdk底层的Socket的TCP
相关配置。
我们跟进
public NioServerSocketChannel(ServerSocketChannel channel) {
super(null, channel, SelectionKey.OP_ACCEPT);
进入父类的构造函数
protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent, ch, readInterestOp);
}
继续跟进
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent);
this.ch = ch;
this.readInterestOp = readInterestOp;
try {
ch.configureBlocking(false);
} catch (IOException e) {
当我们看到ch.configureBlocking(false)
这行代码的时候,就知道了创建出来的Socket
是非阻塞模式。
继续跟进父类
protected AbstractChannel(Channel parent) {
this.parent = parent;
id = newId();
unsafe = newUnsafe();
pipeline = newChannelPipeline();
}
创建了Channel
的唯一标识id,unsafe
封装了Channel
和底层相关的操作,pipeline
封装了跟服务端程序相关的逻辑链。至此服务端NioServerSocketChannel
创建成功。
以上是关于netty源码走读(服务端Channel创建流程)的主要内容,如果未能解决你的问题,请参考以下文章