当前位置: 首页 > article >正文

Dubbo如何传递链路追踪id?

1.什么是链路追踪?

分布式链路追踪就是将一次分布式请求还原成调用链路,将一次分布式请求的调用情况集中展示,比如各个服务节点上的耗时、请求具体到达哪台机器上、每个服务节点的请求状态等等。

链路跟踪主要功能:

  • 故障快速定位:可以通过调用链结合业务日志快速定位错误信息。
  • 链路性能可视化:各个阶段链路耗时、服务依赖关系可以通过可视化界面展现出来。
  • 链路分析:通过分析链路耗时、服务依赖关系可以得到用户的行为路径,汇总分析应用在很多业务场景。

应用场景

在现行微服务的趋势下,一次调用的过程中涉及多个服务节点,产生的日志分布在不同的服务器上,如果需要查看一次调用的全链路日志,则一般的做法是通过在系统边界中产生一个 traceId,向调用链的后续服务传递 traceId,后续服务继续使用 traceId 打印日志,并再向其他后续服务传递 traceId,此过程简称,traceId透传。 在使用HTTP协议作为服务协议的系统里,可以统一使用一个封装好的http client做traceId透传。但是dubbo实现traceId透传就稍微复杂些了。一般情况下,会自定义Filter来实现traceId透传。

探寻原理

链路追踪系统(可能)最早是由Goggle公开发布的一篇论文《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》被大家广泛熟悉,大家感兴趣的话可以去看一看

2.代码工程

前提条件:dubbo工程如何搭建详:Spring Boot集成dubbo快速入门Demo

实验目标

实现消费者和生产者之间传递traceID

消费者

配置过滤器

package com.et.consumer.config;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.*;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
@Slf4j
@Activate(group = {Constants.CONSUMER})
public class ConsumerFilter implements Filter {

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        Object token = MDC.get("TRACKING_LOG_SESSION_TOKEN_ID");
        if (token != null) {
            log.info("----cunsumer trace id:{}",token);
            RpcContext.getContext().setAttachment("TRACKING_LOG_SESSION_TOKEN_ID", token.toString());
        }
        Result result = invoker.invoke(invocation);
        return result;
    }
}

在dubbo-samples-spring-boot-consume/src/main/resources/META-INF/dubbo下面配置过滤器  

ConsumerFilter=com.et.consumer.config.ConsumerFilter

consumer

生产者

配置过滤器

package com.et.provider.config;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.*;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;

@Slf4j
@Activate(group = { Constants.PROVIDER })
public class ProviderFilter implements Filter {

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {

       String var = RpcContext.getContext().getAttachment("TRACKING_LOG_SESSION_TOKEN_ID");
        MDC.put("TRACKING_LOG_SESSION_TOKEN_ID", var);
        log.info("----->provider trance id:{}",var);
        Result result = invoker.invoke(invocation);
        MDC.remove("TRACKING_LOG_SESSION_TOKEN_ID");

        return result;
    }
}

在dubbo-samples-spring-boot-provider/src/main/resources/META-INF/dubbo下面配置过滤器

ProviderFilter=com.et.provider.config.ProviderFilter

   

provider

以上只是一些关键代码,所有代码请参见下面代码仓库

代码仓库

  • https://github.com/Harries/springboot-demo(dubbo)

3.测试

  • 启动dubbo-samples-spring-boot-provider
  • 启动dubbo-samples-spring-boot-consume
  • 访问http://127.0.0.1:8080/user/info

消费端日志

2024-08-29 23:46:24.497 [1AB90DBB-06CA-4D35-8A2E-BEDBB4F86DA9] [http-nio-8080-exec-1] INFO  c.et.consumer.config.ConsumerFilter [ConsumerFilter.java:16] - ----cunsumer trace id:1AB90DBB-06CA-4D35-8A2E-BEDBB4F86DA9

服务端日志

2024-08-29 23:46:24.589 [1AB90DBB-06CA-4D35-8A2E-BEDBB4F86DA9] [DubboServerHandler-192.168.0.100:20880-thread-2] INFO c.et.provider.config.ProviderFilter [ProviderFilter.java:18] - ----->provider trance id:1AB90DBB-06CA-4D35-8A2E-BEDBB4F86DA9
2024-08-29 23:46:24.595 [1AB90DBB-06CA-4D35-8A2E-BEDBB4F86DA9] [DubboServerHandler-192.168.0.100:20880-thread-2] INFO c.e.provider.service.UserServiceImpl [UserServiceImpl.java:19] - this is a test

实验结果表明traceid【1AB90DBB-06CA-4D35-8A2E-BEDBB4F86DA9】在消费者和服务者之间传递

4.总结

dubbo通过spi和Adaptive注解来实现链路追踪id传递

dubbo的SPI

dubbo在原有的spi基础上主要有以下的改变,①配置文件采用键值对配置的方式,使用起来更加灵活和简单 ② 增强了原本SPI的功能,使得SPI具备ioc和aop的功能,这在原本的java中spi是不支持的。dubbo的spi是通过ExtensionLoader来解析的,通过ExtensionLoader来加载指定的实现类,配置文件的路径在META-INF/dubbo路径下

@Adaptive注解的作用是什么?

Dubbo通过注解@Adaptive作为标记实现了一个适配器类,dubbo将会为这个类动态生成代理对象;ExtensionLoader中获取默认实现类或者通过实现类名称(由@SPI注解指定的名称)来获取实现类 为什么会出现@Adaptive这个注解呢?主要原因是因为dubbo的加载扩展了是从配置文件加载的,是很动态的,但是实现类却要固定写死或者灵活实现,所以就得区分开。用@Adaptive就是表示由框架自己生成,不需要人为实现.在dubbo加载SPI时会动态创建SPI Adaptive实现ExtensionLoader。

  • ExtensionLoader 类里声明了以下几个文件夹都可以使用
private static final String SERVICES_DIRECTORY = "META-INF/services/";
private static final String DUBBO_DIRECTORY = "META-INF/dubbo/";
private static final String DUBBO_INTERNAL_DIRECTORY = "META-INF/dubbo/internal/";

 

5.引用

  • Peter Bourgon · Metrics, tracing, and logging
  • Dubbo如何传递链路追踪id? | Harries Blog™
  • https://cn.dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/attachment/

http://www.kler.cn/news/283781.html

相关文章:

  • 小琳AI课堂:使用ChatGPT API搭建系统(二)
  • innovus:如何让部分sink长到target insertion delay的长度
  • 关于OBI 在unity URP环境下使用的正确步骤
  • 网络编程(学习)2024.8.27
  • jQuery基础——选择器的补充方法——过滤方法、查找方法
  • python使用multiprocessing多进程通讯
  • 各种各样的正则表达式
  • 92. UE5 RPG 使用C++创建GE实现灼烧的负面效果
  • 达梦数据库-DM8 企业版安装指南
  • [java][代码] java中date格式化输出时间字符串
  • 《征服数据结构》LFU缓存
  • Vatee万腾平台:打造企业智能化转型的坚实后盾
  • 【Android】UIMode
  • fpga图像处理实战-双三次插值算法
  • Jmeter提取token并设置为全局变量
  • 聊聊STM32 MCU的BOOT0和BOOT1引脚
  • 浅谈Vue3和React18
  • 六个方面探讨企业为何迫切需要替换FTP
  • PyQt 迁移到 PySide
  • WPF ToolkitMVVM RelayCommand
  • 探究:Elasticsearch 文档的 _id 是 Lucene 的 docid 吗?
  • DNN学习平台(GoogleNet、SSD、FastRCNN、Yolov3)
  • C# 自动化抢购脚本:基于商品链接的实现方案
  • 【杂谈】新能源和智能车
  • 在docker中安装skywalking + es
  • 一起搭WPF架构之浅写View界面按钮的进阶设计
  • 人工智能领域面试基础问题整理(二):什么是人工智能?
  • OpenCV小练习:人脸检测
  • LVS之net模式实验
  • MySQL空间管理:查询、优化与碎片清理