博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Netty的Nio写优化
阅读量:4214 次
发布时间:2019-05-26

本文共 4270 字,大约阅读时间需要 14 分钟。

  今天又看了一遍boyan的《Nip trick and trip》,又有一些新的收获。比以前看地更深刻了。其中有一处写到Nio的写优化,当Nio的channel设置为nonblocking时,写操作不再阻塞,而是直接返回0,表示当时socket的写缓冲区已满不可写。通常的处理办法是返回本次loop并继续注册op_read或者op_write。这样会带来线程切换的开销,使当前select阻塞,直到有可写发生再次唤醒。Netty是怎么解决的?以前虽然看过Netty的代码但并没有深入到细节中去,看了boyanNetty采用writeSpinCount的介绍才深有感悟。好多知识都在细节里,就看我们对这个领域掌握地深不深,如果蜻蜓点水肯定发现了这些看似简单的代码的玄妙之处。话归正题,writeSpinCount如何解决这个问题的呢?类似自旋锁,还是看看Netty的代码吧,比较形象。

for (;;) {                MessageEvent evt = channel.currentWriteEvent;                SendBuffer buf;                if (evt == null) {                    if ((channel.currentWriteEvent = evt = writeBuffer.poll()) == null) {                       //写事件队列为空,此时应该去除op_write                        removeOpWrite = true;                        channel.writeSuspended = false;                        break;                    }                    channel.currentWriteBuffer = buf = sendBufferPool.acquire(evt.getMessage());                } else {                    buf = channel.currentWriteBuffer;                }                ChannelFuture future = evt.getFuture();                try {                    long localWrittenBytes = 0;                    for (int i = writeSpinCount; i > 0; i --) {//此处为writeSpinCount的解决方式                       //向channel写数据,为了使其fileChannel的transferTo接口一致。这样从file写向socket时避免四次copy,sendfile的功能                        localWrittenBytes = buf.transferTo(ch);                        //写入的数据大于0,跳出本次循环,如为零则循环writeSpinCount,如再次期间localWrittenBytes>0,说明再次可写。                        if (localWrittenBytes != 0) {                            writtenBytes += localWrittenBytes;                            break;                        }                        if (buf.finished()) {                            break;                        }                    }                    if (buf.finished()) {                        // Successful write - proceed to the next message.                        //完整地写完,则继续处理下一个消息                        buf.release();                        channel.currentWriteEvent = null;                        channel.currentWriteBuffer = null;                        evt = null;                        buf = null;                        future.setSuccess();                    } else {                        // Not written fully - perhaps the kernel buffer is full.                        //没能完整地写完当前的message,则继续设置op_write,并跳出外层循环                        addOpWrite = true;                        channel.writeSuspended = true;                        if (localWrittenBytes > 0) {                            // Notify progress listeners if necessary.                            future.setProgress(                                    localWrittenBytes,                                    buf.writtenBytes(), buf.totalBytes());                        }                        break;                    }                } catch (AsynchronousCloseException e) {                    // Doesn't need a user attention - ignore.                } catch (Throwable t) {                    if (buf != null) {                        buf.release();                    }                    channel.currentWriteEvent = null;                    channel.currentWriteBuffer = null;                    buf = null;                    evt = null;                    future.setFailure(t);                    if (iothread) {                        fireExceptionCaught(channel, t);                    } else {                        fireExceptionCaughtLater(channel, t);                    }                    if (t instanceof IOException) {                        open = false;                        close(channel, succeededFuture(channel));                    }                }            }            channel.inWriteNowLoop = false;            // Initially, the following block was executed after releasing            // the writeLock, but there was a race condition, and it has to be            // executed before releasing the writeLock:            //            //     https://issues.jboss.org/browse/NETTY-410            //            if (open) {                if (addOpWrite) {                    setOpWrite(channel);                } else if (removeOpWrite) {                    clearOpWrite(channel);                }            }        }

 

转载地址:http://vqdmi.baihongyu.com/

你可能感兴趣的文章
hdoj 1595 最短路中的最长路(good)
查看>>
C++优先队列使用
查看>>
hdoj 1026
查看>>
csp 2017_3_3 markdown
查看>>
CSP 2017_9_4 通信网络
查看>>
hdoj 1026 搜索
查看>>
递归 理解
查看>>
欧几里德求最大公约数/最小公倍数
查看>>
hdoj 1016 素数环
查看>>
POJ 3617 字典序最小
查看>>
筛法求素数
查看>>
atoi/atof 字符串转Int/float
查看>>
数字字符串与int相互转化
查看>>
PAT 天梯赛 L1-025 A+B
查看>>
hdoj 1597 二分 下界(等差数列)
查看>>
二分查找
查看>>
hdoj 1180 搜索 + bfs + 优先队列
查看>>
hdoj 2141 二分 + 优化
查看>>
PAT 天梯赛 L1-027. 出租 (简单字符串处理)
查看>>
hdoj 1863 最小生成树(kruskal + 并查集)
查看>>