关于 Netty Channel 的 Autoread
Netty 4 的 Channel 多了一个 autoread 参数, 它的用处是在让 channel 在触发某些事件以后(例如 channelActive, channelReadComplete)以后还会自动调用一次 read(), 代码:
DefaultChannelPipeline.java
- @Override
- public ChannelPipeline fireChannelActive() {
- head.fireChannelActive();
- if (channel.config().isAutoRead()) {
- channel.read();
- }
- return this;
- }
- -----------------------------------
- @Override
- public ChannelPipeline fireChannelReadComplete() {
- head.fireChannelReadComplete();
- if (channel.config().isAutoRead()) {
- read();
- }
- return this;
- }
另外一个很重要的作用是在触发某些事件(例如 socket 关闭)时, 在 NioEventloop 的 OP_READ 位为 1 时, 是否真正的去 channel 读取数据, 去 channel 读取数据的意义还包括可以更新 channel 的状态, 例如改变 active 状态等, 代码:
Eventloop.java
- private static void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
- final NioUnsafe unsafe = ch.unsafe();
- if (!k.isValid()) {
- // close the channel if the key is not valid anymore
- unsafe.close(unsafe.voidPromise());
- return;
- }
- try {
- int readyOps = k.readyOps();
- // Also check for readOps of 0 to workaround possible JDK bug which may otherwise lead
- // to a spin loop
- if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
- unsafe.read();
- if (!ch.isOpen()) {
- // Connection already closed - no need to handle write.
- return;
- }
- }
- if ((readyOps & SelectionKey.OP_WRITE) != 0) {
- // Call forceFlush which will also take care of clear the OP_WRITE once there is nothing left to write
- ch.unsafe().forceFlush();
- }
- if ((readyOps & SelectionKey.OP_CONNECT) != 0) {
- // remove OP_CONNECT as otherwise Selector.select(..) will always return without blocking
- // See https://github.com/netty/netty/issues/924
- int ops = k.interestOps();
- ops &= ~SelectionKey.OP_CONNECT;
- k.interestOps(ops);
- unsafe.finishConnect();
- }
- } catch (CancelledKeyException e) {
- unsafe.close(unsafe.voidPromise());
- }
- }
AbstractNioByteChannel.java (unsafe.read())
- public void read() {
- final ChannelConfig config = config();
// 判断是否是 autoread, 如果不是直接移除 opRead 标志位返回- if (!config.isAutoRead() && !isReadPending()) {
- // ChannelConfig.setAutoRead(false) was called in the meantime
- removeReadOp();
- return;
- }
- final ChannelPipeline pipeline = pipeline();
- final ByteBufAllocator allocator = config.getAllocator();
- final int maxMessagesPerRead = config.getMaxMessagesPerRead();
- RecvByteBufAllocator.Handle allocHandle = this.allocHandle;
- if (allocHandle == null) {
- this.allocHandle = allocHandle = config.getRecvByteBufAllocator().newHandle();
- }
- ByteBuf byteBuf = null;
- int messages = 0;
- boolean close = false;
- try {
- int totalReadAmount = 0;
- boolean readPendingReset = false;
- do {
- byteBuf = allocHandle.allocate(allocator);
- int writable = byteBuf.writableBytes();
// 这里会到 channel 中 read 一次, 如果返回 -1, 则表示 channel 关闭
// 假如说 autoread 为 false, 则在 socket close 时永远不会进入这里, 从而改变 channel 的 active 状态- int localReadAmount = doReadBytes(byteBuf);
- if (localReadAmount <= 0) {
- // not was read release the buffer
- byteBuf.release();
- close = localReadAmount < 0;
- break;
- }
- if (!readPendingReset) {
- readPendingReset = true;
- setReadPending(false);
- }
- pipeline.fireChannelRead(byteBuf);
- byteBuf = null;
- if (totalReadAmount >= Integer.MAX_VALUE - localReadAmount) {
- // Avoid overflow.
- totalReadAmount = Integer.MAX_VALUE;
- break;
- }
- totalReadAmount += localReadAmount;
- // stop reading
- if (!config.isAutoRead()) {
- break;
- }
- if (localReadAmount < writable) {
- // Read less than what the buffer can hold,
- // which might mean we drained the recv buffer completely.
- break;
- }
- } while (++ messages < maxMessagesPerRead);
- pipeline.fireChannelReadComplete();
- allocHandle.record(totalReadAmount);
- // 关闭 channel, 并改变 channel active 状态
- if (close) {
- closeOnRead(pipeline);
- close = false;
- }
- } catch (Throwable t) {
- handleReadException(pipeline, byteBuf, t, close);
- } finally {
- // Check if there is a readPending which was not processed yet.
- // This could be for two reasons:
- // * The user called Channel.read() or ChannelHandlerContext.read() in channelRead(...) method
- // * The user called Channel.read() or ChannelHandlerContext.read() in channelReadComplete(...) method
- //
- // See https://github.com/netty/netty/issues/2254
- if (!config.isAutoRead() && !isReadPending()) {
- removeReadOp();
- }
- }
- }
- }
关于 Netty Channel 的 Autoread的更多相关文章
- SparkStreaming+Flume出现ERROR ReceiverTracker: Deregistered receiver for stream 0: Error starting receiver 0 - org.jboss.netty.channel.ChannelException
文章发自http://www.cnblogs.com/hark0623/p/4204104.html ,转载请注明 我发现太多太多的坑要趟了… 向yarn提交sparkstreaming了,提交脚本如 ...
- android netty5.0 编译时 java.lang.NoClassDefFoundError: io.netty.channel.nio.NioEventLoopGroup
android netty5.0 编译时 java.lang.NoClassDefFoundError: io.netty.channel.nio.NioEventLoopGroup 复制netty包 ...
- netty-websocket-spring-boot-starter关闭报错 io/netty/channel/AbstractChannel$AbstractUnsafe io/netty/util/concurrent/GlobalEventExecutor
报错 java.lang.NoClassDefFoundError: io/netty/channel/AbstractChannel$AbstractUnsafe$ at io.netty.chan ...
- Netty Channel 接口名词理解
1.Channel channel 是负责数据读,写的对象,有点类似于老的io里面的stream.它和stream的区别,channel是双向的,既可以write 也可以read,而stream要分o ...
- netty源码解解析(4.0)-3 Channel的抽象实现
AbstractChannel和AbstractUnsafe抽象类 io.netty.channel.AbstractChannel 从本章开始,会有大量的篇幅涉及到代码分析.为了能够清晰简洁的地说明 ...
- Netty那点事: 概述, Netty中的buffer, Channel与Pipeline
Netty那点事(一)概述 Netty和Mina是Java世界非常知名的通讯框架.它们都出自同一个作者,Mina诞生略早,属于Apache基金会,而Netty开始在Jboss名下,后来出来自立门户ne ...
- [编织消息框架][netty源码分析]8 Channel 实现类NioSocketChannel职责与实现
Unsafe是托委访问socket,那么Channel是直接提供给开发者使用的 Channel 主要有两个实现 NioServerSocketChannel同NioSocketChannel 致于其它 ...
- netty源码解解析(4.0)-14 Channel NIO实现:读取数据
本章分析Nio Channel的数据读取功能的实现. Channel读取数据需要Channel和ChannelHandler配合使用,netty设计数据读取功能包括三个要素:Channel, Eve ...
- netty源码解解析(4.0)-15 Channel NIO实现:写数据
写数据是NIO Channel实现的另一个比较复杂的功能.每一个channel都有一个outboundBuffer,这是一个输出缓冲区.当调用channel的write方法写数据时,这个数据被一系列C ...
随机推荐
- cut命令
cut是一个选取命令,就是将一段数据经过分析,取出我们想要的.一般来说,选取信息通常是针对"行"来进行分析的,并不是整篇信息分析的. (1)其语法格式为:cut [-bn] [f ...
- 拒绝访问 temp 目录。用来运行 XmlSerializer 的标识“IIS APPPOOL\UGAS”没有访问 temp 目录的足够权限
在部署IIS时候会出现下图错误,拒绝访问 temp 目录.用来运行 XmlSerializer 的标识“IIS APPPOOL\UGAS”没有访问 temp 目录的足够权限 解决方法: 在IIS信息管 ...
- 百度云 + GIT
百度云同步 百度云同步,会将本地的某个文件目录和云端进行同步.如果在本地将这个同步的目录设置为Git的中心服务器,那么本地push到中心服务器的内容也会被同步到云端.其他开发者只要也进行相同的设置,就 ...
- Maximo-获取url
//访问报表public void OPENREPORT() throws RemoteException, MXException{ int polineid=this.getMbo().getIn ...
- vs2012安装Microsoft.AspNet.WebApi.WebHost
工具---库程序包管理器---程序包管理器控制台:输入下面命令: Install-Package Microsoft.AspNet.WebApi.WebHost
- <读书笔记> 代码整洁之道
概述 1.本文档的内容主要来源于书籍<代码整洁之道>作者Robert C.Martin,属于读书笔记. 2.软件质量,不仅依赖于架构和项目管理,而且与代码质量紧密相关,本书提出一 ...
- C语言编程技巧-signal(信号)[转]
自 http://www.uml.org.cn/c++/200812083.asp 信号是Linux编程中非常重要的部分,本文将详细介绍信号机制的基本概念.Linux对信号机制的大致实现方法.如何使用 ...
- thinkphp修改及编写标签库,编辑器的使用
在view目录下创建Index_aaa.html <!DOCTYPE html> <html> <head> <meta charset="UTF- ...
- MSSQL 查询数据库所有表的大小, 有助于删除一些没用的表
SELECT b.name AS tablename , a.rowcnt AS datacount FROM sysindexes a , sysobjects b WHERE a.id = b.i ...
- MongoDB是一个介于关系数据库和非关系数据库之间的产品
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.他支持的数据结构非常松散,是类似json的bjson格式,因此可以存储比较复杂的数据类型.M ...