分布式系统间请求跟踪

标签: 框架/架构 分布式 请求跟踪 | 发表时间:2017-04-22 08:27 | 作者:coderbee
出处:http://coderbee.net

一、请求跟踪基本原理

现在的很多应用都是由很多系统系统在支持,这些系统还会部署很多个实例,用户的一个请求可能在多个系统的部署实例之间流转。为了跟踪一个请求的完整处理过程,我们可以给请求分配一个唯一的 ID traceID,当请求调用到另一个系统时,我们传递这个 traceID。在输出日志时,把这个 traceID 也输出到日志里,这样,根据日志文件,提取出现这个 traceID 的日志就可以分析这个请求的完整调用过程,甚至进行性能分析。

当然,在一个系统内部,我们不希望每次调用一个方法时都要传递这个 traceID,因此在 Java 里,一般把这个 traceID 放到某种形式的 ThreadLocal 变量里。

日志类库在输出日志时,就从这个 ThreadLocal 变量里取出 traceID,跟要输出的日志信息一起写入日志文件。

这样对于应用的开发者来说,基本不需要关注这个 traceID

二、远程调用间传递跟踪信息

如何使用的是自定义的 RPC 实现,这些 RPC 一般都预留了扩展机制来传递一些自定义的信息,我们可以把 traceID 作为自定义信息进行传递。

对于 Hessian 这种基于 HTTP 协议的 RPC 方法,它把序列化后的调用信息作为 POST 的请求体。如果我们不想去修改 Hessian 的调用机制,可以把 traceID 放到 HTTP 的请求头里。

在客户端只需要提供封装好的 RPC 调用代理。

在服务端通过 Filter 得到 traceID 放入 ThreadLocal 变量。

三、线程间传递跟踪信息

在实际的应用中,我们还可能把请求交给别的线程去异步处理,这就涉及在线程间传递 traceID

当我们直接用 java.util.concurrent.ExecutorService.submit(Runnable task) 提交一个任务时,显然是不会自动传递这个 traceID 的,我们需要做一些封装来透明地传递 traceID

下面是一个可跟踪任务的定义,利用 org.slf4j.MDC 来保存旧线程里的 traceID,在新线程执行子类任务时初始化跟踪信息。

  package net.coderbee.util.concurrent;

import org.slf4j.MDC;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * Created by coderbee on 2017/4/21.
 */
class TraceableTask {
    private Map<String, String> context;

    public TraceableTask() {
        context = MDC.getCopyOfContextMap();
    }

    protected void clearContext() {
        MDC.clear();
    }

    void initContext() {
        if (context == null || context.isEmpty()) {
            init();
        } else {
            MDC.setContextMap(context);
        }
    }

    private void init() {
        Map<String, String> context = new HashMap<String, String>();
        String traceID = UUID.randomUUID().toString().replace("-", "");
        context.put("trace_id", traceID);

        MDC.setContextMap(context);
    }

}

Runnable, Callable<T> 分别定义一个子类如下:

  package net.coderbee.util.concurrent;

public abstract class TraceableRunnable extends TraceableTask
        implements Runnable {

    public final void run() {
        super.initContext();

        run0();
    }

    protected abstract void run0();
}


package net.coderbee.util.concurrent;

import java.util.concurrent.Callable;

public abstract class TraceableCallable<T> extends TraceableTask
        implements Callable<T> {

    public final T call() {
        super.initContext();

        return call0();
    }

    protected abstract T call0();
}

这两个子类利用了 Java 在对象实例化时总是会执行父类构造函数的特点,使得子类不需要显式保存 traceID

当我们实例化 TraceableRunnableTraceableCallable 时,是在旧的线程里执行的,因此它的 traceID 会保存在 TraceableTaskcontext 属性里。

当另一个线程执行这些任务实例时,首先执行的是 runcall 方法, TraceableTask 会把保存的 context 设置到当前线程的 ThreadLocal 里,这就完成了 traceID 的传递。

相关 [分布 系统 跟踪] 推荐:

分布式系统间请求跟踪

- - 码蜂笔记
现在的很多应用都是由很多系统系统在支持,这些系统还会部署很多个实例,用户的一个请求可能在多个系统的部署实例之间流转. 为了跟踪一个请求的完整处理过程,我们可以给请求分配一个唯一的 ID traceID,当请求调用到另一个系统时,我们传递这个 traceID. 在输出日志时,把这个 traceID 也输出到日志里,这样,根据日志文件,提取出现这个 traceID 的日志就可以分析这个请求的完整调用过程,甚至进行性能分析.

分布式会话跟踪系统架构设计与实践

- - 美团点评技术团队
本文整理自美团点评技术沙龙第08期:大规模集群的服务治理设计与实践. 美团点评技术沙龙由美团点评技术团队主办,每月一期. 每期沙龙邀请美团点评及其它互联网公司的技术专家分享来自一线的实践经验,覆盖各主要技术领域. 目前沙龙会分别在北京、上海和厦门等地举行,要参加下一次最新沙龙活动. 赶快关注微信公众号“美团点评技术团队”.

浅析淘宝分布式调用跟踪系统

- - 企业架构 - ITeye博客
分布式系统为什么需要分布式跟踪. 电商平台由数以百计的分布式服务构成,每一个请求路由过来后,会经过多个业务系统并留下足迹,并产生对各种Cache或DB的访问,但是这些分散的数据对于问题排查,或是流程优化都帮助有限. 对于这么一个跨进程/跨线程的场景,汇总收集并分析海量日志就显得尤为重要. 要能做到追踪每个请求的完整调用链路,收集调用链路上每个服务的性能数据,计算性能数据和比对性能指标(SLA),甚至在更远的未来能够再反馈到服务治理中,那么这就是分布式跟踪的目标了.

Facebook Cookies跟踪登出系统的用户

- 微笑!?~ - Solidot
淘宝网女装秋装外套 写道 "Facebook被人诟病的最大问题是隐私问题,现在它再次被曝光在用户登出系统后仍然跟踪用户行为. 新的隐私问题是:由于修改了cookie,Facebook现在知道用户在做什么,即使用户已经登出Facebook网站,他们也能通过Cookie继续跟踪用户. 澳大利亚技术抓紧Nik Cubrilovic运行一系列测试,分析浏览器向Facebook网站发出请求的HTTP头文件,他发现Facebook在用户登出的时候没有删除cookie,而是对其跟踪的cookie进行修改.

开源分布式跟踪方案概览

- - InfoQ - 促进软件开发领域知识与创新的传播
本文最初发表于 RedHat的开发者博客,经RedHat和原作者Juraci Paixão Kröhling授权由InfoQ中文站翻译分享. 入门分布式跟踪可能是一项很艰难的任务. 这个领域有太多新术语、框架和工具,它们有着明显互相重叠的功能,初学者很容易迷失或偏离主题. 本文对最流行的工具进行了概述和分类,能够帮助你掌握分布式跟踪领域的概况.

研究人员发现无法躲避的在线跟踪系统

- Gnauk - Solidot
加州伯克利大学的研究人员曝光了一种用户无法避开的在线跟踪系统,即使他们屏蔽了cookies,或者是使用浏览器的隐身模式. KISSmetrics是被用于跟踪用户访问数量,所访问网页,从何处点击进入网站的路径等的在线服务,该公司声称它的功能比Google Analytics更全面. 但研究人员发现,用户无法选择退出KISSmetrics的跟踪系统.

分布式缓存系统 Xixibase

- Le - 开源中国社区最新软件
Xixibase是一个高性能,跨平台的分布式缓存系统. Xixibase server 采用 C++ 实现,底层网络库采用的是Boost Asio. Xixibase 主要特点: 1. 实现'Local Cache'功能, 当客户端打开'Local Cache'选项, 客户端可以将数据同时存储在Server 端和本地,并且保证本地数据和Server 端的数据的一致性.

分布式检索系统 ElasticSearch

- - 丕子
ElasticSearch最近发展不错,github等都用它,可以关注I下. ElasticSearch是分布式,REST风格,搜索和分析系统. 具有实时数据,实时分析,分布式,高可用性,多租户,全文搜索,面向文档,冲突管理,自由模式,rest风格API,每个操作的持久性,Apache 2的开源许可证,基于Apache Lucene之上的特点.

分布式消息系统:Kafka

- - 标点符
Kafka是分布式发布-订阅消息系统. 它最初由LinkedIn公司开发,之后成为Apache项目的一部分. Kafka是一个分布式的,可划分的,冗余备份的持久性的日志服务. 在大数据系统中,常常会碰到一个问题,整个大数据是由各个子系统组成,数据需要在各个子系统中高性能,低延迟的不停流转. 传统的企业消息系统并不是非常适合大规模的数据处理.

分布式系统介绍-PNUTS

- - CSDN博客推荐文章
PNUTS是Yahoo!的分布式数据库系统,支持地域上分布的大规模并发操作. 它根据主键的范围区间或者其哈希值的范围区间将表拆分为表单元(Tablet),多个表单元存储在一个服务器上. 一个表单元控制器根据服务器的负载情况,进行表单元的迁移和拆分. 每条记录的数据都没有固定的模式(采用JSON格式的文本).