Netty服务端的业务流程分析
Netty的服务端怎么和java NIO联系起来的,一直很好奇这块内容,这里跟下代码,下篇文章看下Channel相关的知识。
finalChannelFuture initAndRegister(){finalChannel channel = channelFactory().newChannel();//try{init(channel);}catch(Throwable t){channel.unsafe().closeForcibly();//立即关闭通道且不会触发事件//因为这个通道还没有注册到EventLoop,所以我们需要强制GlobalEventExecutor的使用。returnnewDefaultChannelPromise(channel,GlobalEventExecutor.INSTANCE).setFailure(t);}//注册一个EventLoopChannelFuture regFuture = group().register(channel);//注册失败if(regFuture.cause()!=null){if(channel.isRegistered()){channel.close();}else{channel.unsafe().closeForcibly();}}// If we are here and the promise is not failed, it's one of the following cases:// 程序运行到这里且promise没有失败,可能有如下几种情况// 1) If we attempted registration from the event loop, the registration has been completed at this point.// 如果试图注册到一个EventLoop,该注册完成,// i.e. It's safe to attempt bind() or connect() now because the channel has been registered.// 2) If we attempted registration from the other thread, the registration request has been successfully// added to the event loop's task queue for later execution.// 如果试图注册到其他线程,该注册已经成功,但是没有完成,添加一个事件到任务队列中,等会执行// i.e. It's safe to attempt bind() or connect() now:// because bind() or connect() will be executed *after* the scheduled registration task is executed// because register(), bind(), and connect() are all bound to the same thread.return regFuture;}
@OverridepublicChannelFutureregister(Channel channel){return next().register(channel);}
@OverridepublicChannelFutureregister(finalChannel channel,finalChannelPromise promise){if(channel ==null){thrownewNullPointerException("channel");}if(promise ==null){thrownewNullPointerException("promise");}channel.unsafe().register(this, promise);return promise;}
@Overridepublicfinalvoidregister(EventLoop eventLoop,finalChannelPromise promise){if(eventLoop ==null){thrownewNullPointerException("eventLoop");}if(isRegistered()){promise.setFailure(newIllegalStateException("registered to an event loop already"));return;}if(!isCompatible(eventLoop)){promise.setFailure(newIllegalStateException("incompatible event loop type: "+ eventLoop.getClass().getName()));return;}AbstractChannel.this.eventLoop = eventLoop;if(eventLoop.inEventLoop()){register0(promise);}else{try{eventLoop.execute(newOneTimeTask(){@Overridepublicvoid 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);}}}
@Overrideprotectedvoid doRegister()throwsException{boolean selected =false;for(;;){try{selectionKey = javaChannel().register(eventLoop().selector,0,this);return;}catch(CancelledKeyException e){if(!selected){// Force the Selector to select now as the "canceled" SelectionKey may still be// cached and not removed because no Select.select(..) operation was called yet.eventLoop().selectNow();selected =true;}else{// We forced a select operation on the selector before but the SelectionKey is still cached// for whatever reason. JDK bug ?throw e;}}}}
wakeup 方法所得的结果privatestaticvoid doBind0(finalChannelFuture regFuture,finalChannel channel,finalSocketAddress localAddress,finalChannelPromise promise){// This method is invoked before channelRegistered() is triggered. Give user handlers a chance to set up// the pipeline in its channelRegistered() implementation.channel.eventLoop().execute(newRunnable(){@Overridepublicvoid run(){if(regFuture.isSuccess()){channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);}else{promise.setFailure(regFuture.cause());}}});}
@Overrideprotectedvoid run(){for(;;){boolean oldWakenUp = wakenUp.getAndSet(false);try{if(hasTasks()){selectNow();}else{select(oldWakenUp);// 'wakenUp.compareAndSet(false, true)' is always evaluated// before calling 'selector.wakeup()' to reduce the wake-up// overhead. (Selector.wakeup() is an expensive operation.)//// However, there is a race condition in this approach.// The race condition is triggered when 'wakenUp' is set to// true too early.//// 'wakenUp' is set to true too early if:// 1) Selector is waken up between 'wakenUp.set(false)' and// 'selector.select(...)'. (BAD)// 2) Selector is waken up between 'selector.select(...)' and// 'if (wakenUp.get()) { ... }'. (OK)//// In the first case, 'wakenUp' is set to true and the// following 'selector.select(...)' will wake up immediately.// Until 'wakenUp' is set to false again in the next round,// 'wakenUp.compareAndSet(false, true)' will fail, and therefore// any attempt to wake up the Selector will fail, too, causing// the following 'selector.select(...)' call to block// unnecessarily.//// To fix this problem, we wake up the selector again if wakenUp// is true immediately after selector.select(...).// It is inefficient in that it wakes up the selector for both// the first case (BAD - wake-up required) and the second case// (OK - no wake-up required).if(wakenUp.get()){selector.wakeup();}}cancelledKeys =0;needsToSelectAgain =false;finalint ioRatio =this.ioRatio;if(ioRatio ==100){processSelectedKeys();runAllTasks();}else{finallong ioStartTime =System.nanoTime();processSelectedKeys();finallong ioTime =System.nanoTime()- ioStartTime;runAllTasks(ioTime *(100- ioRatio)/ ioRatio);}if(isShuttingDown()){closeAll();if(confirmShutdown()){break;}}}catch(Throwable t){logger.warn("Unexpected exception in the selector loop.", t);// Prevent possible consecutive immediate failures that lead to// excessive CPU consumption.try{Thread.sleep(1000);}catch(InterruptedException e){// Ignore.}}}}
Netty服务端的业务流程分析的更多相关文章
- Netty服务端的启动源码分析
ServerBootstrap的构造: public class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, Serve ...
- Netty之旅三:Netty服务端启动源码分析,一梭子带走!
Netty服务端启动流程源码分析 前记 哈喽,自从上篇<Netty之旅二:口口相传的高性能Netty到底是什么?>后,迟迟两周才开启今天的Netty源码系列.源码分析的第一篇文章,下一篇我 ...
- 【Netty源码分析】Netty服务端bind端口过程
这一篇博客我们介绍一下Netty服务端绑定端口的过程,我们通过跟踪代码一直到NIO原生绑定端口的操作. 绑定端口操作 ChannelFuture future = serverBootstrap.bi ...
- Netty 服务端启动过程
在 Netty 中创建 1 个 NioServerSocketChannel 在指定的端口监听客户端连接,这个过程主要有以下 个步骤: 创建 NioServerSocketChannel 初始化并注 ...
- Netty 服务端创建
参考:http://blog.csdn.net/suifeng3051/article/details/28861883?utm_source=tuicool&utm_medium=refer ...
- netty服务端启动--ServerBootstrap源码解析
netty服务端启动--ServerBootstrap源码解析 前面的第一篇文章中,我以spark中的netty客户端的创建为切入点,分析了netty的客户端引导类Bootstrap的参数设置以及启动 ...
- Netty服务端NioEventLoop启动及新连接接入处理
一 Netty服务端NioEventLoop的启动 Netty服务端创建.初始化完成后,再向Selector上注册时,会将服务端Channel与NioEventLoop绑定,绑定之后,一方面会将服务端 ...
- Netty服务端Channel的创建与初始化
Netty创建服务端Channel时,从服务端 ServerBootstrap 类的 bind 方法进入,下图是创建服务端Channel的函数调用链.在后续代码中通过反射的方式创建服务端Channel ...
- netty服务端客户端启动流程分析
服务端启动流程 我们回顾前面讲解的netty启动流程,服务端这边有两个EventLoopGroup,一个专门用来处理连接,一个用来处理后续的io事件 服务端启动还是跟nio一样,绑定端口进行监听,我们 ...
随机推荐
- input 标签中的checkd 添加与取消
//获取是否选中 var isChecked = $('#cb').prop('checked'); //或 var isChecked = $('#cb').is(":checked&qu ...
- [转载] 最简单的基于FFmpeg的AVDevice例子(读取摄像头)
=====================================================最简单的基于FFmpeg的AVDevice例子文章列表: 最简单的基于FFmpeg的AVDev ...
- .net remoting和wcf自托管——一个bug引发的警示
一.解决问题,需要深入,并从细节入手,多从代码找原因,不能认为代码是死的,不会出错: 之前代码都运行良好,突然某一天,在我电脑上出问题了.出了问题,那就应该找出原因.其实这个问题,本身并不难,好歹给你 ...
- htaccess不起作用的解决方法,AllowOverride All打开后出现403错误时解决办法
在php程序的目录下有一个htaccess文件,这个文件起着对url重写的作用,但是不巧的,在我的应用程序里不起作用,baidu了一下,发现是 AllowOverride All, 这个选项没有打开 ...
- pair对组
一.pair基本概念 对组(pair)将一对值组合成一个值,这一对值可以具有不同的数据类型,两个值可以分别用pair的两个公有函数first和second访问. 类模板:template <cl ...
- 使用.NET中的XML注释(二) -- 创建帮助文档入门篇
一.摘要 在本系列的第一篇文章介绍了.NET中XML注释的用途, 本篇文章将讲解如何使用XML注释生成与MSDN一样的帮助文件.主要介绍NDoc的继承者:SandCastle. 二.背景 要生成帮助文 ...
- Python函数-all()
all(iterable) 作用: 如果iterable的所有元素不为0.''.False或者iterable为空,all(iterable)返回True,否则返回False:函数等价于: def a ...
- (C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令
(本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一节:(C#)Windows Shell 外壳编程系列3 - 上下文菜单(iContextMenu)(一)右键菜单 上一节说到如 ...
- Azure VM的加速网络
Azure的VM在经过几代发展后已经有多种硬件类型.目前Azure China的多种机型都配置了FPGA卡,可以实现网络加速.本文将介绍Azure的加速网络相关的内容. 一. 加速网络的硬件准备 下图 ...
- PCIE编程1:lspci操作
lspci 是一个用来显示系统中所有PCI总线设备或连接到该总线上的所有设备的工具. 列出所有的PCIE设备: lspci 选项: -v 使得 lspci 以冗余模式显示所有设备的详细信息. -vv ...