傻大方


首页 > 潮·科技 > >

绝!真就一文全懂!Netty线程模型+启动详细分析+内存管理( 四 )

傻大方提要:【绝!真就一文全懂!Netty线程模型+启动详细分析+内存管理( 四 )】channel = channelFactory.newChannel(); 前面在ServerBootstrap实例设置服务端Channel时 , 设置了这个Channel的类型 , 这里就通过工厂类的方法生成NioServerSocketChannel对象...



按关键词阅读:


channel = channelFactory.newChannel();前面在ServerBootstrap实例设置服务端Channel时 , 设置了这个Channel的类型 , 这里就通过工厂类的方法生成NioServerSocketChannel对象 。
追溯NioServerSocketChannel的默认构造函数 , 我们可以发现在构造该实例时 , 设置了channel为非阻塞模式、SelectionKey.OP_ACCEPT事件、channelId 、NioMessageUnsafe(封装了用于数据传输操作的函数)、DefaultChannelPipeline和 NioServerSocketChannelConfig 属性 。
2.init这个Channel
void init(Channel channel) throws Exception {// 设置配置的option参数final Map, Object> options = options0();synchronized (options) {channel.config().setOptions(options);}final Map, Object> attrs = attrs0();synchronized (attrs) {for (Entry, Object> e: attrs.entrySet()) {@SuppressWarnings("unchecked")AttributeKey key = (AttributeKey) e.getKey();channel.attr(key).set(e.getValue());}}// 获取绑定的pipelineChannelPipeline p = channel.pipeline();// 准备child用到的4个partfinal EventLoopGroup currentChildGroup = childGroup;final ChannelHandler currentChildHandler = childHandler;final Entry, Object>[] currentChildOptions;final Entry, Object>[] currentChildAttrs;synchronized (childOptions) {currentChildOptions = childOptions.entrySet().toArray(newOptionArray(childOptions.size()));}synchronized (childAttrs) {currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(childAttrs.size()));}// 为NioServerSocketChannel的pipeline添加一个初始化Handler,// 当NioServerSocketChannel在EventLoop注册成功时 , 该handler的init方法将被调用p.addLast(new ChannelInitializer() {@Overridepublic void initChannel(Channel ch) throws Exception {final ChannelPipeline pipeline = ch.pipeline();ChannelHandler handler = config.handler();//如果用户配置过Handlerif (handler != null) {pipeline.addLast(handler);}ch.eventLoop().execute(new Runnable() {@Overridepublic void run() {// 为NioServerSocketChannel的pipeline添加ServerBootstrapAcceptor处理器// 该Handler主要用来将新创建的NioSocketChannel注册到EventLoopGroup中pipeline.addLast(new ServerBootstrapAcceptor(currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));}});}});}我们发现init其实就做了三件事:
  • 设置options、attrs
  • 设置新接入Channel的options、attrs
  • 将用于服务端注册的 Handler ServerBootstrapAcceptor 添加到 ServerChannel的ChannelPipeline 中 。 ServerBootstrapAcceptor 为一个接入器 , 专门接受新请求 。
3.向EventLoopGroup中注册这个Channel
ChannelFuture regFuture = config().group().register(channel);通过追溯我们发现过程如下:
public ChannelFuture register(Channel channel) {return next().register(channel);}调用 next() 方法从 EventLoopGroup 中获取下一个 EventLoop , 调用 register() 方法注册:
public ChannelFuture register(Channel channel) {return register(new DefaultChannelPromise(channel, this));}将Channel和EventLoop封装成一个DefaultChannelPromise对象 , 然后调用register()方法 。 DefaultChannelPromis为ChannelPromise的默认实现 , 而ChannelPromisee继承Future , 具备异步执行结构 , 绑定Channel , 所以又具备了监听的能力 , 故而ChannelPromis是Netty异步执行的核心接口 。
public ChannelFuture register(ChannelPromise promise) {ObjectUtil.checkNotNull(promise, "promise");promise.channel().unsafe().register(this, promise);return promise;}unsafe就是我们之前构造NioServerSocketChannel时new的对象 , 这里调用register方法过程如下:
public final void register(EventLoop eventLoop, final ChannelPromise promise) {if (eventLoop == null) {throw new NullPointerException("eventLoop");}if (isRegistered()) {promise.setFailure(new IllegalStateException("registered to an event loop already"));return;}if (!isCompatible(eventLoop)) {promise.setFailure(new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName()));return;}AbstractChannel.this.eventLoop = eventLoop;// 必须要保证注册是由该EventLoop发起的if (eventLoop.inEventLoop()) {register0(promise);// 注册} else {// 如果不是单独封装成一个task异步执行try {eventLoop.execute(new Runnable() {@Overridepublic void run() {register0(promise);}});} catch (Throwable t) {logger.warn("Force-closing a channel whose registration task was not accepted by an event loop: {}",AbstractChannel.this, t);closeForcibly();closeFuture.setClosed();safeSetFailure(promise, t);}}} 首先通过isRegistered() 判断该 Channel 是否已经注册到 EventLoop 中;
通过 eventLoop.inEventLoop() 来判断当前线程是否为该 EventLoop 自身发起的 , 如果是 , 则调用 register0() 直接注册;
如果不是 , 说明该 EventLoop 中的线程此时没有执行权 , 则需要新建一个线程 , 单独封装一个 Task , 而该 Task 的主要任务则是执行register0() 。


稿源:(未知)

【傻大方】网址:http://www.shadafang.com/c/111J293N2020.html

标题:绝!真就一文全懂!Netty线程模型+启动详细分析+内存管理( 四 )


上一篇:干翻诺基亚的不是苹果,终结汽油车的也不会是特斯拉

下一篇:华为Mate40 Pro实拍样张:没有光学防抖真的很影响吗?