广告
返回顶部
首页 > 资讯 > 精选 >Netty分布式编码器及写数据事件处理使用场景的示例分析
  • 364
分享到

Netty分布式编码器及写数据事件处理使用场景的示例分析

2023-06-29 17:06:04 364人浏览 薄情痞子
摘要

这篇文章主要介绍Netty分布式编码器及写数据事件处理使用场景的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!编码器第一节: writeAndFlush的事件传播我们之前在学习pipeline的时候

这篇文章主要介绍Netty分布式编码器及写数据事件处理使用场景的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

编码器

第一节: writeAndFlush的事件传播

我们之前在学习pipeline的时候, 讲解了write事件的传播过程, 但在实际使用的时候, 我们通常不会调用channel的write方法, 因为该方法只会写入到发送数据的缓存中, 并不会直接写入channel中, 如果想写入到channel中, 还需要调用flush方法

实际使用过程中, 我们用的更多的是writeAndFlush方法, 这方法既能将数据写到发送缓存中, 也能刷新到channel中

我们看一个最简单的使用的场景
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {    ctx.channel().writeAndFlush("test data");}

学过netty的同学们对此肯定不陌生, 通过这种方式, 可以将数据发送到channel中, 对方可以收到响应

我们跟到writeAndFlush方法中

首先会走到AbstractChannel的writeAndFlush:

public ChannelFuture writeAndFlush(Object msg) {    return pipeline.writeAndFlush(msg);}

继续跟到DefualtChannelPipeline中的writeAndFlush方法中:

public final ChannelFuture writeAndFlush(Object msg) {    return tail.writeAndFlush(msg);}

这里我们看到, writeAndFlush是从tail节点进行传播, 有关事件传播, 我们再pipeline中进行过剖析, 相信这个不会陌生

继续跟, 会跟到AbstractChannelHandlerContext中的writeAndFlush方法:

public ChannelFuture writeAndFlush(Object msg) {    return writeAndFlush(msg, newPromise());}

继续跟:

public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) {    if (msg == null) {        throw new NullPointerException("msg");    }    if (!validatePromise(promise, true)) {        ReferenceCountUtil.release(msg);        // cancelled        return promise;    }     write(msg, true, promise);    return promise;}

继续跟write方法:

private void write(Object msg, boolean flush, ChannelPromise promise) {    //findContextOutbound()寻找前一个outbound节点    //最后到head节点结束    AbstractChannelHandlerContext next = findContextOutbound();    final Object m = pipeline.touch(msg, next);    EventExecutor executor = next.executor();    if (executor.inEventLoop()) {        if (flush) {            next.invokeWriteAndFlush(m, promise);        } else {            //没有调flush            next.invokeWrite(m, promise);        }    } else {        AbstractWriteTask task;        if (flush) {            task = WriteAndFlushTask.newInstance(next, m, promise);        }  else {            task = WriteTask.newInstance(next, m, promise);        }        safeExecute(executor, task, promise, m);    }}

这里的逻辑我们也不陌生, 找到下一个节点, 因为writeAndFlush是从tail节点开始的, 并且是outBound的事件, 所以这里会找到tail节点的上一个outBoundHandler, 有可能是编码器, 也有可能是我们业务处理的handler

 if (executor.inEventLoop()) 判断是否是eventLoop线程, 如果不是, 则封装成task通过NIOEventLoop异步执行, 我们这里先按照是eventLoop线程分析

首先, 这里通过flush判断是否调用了flush, 这里显然是true, 因为我们调用的方法是writeAndFlush

我们跟到invokeWriteAndFlush中
private void invokeWriteAndFlush(Object msg, ChannelPromise promise) {    if (invokeHandler()) {        //写入        invokeWrite0(msg, promise);        //刷新        invokeFlush0();    } else {        writeAndFlush(msg, promise);    }}

这里就真相大白了, 其实在writeAndFlush中, 首先调用write, write完成之后再调用flush方法进行的刷新

首先跟到invokeWrite0方法中:

private void invokeWrite0(Object msg, ChannelPromise promise) {    try {        //调用当前handler的wirte()方法        ((ChannelOutboundHandler) handler()).write(this, msg, promise);    } catch (Throwable t) {        notifyOutboundHandlerException(t, promise);    }}

该方法我们在pipeline中已经进行过分析, 就是调用当前handler的write方法, 如果当前handler中write方法是继续往下传播, 在会继续传播写事件, 直到传播到head节点, 最后会走到HeadContext的write方法中

跟到HeadContext的write方法中:

public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {    unsafe.write(msg, promise);}

这里通过当前channel的unsafe对象对将当前消息写到缓存中, 写入的过程, 我们之后的小节进行分析

回到到invokeWriteAndFlush方法中:

private void invokeWriteAndFlush(Object msg, ChannelPromise promise) {    if (invokeHandler()) {        //写入        invokeWrite0(msg, promise);        //刷新        invokeFlush0();    } else {        writeAndFlush(msg, promise);    }}
我们再看invokeFlush0方法
private void invokeFlush0() {    try {        ((ChannelOutboundHandler) handler()).flush(this);    } catch (Throwable t) {        notifyHandlerException(t);    }}

同样, 这里会调用当前handler的flush方法, 如果当前handler的flush方法是继续传播flush事件, 则flush事件会继续往下传播, 直到最后会调用head节点的flush方法, 如果我们熟悉pipeline的话, 对这里的逻辑不会陌生

跟到HeadContext的flush方法中:

public void flush(ChannelHandlerContext ctx) throws Exception {    unsafe.flush();}

这里同样, 会通过当前channel的unsafe对象通过调用flush方法将缓存的数据刷新到channel中, 有关刷新的逻辑, 我们会在以后的小节进行剖析

以上是“Netty分布式编码器及写数据事件处理使用场景的示例分析”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注编程网精选频道!

--结束END--

本文标题: Netty分布式编码器及写数据事件处理使用场景的示例分析

本文链接: https://www.lsjlt.com/news/325913.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作