ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

dubbo发送过程编码失败,会唤醒发送线程吗?

2022-05-05 01:31:59  阅读:171  来源: 互联网

标签:dubbo chain NettyClientHandler 发送 线程 客户端


dubbo发送过程编码失败,会唤醒发送(客户端业务)线程吗?如何实现的?

在上篇文章 dubbo坑- No provider available for the service xxx 中,如果dubbo请求阶段,编码异常,而业务线程依然在等待响应,dubbo如何处理的?总不能等待超时,响应个超时异常吧,这不合理,接下来看dubbo编码异常,如何处理的

回顾下之前自己分析的dubbo transport层记录,详细记录了dubbo调用链路(包括netty channelhandler chain,dubbo channelhandler chain)的执行,在简单回顾下:

客户端发送:此时是在业务线程执行,客户端业务线程依次执行 InvokerInvocationHandler入口 -> RegistryDirectory获取服务集合 -> tagRouter过滤 -> 负载均衡选取一个Invoker -> dubbo consumer filter chain -> DubboInvoker执行调用invoke -> Exchange层封装请求模型Request且创建DefaultFuture并阻塞等待 -> 网络客户端NettyClient发送消息 -> dubbo Channel即NettyChannel发送 -> 调用netty channle发送 io.netty.channel.Channel.writeAndFlush(message),接着触发执行netty pipeline的outbound事件,执行顺序TailContext->NettyClientHandler->InternalEncoder->InternalDecoder->HeadContext,其中在TailContext内由业务线程切换到reactor IO线程,接着InternalEncoder进行编码,最终由HeadContext把数据发送给服务方;

客户端接收服务端响应:reactor IO线程监听到selector有read事件,执行processSelectedKeys(),触发执行netty pipeline的inbound事件,执行顺序【HeadContext->InternalDecoder->InternalEncoder->NettyClientHandler->TailContext】,由InternalDecoder解码,接着在NettyClientHandler#channelRead执行,NettyClientHandler持有dubbo channelhandler chain,因此链式执行dubbo channelhandler chain,即NettyClient->MultiMessageHandler->HeartbeatHandler->AllChannelHandler->DecodeHandler->HeaderExchangeHandler->DubboProtocol$1,这里重要的是在AllChannelHandler内由IO线程切换到业务线程(封装响应Response为ChannelEventRunnable,提交到dubbo业务线程池),接着在业务线程上HeaderExchangeHandler判断mesage是Response,处理响应,唤醒DefaultFuture的阻塞等待。

接着客户端业务线程被唤醒,根据Response内容处理,获取返回的数据结果/异常。

以上就是dubbo整个发送-响应的整个流程,重点是netty pipeline和dubbo channelhandler chain,都是责任链模式增加功能。

接着分析我们这个问题,从上面回顾的流程可知,未实现序列化,那么异常肯定发生在dubbo编码阶段,即InternalEncoder抛出异常,异常是java.lang.RuntimeException,异常信息Serialized class com.zzz.ioc.codec.util.KeyValuePair must implement java.io.Serializable Java field: private com.zzz.ioc.codec.util.KeyValuePair com.zzz.ioc.protocol.t808.T0900.message,异常封装在netty DefaultChannelPromise,因此在NettyClientHandler获取InternalEncoder.write结果(此过程在IO线程执行),判断是否有无异常,代码如下

image-20220327001350572

消息发送有异常,则mock response返回,接着执行NettyClientHandler持有的dubbo channelhandler chain[NettyClient->MultiMessageHandler->HeartbeatHandler->AllChannelHandler->DecodeHandler->HeaderExchangeHandler->DubboProtocol$1],AllChannelHandler执行,IO线程切换到业务线程(dubbo客户端线程池,线程名称DubboClientHandler-开头),接着业务线程上执行HeaderExchangeHandler,处理response,唤醒发送等待线程。此过程为了避免write操作失败,mock Request,然后和正常接收响应基本一样的处理方式(不同之处是不经过selector的processSelectedKeys())唤醒发送线程。通信框架出现这个问题也不容易,但是dubbo设计的非常巧妙。

小结:

回答前面提问

1.dubbo发送过程编码失败,会唤醒发送线程吗?

会唤醒发送线程,否则发送线程就是timeout异常,实际并没有。

如何实现的?

发送异常,比如编码异常,NettyClientHandler 进行mock response,接着和正常处理响应基本相同方式,触发NettyClientHandler 持有的dubbo channelhandler chain,由AllChannelHandler封装响应Response为ChannelEventRunnable,提交到dubbo业务线程池(cache线程池,线程名DubboClientHandler-开头),线程由IO线程切换到dubbo业务线程执行Exchange,即HeaderExchangeHandler处理response,继而唤醒发送线程,最后发送(客户端业务)线程处理响应业务逻辑。

标签:dubbo,chain,NettyClientHandler,发送,线程,客户端
来源: https://www.cnblogs.com/zhangyjblogs/p/16223151.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有