dubbo异步同步调用混合使用问题

本文分析了一种在使用Dubbo时遇到的问题:预期在ServiceA中同步调用ServiceB和ServiceC并拼接结果,但实际上只获得了ServiceC的返回。原因在于RpcInvocation中的async属性被错误地设置为了true,导致ServiceB调用变为异步,从而在后续步骤中获取到的结果为null。解决方案是对async属性进行正确赋值。

个人笔记。

先看下面的case

我们假设

Assume1: ServiceB返回字符串”ServiceB”,

Assume2: ServiceC返回字符串”ServiceC”,

ServiceA 拼接字符串”ServiceA”,加上assume1 和 assume2 的返回结果

预期:client获得“ServiceA ServiceB ServiceC”

实际:client获得“ServiceA ServiceC”

没有获得ServiceB的返回结果, 从log看的话,在ServiceA里面获取的step3的结果也的确是null。

分析:

Client 和 server进行交互的方式,默认是netty,通过NettyHandler进行操作,有消息的收发处理方法。

进行debug,

client到ServiceA之后,在RpcInvocation里有一个async=true,同时RpcContext.getContext().getAttachments()也包含这个属性。

然后进行step2,进行一系列filter,最后到AbstractInvoker, #134开始,

Map<String, String> context = RpcContext.getContext().getAttachments();
        if (context != null) {
        	invocation.addAttachmentsIfAbsent(context);
        }

//这里吧当前context里面的attachments付给了调用ServiceBRpcInvocation,所以这时变成async=true

if (getUrl().getMethodParameter(invocation.getMethodName(), Constants.ASYNC_KEY, false)){
    invocation.setAttachment(Constants.ASYNC_KEY, Boolean.TRUE.toString());
}

//这里判断后,由于调用ServiceB的url里面是没有async的属性的,所以返回false

继续向后,进入到DubboProtocol的reply,可以获取到DubboInvoker, DubboInvoker.doInvoke方法,先判断一下是否为异步

boolean isAsync = RpcUtils.isAsync(getUrl(), invocation);

由于上面的方法导致此时为true(本来的同步调用变成了异步调用)

else if (isAsync) {
            	ResponseFuture future = currentClient.request(inv, timeout) ;
                RpcContext.getContext().setFuture(new FutureAdapter<Object>(future));
                return new RpcResult();
            }

进入这个逻辑后,设置了future,然后返回了空的RpcResult,data和exception都为null。

所以在step3获得的结果为null。

执行完后,继续,有一些清理操作,在ConsumerContextFilter里面会清掉attachements

然后在step4,就是正常的同步调用,可以获取结果。

修改:

简单的进行了一下修改,AbstractInvoker的#137处,每次都对async进行实际赋值

boolean isAsync = getUrl().getMethodParameter(invocation.getMethodName(), Constants.ASYNC_KEY, false);
invocation.setAttachment(Constants.ASYNC_KEY, String.valueOf(isAsync));

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值