Dubbo中重要的概念Invoker、Invocation、Protocol和URL。Dubbo异步调用中的Bug及处理方式...

dubbo的调用过程如下图所示

303808-711b94c03cfc202b.png
dubbo的调用过程

1:URL
定义了调用的url如协议、协议、参数等信息。还有在拓展加载中选择对应的拓展类如下代码片段所示(isActive(activate, url))

public List<T> getActivateExtension(URL url, String[] values, String group) {
    List<T> exts = new ArrayList<T>();
    List<String> names = values == null ? new ArrayList<String>(0) : Arrays.asList(values);
    if (! names.contains(Constants.REMOVE_VALUE_PREFIX + Constants.DEFAULT_KEY)) {
        getExtensionClasses();
        for (Map.Entry<String, Activate> entry : cachedActivates.entrySet()) {
            String name = entry.getKey();
            Activate activate = entry.getValue();
            if (isMatchGroup(group, activate.group())) {
                T ext = getExtension(name);
                if (! names.contains(name)
                        && ! names.contains(Constants.REMOVE_VALUE_PREFIX + name) 
                        && isActive(activate, url)) {
                    exts.add(ext);
                }
            }
        }

dubbo已知的调用传递bug(dubbo.2.5.3)

服务A异步调用服务B再同步调用服务C这种情况下服务A将获取不到结果。原因是在传递async参数的过程中将B同步调用C修改为异步调用。

303808-bac6b4cc1da020ec.png
dubbo已知的调用传递bug(版本2.5.3)

传递bug导致具体代码位置


303808-87a525a994874d18.png
传递bug导致具体代码位置

如何解决传递问题
添加Filter在调用前把async属性重置为默认值。如下所示

@Activate(value = {Constants.CONSUMER,Constants.PROVIDER} ,order = -1000000)
public class RmAsync implements Filter {

    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        invocation.getAttachments().put("async", "false");
        return invoker.invoke(invocation);
    }
}

URl中实际开发中应用

服务跟踪同一笔请求从源头服务开始把日志ID传递到服务方,根据日志id跟踪调用流程具体实现如下

public class ConsumerTrackingFilter implements Filter {
    private Logger logger = LoggerFactory.getLogger(ConsumerTrackingFilter.class);

    public ConsumerTrackingFilter() {
    }

    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        try {
            String unique = LogUniqueKeyUtil.getKeyFromLog();
            if (StringUtils.isEmpty(unique)) {
                LogUniqueKeyUtil.generateKeyToLog();
            }

            RpcContext.getContext().setAttachment(LogUniqueKeyUtil.LOG_KEY, unique);
        } catch (Throwable var4) {
            this.logger.warn("ConsumerTrackingFilter error", var4);
        }

        Result result = invoker.invoke(invocation);
        return result;
    }
}

2:Invoker

是实体域,它是 Dubbo 的核心模型,其它模型都向它靠扰,或转换成它,它代表一个可执行体,可向它发起 invoke 调用,它有可能是一个本地的实现,也可能是一个远程的实现,也可能一个集群实现。
服务提供者暴露一个服务的详细过程


303808-e2266f6c3a8043ab.png
服务提供者暴露一个服务的详细过程

服务消费者消费一个服务的详细过程


303808-087f65e7f2bd0b3b.png
服务消费者消费一个服务的详细过程

3:Invocation
是会话域,它持有调用过程中的变量,比如方法名,参数等。
4:Protocol
是服务域,它是 Invoker 暴露和引用的主功能入口,它负责 Invoker 的生命周期管理。

猜你喜欢

转载自blog.csdn.net/weixin_33858485/article/details/87604487