原 荐 Dubbo链路追踪——生成全局ID(traceId)

栏目: 后端 · 发布时间: 8年前

原 荐 Dubbo链路追踪——生成全局ID(traceId)

Dubbo链路追踪——生成全局ID(traceId)

原

荐

  键走偏锋 发布于 22分钟前

字数 899

阅读 4

收藏 0

Dubbo

开源中国十周年庆:开源众包怎么做我说了算!参与赢终身免费大奖 >>> 原 荐 Dubbo链路追踪——生成全局ID(traceId)

全局 traceId

关于链路追踪,在微服务的趋势下,一次调用的日志信息分布在不同的机器上或目录下,当需要看一条链路调用所有的日志信息时,这是个比较困难的地方,我们虽然有ELK , Sentry等日志异常收集分析工具, 但是如何把信息串起来也是一个关键的问题。 我们一般的做法是在系统调用开始时生成一个traceId , 并且它伴随着一次调用的整个生命周期 。 当一个服务调用另外一个服务的时候,traceId 则向下透传,全局使用唯一一个。

一、通过修改Dubbo源码实现全局traceId(侵入性高不建议使用)

我们通过分析源码可以知道客户端在调用服务段进行服务消费时,实际上发送的是封装过的Request实体 ,Data为Invocation实体对象(接口签名,参数类型,参数值,及attachment附件)

final class HeaderExchangeChannel implements ExchangeChannel {
...
    public ResponseFuture request(Object request, int timeout) throws RemotingException {
        if (closed) {
            throw new RemotingException(this.getLocalAddress(), null, "Failed to send request " + request + ", cause: The channel " + this + " is closed!");
        }
        // create request.
        Request req = new Request();
        req.setVersion("2.0.0");
        req.setTwoWay(true);
        req.setData(request);
        DefaultFuture future = new DefaultFuture(channel, req, timeout);
        try {
            channel.send(req);
        } catch (RemotingException e) {
            future.cancel();
            throw e;
        }
        return future;
    }
...
}

通过源码可知 request是入参,其他参数均为固定,所以只能在request中做文章。

代码涉及到的类有

  • TraceIdUtil : 链路追踪全局ID生成器
  • InvokerInvocationHandler : 消费端Invocation处理器
  • DubboProtocol : Dubbo协议处理入口,内有服务提供者处理请求数据信息的Handler处理器

TraceIdUtil源码如下

public class TraceIdUtil {

	private static final ThreadLocal<String> TRACE_ID = new ThreadLocal<String>();

	public static String getTraceId() {
		if(TRACE_ID.get() == null) {
			String s = UUID.randomUUID().toString();
			setTraceId(s);
		}
		return TRACE_ID.get();
	}

	public static void setTraceId(String traceId) {
		TRACE_ID.set(traceId);
	}
}

由 Dubbo线程模型图示 可知,Dubbo客户端调用实际上通过JavassistProxyFactory获取的是Proxy代理对象。 原 荐 Dubbo链路追踪——生成全局ID(traceId) 代码如下

public class JavassistProxyFactory extends AbstractProxyFactory {
	...
    @SuppressWarnings("unchecked")
    public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
        return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
    }
	...
}

其中 InvokerInvocationHandler 调用数据的处理及rpc调用实体的封装过程。所以我们需要在调用的起始位置添加traceId信息 。 原 荐 Dubbo链路追踪——生成全局ID(traceId)

其次是服务提供者进行请求处理过程: DubboProtocol的requestHandler 请求处理器(不明白请详读服务Dubbo服务暴露过程源码) 原 荐 Dubbo链路追踪——生成全局ID(traceId)

将traceId 从RpcInvocation 的attachment属性中取出 ,传给TraceIdUtil 方面后续调用过程使用。

扩展Provider端Filter (无侵入性,建议使用)

创建Filter 服务提供者端扩展

/**
 * Created with IntelliJ IDEA.
 *
 * @author: bakerZhu
 * @description:
 * @time: 2018年09月09日
 * @modifytime:
 */
@Activate(group = {Constants.CONSUMER, Constants.PROVIDER} , order = -9999)
public class GlobalTraceFilter implements Filter {

	@Override
	public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
		String traceId = invocation.getAttachment("traceId");
		if(!StringUtils.isBlank(traceId)) {
			RpcContext.getContext().setAttachment("traceId",traceId);
		}else { // 第一次发起调用
			RpcContext.getContext().setAttachment("traceId", UUID.randomUUID().toString());
		}
		return invoker.invoke(invocation);
	}
}

资源文件夹下创建 META-INF/dubbo 文件夹 创建com.alibaba.dubbo.rpc.Filter 文件,并编辑文件内容 gtrace=com.alibaba.dubbo.rpc.filter.GlobalTraceFilter

疑惑点 为什么设置Dubbo上下文的attachment调用时会出现在 RpcInvocation中

详见 AbstractInvoker.invoke(Invocation inv) 方法

public abstract class AbstractInvoker<T> implements Invoker<T> {
    public Result invoke(Invocation inv) throws RpcException {
		......
        Map<String, String> context = RpcContext.getContext().getAttachments();
        if (context != null) {
            invocation.addAttachmentsIfAbsent(context);
        }
        if (getUrl().getMethodParameter(invocation.getMethodName(), Constants.ASYNC_KEY, false)) {
            invocation.setAttachment(Constants.ASYNC_KEY, Boolean.TRUE.toString());
        }
        RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
		......
    }
}

将上下文的“附件信息”拷贝到RpcInvocation中

© 著作权归作者所有

共有人打赏支持

原 荐 Dubbo链路追踪——生成全局ID(traceId)

键走偏锋

粉丝 79

博文 556

码字总数 563559

作品 0

通州

程序员

相关文章 最新文章

分布式系统调用链监控

分布式系统调用链监控 应用架构由集中式向分布式演进后,整个调用关系变得复杂。 分布式架构由复杂且较大规模集群构成,各个应用之间相当独立,可能由不同团队、不同语言实现。 系统一个完整...

wangyangzhizhou

2016/12/23

0

0

原 荐 Dubbo链路追踪——生成全局ID(traceId)
#研发解决方案介绍#Tracing(鹰眼)

郑昀 最后更新于2014/11/12 GoogleDapper、分布式跟踪、鹰眼、Tracing、HBase、HDFS、 本文档适用人员:研发 分布式系统为什么需要 Tracing? 先介绍一个概念:分布式跟踪,或分布式追踪。 ...

旁观者-郑昀

2014/12/17

0

1

分布式调用跟踪系统调研笔记

分布式调用链跟踪系统通常有几个设计目标 低侵入性 -- 作为非业务组件,应当尽可能少侵入或者无侵入其他业务系统,对于使用方透明,减少开发人员的负担; 灵活的应用策略 -- 可以(最好随时)...

ginobefun

2017/05/25

0

0

原 荐 Dubbo链路追踪——生成全局ID(traceId)
分布式跟踪系统-cicada

https://github.com/Yirendai/cicada/blob/master/cicada-docs/cicadadesign.md 背景与目标 面对日趋复杂的分布式系统,如服务框架、消息中间件、缓存、数据层等,我司在业务性能瓶颈定位、故...

tantexian

2016/11/02

547

1

ZipKin原理学习--ZipKin入门介绍

ZipKin入门介绍 Zipkin是一款开源的分布式实时数据追踪系统(Distributed Tracking System),基于 Google Dapper的论文设计而来,由 Twitter 公司开发贡献。其主要功能是聚集来自各个异构系...

qq924862077

05/12

0

0

原 荐 Dubbo链路追踪——生成全局ID(traceId)

没有更多内容

加载失败,请刷新页面

加载更多
Thread的run()与start()的区别

Thread的run()与start()的区别 java 的线程是通过java.lang.Thread类来实现的。VM启动时会有一个由主方法所定义的线程。可以通过创建Thread的实例来创建新的线程。每个线程都是通过某个特...

DemonsI

12分钟前

0

0

golang.org/x/xxx 包的手动安装方法

由于 golang.org 在国内已被墙,不能直接使用go get安装对应的包,但是可以通过github间接安装。 因为 golang.org/x/xxx 这类包托管在 github.com/golang,从这里找到相应的包即可。比如 go...

FalconChen

14分钟前

0

0

小视频合并 怎样把多个视频片段合并成一个完整的视频

在网上刷小视频的时候可以发现,有很多视频是由多个小视频合并到一起的,我们也可以将多个视频片段合并到一起,制作成一个完整视频。对多个视频片段进行合并的好处就是,让你在观看视频的...

萤火的萤火

19分钟前

1

0

原 荐 Dubbo链路追踪——生成全局ID(traceId)
Win8.1上安装.NET Framework3.5

1.首先找到你的系统安装文件 如:cn_windows_8.1_professional_vl_with_update_x64_dvd_4050293.iso 2.解压出来的路径: E:\cn_windows_8.1_professional_vl_with_update_x64_dvd_4050293 3.找......

Kxvz

21分钟前

0

0

Java并发编程:volatile关键字解析

Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过。在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果。在...

飓风2000

22分钟前

0

0

原 荐 Dubbo链路追踪——生成全局ID(traceId)

没有更多内容

加载失败,请刷新页面

加载更多

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。

Learning Python, 5th Edition

Learning Python, 5th Edition

Mark Lutz / O'Reilly Media / 2013-7-6 / USD 64.99

If you want to write efficient, high-quality code that's easily integrated with other languages and tools, this hands-on book will help you be productive with Python quickly. Learning Python, Fifth Ed......一起来看看 《Learning Python, 5th Edition》 这本书的介绍吧!

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具