netty启动流程图
2022-11-08 11:43:23 14 举报
netty启动流程图
作者其他创作
大纲/内容
NioByteUnsafe.read()
AbstractNioChannel.doRegister()
拿到ServerBootstrap
p.addLast(new ChannelInitializer<Channel>())
AbstractChannel.register(promise);
这里用for死循环
ServerSocketChannel就是服务端自己的channel
EventLoop是线程组中的一个线程,从boosLoopGroup拿出一个线程来处理channel的注册,将channel注册到自己线程的selector上
启动线程
TailContext
将注册的OP_READ事件的channel配置成非阻塞
register(channel)
当channel注册事件时会调用
HeadContext
将一些需要的操作赋值给变量
config()
创建
将serverSocketChannel封装城NioSocketChannel对象
bind(9000)
调用handler的channelRegistered()方法
绑定端口
initChannel(cx)
channelInitializer
public B channel(Class<? extends C> channelClass)
Pipeline管道
NettyServerHandler
group(EventLoopGroup group){group = group;}
addTask(task);
调用next方法
ServerBootstrapAcceptor
boosGroupEventLoopGroup
创建头headHandler和TailContext,在这个管道是双向的
调用super()初始化channel,并将这个channel设置为op_accept事件
从head开始调用serverChannel的pipeline里面所有的inboundHandler
select(curDeadlineNanos)
eventLoop.execute(new Runnable() { @Override public void run() { register0(promise); } });
public ReflectiveChannelFactory(Class<? extends T> clazz) {this.constructor = clazz.getConstructor();}
分支
socketchanel就是客户端连接服务端的channel
runAllTasks()
unsafe.read();
workerGroupEventLoopGroup
client
initAndRegister()
NioMessageUnsafe.read()
将连接过来的socketChannel注册到workgroup里的线程上的一个selector
SingleThreadEventLoop.register(channel)
ServerBootStrap
创建一个EventExecutor的线程组
将channelInitializer添加到pipeline
DefaultSelectorProvider.create()
ServerSocketChannelPipeline管道
创建pipeline的头handler和尾handler
如果有事件就会继续处理事件
child.pipeline().addLast(childHandler);
EventLoopGroup
1.当前是initAndRegister()方法的第三个分支
从队列里面拿任务
这里添加一个异步的任务
调用super方法完成OP_READ事件注册
super(parent);
ServerBootstrap
这里是一个异步任务,主方法在initChannel(cx)就结束了,添加ServerBootstrapAcceptor是由pipeline.invokeHandlerAddedIfNeeded();方法回调执行的
readBuf存放op_accept事件连接过来的所有socketChannel
DEFAULT_EVENT_LOOP_THREADS=当前CPU核数*2
获取之前创建的channelPipeline管道
调用每个handler的channelRegistered()方法,比如我们自己实现的handler,如果实现了channelRegistered()方法,那么在这里就会调用
selector.select(timeoutMillis)
channelFactory.newChannel()
pipeline.fireChannelRead(readBuf.get(i));
调用socketChannel里面所有handler实现的channelRead()方法
客户端连接服务端OP_ACCEPT事件
如果有read、write、op_accept事件时调用
调用handler的channelRead方法
初始化socketChannel的pipeline管道
socketChannel Pipeline管道
MultithreadEventLoopGroup.next()
startThread()
客户端连接服务端的9000端口
调用绑定方法
当客户端连接到服务端时会产生ap_accept事件,从这里开始产生服务器调用事件
pipeline.invokeHandlerAddedIfNeeded();
如果客户端有read读事件过来,那么会回调NioEventLoop
将ChannelInitializer添加到pipeline管道
group方法将创建的EventLoopGroup线程组赋值给成员变量
这里的channelRead()方法是调用ServerBootstrap的channelRead()方法
configureBlocking(false),设置channel为非阻塞模式
processSelectedKeysOptimized()
这里EventLoopGroup是bossLoopGroup的一个线程
group()
ServerSocket Pipeline管道
AbstractNioChannel(){ch.configureBlocking(false);}
注册channel到selector(对照NIO代码)
左边netty封装右边的Nio注册事件
SelectorProvider.provider()
ChannelPipeline p = channel.pipeline()
SingleThreadEventExecutor.run();
OP_READ事件
processSelectedKeys();
public static SelectorProvider create() {createProvider(\"sun.nio.ch.EPollSelectorProvider\");}
EventLoop
拿到EventLoopGroup
pipeline.fireChannelRegistered()
protected MultithreadEventExecutorGroup(){children = new EventExecutor[nThreads];}
创建ServerSocketChannel
堆Nio的封装
注册op_accept事件,这里的0代表accept事件
调用注册方法
doReadMessages(readBuf)
客户端连接服务端OP_READ事件
添加之后的pipeline管道结构
调用pipeline里面的每一个handler的AddedForAllHandlers方法
这里先时向pipeline管道添加ServerBootStartAcceptorhandler,然后会删除channelInitializer,删除后的结构如下:
for死循环处理selectorKeys里面所有的key
创建channelPipeline管道
1.当前是initAndRegister()方法的第二个分支
ServerBootstrap.init(channel)
调用处理方法处理事件
赋值channel
NioServerSocketChannel()
调用for循环处理有事件的selector
processSelectedKeys()
启动流程开始
childGroup.register(child)
向 socketChannel Pipeline管道添加业务handler,也就是自己写的业务NettyServerHandler
创建一个新的线程来处理任务
doStartThread()
pipeline.fireChannelRead(byteBuf);
监听channel的I/O事件,如果没有事件会一直阻塞,直到超时
服务端的serverBootstrap启动完成
doRegister();
ch.configureBlocking(false);
调用handler的方法之后,回回到之前initChannel(cx)方法添加的异步线程任务
SocketUtils.accept(javaChannel())
启动完成
1.当前是initAndRegister()方法第一个分支,先看当前分支
pipeline = newChannelPipeline();
会轮流执行serverSocketChannel事件
当select时间超时或者有了事件时调用以下方法
获取serverSocketChannel对象,并建立连接
通过反射无参的构造方法创建NioServerSocketChannel类,这个类是ServerSocketChannel的封装类
继续调用super方法
将这个新创建的线程放到队列中
NioEventLoop.run()
super(parent)
拿到eventLoop对象
添加我们自己实现的业务handler,然后将之前添加的channelInitializerd的handler删除
调用本地方法,本地方法在调用操作系统的Java_sun_nio_ch_EPoll_epollCtl函数创建SelectorProvider对象
服务端监听端口9000
child就是channelInitializer,就是我们在服务端启动类添加的option.childHandler()
newChannelPipeline();
NioEventLoop.run
register0(promise)
运行队列中的任务
ChannelInitializer
taskQueue.offer(task)
public synchronized InetAddress anyLocalAddress(){anyLocalAddress.holder().hostName = \"0.0.0.0\";}
收藏
收藏
0 条评论
下一页