图文并茂分析Skywalking dubbo上下午传递源码

这里是weihubeats,觉得文章不错可以关注公众号小奏技术

背景

最近在研究dubbotrace上下文传递,所以免不了要看看skywalking这一快的实现原理

skywalking version

  • 8.12.0

插件版本

  • dubbo-3.x-plugin

dubbo-3.x-plugin源码目录结构

源码整体流程

源码分析

可以看到主要有三个核心类 + 一个配置文件

DubboInstrumentation

这个类主要定义了什么时候触发增强,增强哪个类的哪个方法

增强哪个类
public static final String ENHANCE_CLASS = "org.apache.dubbo.monitor.support.MonitorFilter";

@Override
protected ClassMatch enhanceClass() {
    return NameMatch.byName(ENHANCE_CLASS);
}

可以看到主要是增强MonitorFilter这个类

什么情况触发增强
public static final String CONTEXT_TYPE_NAME = "org.apache.dubbo.rpc.RpcContext";

public static final String GET_SERVER_CONTEXT_METHOD_NAME = "getServerContext";

public static final String CONTEXT_ATTACHMENT_TYPE_NAME = "org.apache.dubbo.rpc.RpcContextAttachment";

@Override
protected List<WitnessMethod> witnessMethods() {
    return Collections.singletonList(
        new WitnessMethod(
            CONTEXT_TYPE_NAME,
            named(GET_SERVER_CONTEXT_METHOD_NAME).and(
                returns(named(CONTEXT_ATTACHMENT_TYPE_NAME)))
        ));
}

这里主要定义了在org.apache.dubbo.rpc.RpcContext中必须存在方法getServerContext
并且他的返回值为org.apache.dubbo.rpc.RpcContextAttachment

我们简单对比下2.7.xdubbo的增强条件是什么


    private static final String CONTEXT_TYPE_NAME = "org.apache.dubbo.rpc.RpcContext";

    private static final String GET_SERVER_CONTEXT_METHOD_NAME = "getServerContext";

    @Override
    protected List<WitnessMethod> witnessMethods() {
        return Collections.singletonList(new WitnessMethod(
            CONTEXT_TYPE_NAME,
            named(GET_SERVER_CONTEXT_METHOD_NAME).and(
                returns(named(CONTEXT_TYPE_NAME)))
        ));
    }

主要是org.apache.dubbo.rpc.RpcContext类中的getServerContext方法,返回值也是org.apache.dubbo.rpc.RpcContext

那么很明确了2.73.xgetServerContext的返回值被修改了。

增强的方法

在前面我知道增强的类是MonitorFilter

现在我们具体来看看增强哪个方法

@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
    return new InstanceMethodsInterceptPoint[] {
        new InstanceMethodsInterceptPoint() {
            @Override
            public ElementMatcher<MethodDescription> getMethodsMatcher() {
                return named(INTERCEPT_POINT_METHOD);
            }

            @Override
            public String getMethodsInterceptor() {
                return INTERCEPT_CLASS;
            }

            @Override
            public boolean isOverrideArgs() {
                return false;
            }
        }
    };
}

要增强的方法是

public static final String INTERCEPT_POINT_METHOD = "invoke";

实现增强的类是

public static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.asf.dubbo3.DubboInterceptor";

所以接下来我们来看看实际实现增强的逻辑吧

DubboInterceptor

源码有点多。我们来一一分析

  1. 校验是不是Consumer
boolean isConsumer = isConsumer(invocation);

private static boolean isConsumer(Invocation invocation) {
    Invoker<?> invoker = invocation.getInvoker();
    // As RpcServiceContext may not been reset when it's role switched from provider
    // to consumer in the same thread, but RpcInvocation is always correctly bounded
    // to the current request or serve request, https://github.com/apache/skywalking-java/pull/110
    return invoker.getUrl()
            .getParameter("side", "provider")
            .equals("consumer");
}

校验方式就通过urlParam获取side参数,默认为provider

  1. 获取RPC上下文RpcContextAttachment

  2. 如果是Consumer则创建ExitSpan,如果是Provider则创建EntrySpan

  3. 如果是Consumer则将skywalking上下文载体ContextCarrier放入dubborpc上下文RpcContextAttachment中,以便上下午在dubbo进行传递

CarrierItem next = contextCarrier.items();
while (next.hasNext()) {
    next = next.next();
    attachment.setAttachment(next.getHeadKey(), next.getHeadValue());
    if (invocation.getAttachments().containsKey(next.getHeadKey())) {
        invocation.getAttachments().remove(next.getHeadKey());
    }
}
  1. 如果是Provider则从dubbo上下文RpcContextAttachment中获取Consumer的上下文恢复到skywalking上下文ContextCarrier

总结

总的来说dubbo这一快的上下文传递还是很简单的。总结为如下几个步骤

  1. 是否需要增强
  2. 如果是则判断是Provider还是Consumer
  3. 如果是Consumer则将上下文放入skywalking上下文ContextCarrier
  4. 如果是如果是Provider则从dubbo上下文RpcContextAttachment中获取Consumer的上下文恢复到skywalking上下文ContextCarrier

如果我们看其他实现trace传递的dubbo增强也是类似的实现原理,比如Tlog,感兴趣可以去看看,这里就不分析了

### SkyWalkingDubbo 的集成方案 SkyWalking 是一款开源的应用性能监控 (APM) 工具,能够对分布式系统的调用链路进行跟踪和分析。而 Dubbo 则是一个高性能的 Java RPC 框架,广泛应用于微服务架构中。两者可以通过特定方式集成,从而实现对 Dubbo 微服务的全面监控。 #### 集成方案概述 为了使 SkyWalking 能够追踪 Dubbo 服务之间的调用关系,通常采用基于 Java Agent 技术的方式[^4]。具体来说,通过在应用启动时加载 `skywalking-agent.jar` 文件,并设置相应的环境变量,即可完成基本的集成工作。以下是具体的配置步骤: 1. **添加 SkyWalking Agent 参数** - 在 Dubbo 提供者和服务消费者的 JVM 启动参数中加入 `-javaagent:<path_to_skywalking_agent>/skywalking-agent.jar`。 - 设置必要的属性,例如应用程序名称 (`application_code`) 和 Collector 地址 (`collector.servers`)。 ```bash JAVA_OPTS="-javaagent:/path/to/skywalking-agent.jar \ -Dskywalking.agent.application_code=my-dubbo-service \ -Dskywalking.collector.servers=127.0.0.1:10800" ``` 2. **验证 Collector 是否正常运行** 如果指定的端口无法访问,则表明 SkyWalking Backend 可能未正确启动或存在网络问题。 3. **测试并观察结果** 完成上述操作后,重启相关服务实例并通过 SkyWalking UI 查看生成的服务拓扑图以及详细的请求轨迹数据[^2]。 --- ### SkyWalkingDubbo 的对比分析 尽管二者同属现代软件开发领域的重要工具之一,但它们的功能定位和技术特性差异显著: | 方面 | SkyWalking | Dubbo | |--------------------|-----------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------| | 主要用途 | APM(Application Performance Management),用于实时监测、诊断复杂系统中的性能瓶颈 | RPC(Remote Procedure Call)框架,专注于跨进程间高效通信 | | 核心功能 | 收集指标、日志;可视化展示依赖关系及时延分布 | 注册中心管理、负载均衡策略定制 | | 实现机制 | 使用字节码增强技术动态注入探针 | 基于接口定义远程方法调用 | | 社区活跃度 | Apache 孵化毕业项目 | Alibaba 开源维护 | 值得注意的是,虽然两者本身并无直接竞争关系,但在某些场景下可能会被共同选用来解决不同的需求——即利用 Dubbo 构建灵活可扩展的基础架构的同时借助 SkyWalking 来保障其稳定性与效率[^3]。 ```python # 示例 Python 代码片段仅作演示目的 def integrate_skywalking_with_dubbo(): agent_path = "/opt/skywalking/agent/" java_opts = f"-javaagent:{agent_path}skywalking-agent.jar " \ "-Dskywalking.agent.application_code=demo-app " \ "-Dskywalking.collector.servers=localhost:10800" print(f"Java Options for integration:\n{java_opts}") integrate_skywalking_with_dubbo() ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值