.NET Core分布式链路追踪框架的基本实现原理

分布式追踪

什么是分布式追踪

分布式系统

当我们使用 Google 或者 百度搜索时,查询服务会将关键字分发到多台查询服务器,每台服务器在自己的索引范围内进行搜索,搜索引擎可以在短时间内获得大量准确的搜索结果;同时,根据关键字,广告子系统会推送合适的相关广告,还会从竞价排名子系统获得网站权重。通常一个搜索可能需要成千上万台服务器参与,需要经过许多不同的系统提供服务。

多台计算机通过网络组成了一个庞大的系统,这个系统即是分布式系统。

在微服务或者云原生开发中,一般认为分布式系统是通过各种中间件/服务网格连接的,这些中间件提供了共享资源、功能(API等)、文件等,使得整个网络可以当作一台计算机进行工作。

分布式追踪

在分布式系统中,用户的一个请求会被分发到多个子系统中,被不同的服务处理,最后将结果返回给用户。用户发出请求和获得结果这段时间是一个请求周期。

当我们购物时,只需要一个很简单的过程:

获取优惠劵 -> 下单 -> 付款 -> 等待收货

然而在后台系统中,每一个环节都需要经过多个子系统进行协作,并且有严格的流程。例如在下单时,需要检查是否有优惠卷、优惠劵能不能用于当前商品、当前订单是否符合使用优惠劵条件等。

下图是一个用户请求后,系统处理请求的流程。

图中出现了很多箭头,这些箭头指向了下一步要流经的服务/子系统,这些箭头组成了链路网络。

在一个复杂的分布式系统中,任何子系统出现性能不佳的情况,都会影响整个请求周期。根据上图,我们设想:

1.系统中有可能每天都在增加新服务或删除旧服务,也可能进行升级,当系统出现错误,我们如何定位问题?

2.当用户请求时,响应缓慢,怎么定位问题?

3.服务可能由不同的编程语言开发,1、2 定位问题的方式,是否适合所有编程语言?

分布式追踪有什么用呢

随着微服务和云原生开发的兴起,越来越多应用基于分布式进行开发,但是大型应用拆分为微服务后,服务之间的依赖和调用变得越来越复杂,这些服务是不同团队、使用不同语言开发的,部署在不同机器上,他们之间提供的接口可能不同(gRPC、Restful api等)。

为了维护这些服务,软件领域出现了 Observability 思想,在这个思想中,对微服务的维护分为三个部分:

  • 度量(Metrics):用于监控和报警;
  • 分布式追踪(Tracing):用于记录系统中所有的跟踪信息;
  • 日志(Logging):记录每个服务只能中离散的信息;

这三部分并不是独立开来的,例如 Metrics 可以监控 Tracing 、Logging 服务是否正常运行。Tacing 和 Metrics 服务在运行过程中会产生日志。

近年来,出现了 APM 系统,APM 称为 应用程序性能管理系统,可以进行 软件性能监视和性能分析。APM 是一种 Metrics,但是现在有融合 Tracing 的趋势。

回归正题,分布式追踪系统(Tracing)有什么用呢?这里可以以 Jaeger 举例,它可以:

  • 分布式跟踪信息传递
  • 分布式事务监控
  • 服务依赖性分析
  • 展示跨进程调用链
  • 定位问题
  • 性能优化

Jaeger 需要结合后端进行结果分析,jaeger 有个 Jaeger UI,但是功能并不多,因此还需要依赖 Metrics 框架从结果呈现中可视化,以及自定义监控、告警规则,所以很自然 Metrics 可能会把 Tracing 的事情也做了。

Dapper

Dapper 是 Google 内部使用的分布式链路追踪系统,并没有开源。

Dapper 用户接口:

分布式追踪系统的实现

下图是一个由用户 X 请求发起的,穿过多个服务的分布式系统,A、B、C、D、E 表示不同的子系统或处理过程。

在这个图中, A 是前端,B、C 是中间层、D、E 是 C 的后端。这些子系统通过 rpc 协议连接,例如 gRPC。

一个简单实用的分布式链路追踪系统的实现,就是对服务器上每一次请求以及响应收集跟踪标识符(message identifiers)和时间戳(timestamped events)。

分布式服务的跟踪系统需要记录在一次特定的请求后系统中完成的所有工作的信息。用户请求可以是并行的,同一时间可能有大量的动作要处理,一个请求也会经过系统中的多个服务,系统中时时刻刻都在产生各种跟踪信息,必须将一个请求在不同服务中产生的追踪信息关联起来。

为了将所有记录条目与一个给定的发起者X关联上并记录所有信息,现在有两种解决方案,黑盒(black-box)和基于标注(annotation-based)的监控方案。

黑盒方案:

假定需要跟踪的除了上述信息之外没有额外的信息,这样使用统计回归技术来推断两者之间的关系。

基于标注的方案:

依赖于应用程序或中间件明确地标记一个全局ID,从而连接每一条记录和发起者的请求。

优缺点:

虽然黑盒方案比标注方案更轻便,他们需要更多的数据,以获得足够的精度,因为他们依赖于统计推论。基于标注的方案最主要的缺点是,很明显,需要代码植入。在我们的生产环境中,因为所有的应用程序都使用相同的线程模型,控制流和 RPC 系统,我们发现,可以把代码植入限制在一个很小的通用组件库中,从而实现了监测系统的应用对开发人员是有效地透明。

Dapper 基于标注的方案,接下来我们将介绍 Dapper 中的一些概念知识。

跟踪树和 span

从形式上看,Dapper 跟踪模型使用的是树形结构,Span 以及 Annotation。

在前面的图片中,我们可以看到,整个请求网络是一个树形结构,用户请求是树的根节点。在 Dapper 的跟踪树结构中,树节点是整个架构的基本单元。

span 称为跨度,一个节点在收到请求以及完成请求的过程是一个 span,span 记录了在这个过程中产生的各种信息。每个节点处理每个请求时都会生成一个独一无二的的 span id,当 A -> C -> D 时,多个连续的 span 会产生父子关系,那么一个 span 除了保存自己的 span id,也需要关联父、子 span id。生成 span id 必须是高性能的,并且能够明确表示时间顺序,这点在后面介绍 Jaeger 时会介绍。

Annotation 译为注释,在一个 span 中,可以为 span 添加更多的跟踪细节,这些额外的信息可以帮助我们监控系统的行为或者帮助调试问题。Annotation 可以添加任意内容。

到此为止,简单介绍了一些分布式追踪以及 Dapper 的知识,但是这些不足以严谨的说明分布式追踪的知识和概念,建议读者有空时阅读 Dapper 论文。

要实现 Dapper,还需要代码埋点、采样、跟踪收集等,这里就不再细谈了,后面会介绍到,读者也可以看看论文。

Jaeger 和 OpenTracing

OpenTracing

OpenTracing 是与分布式系统无关的API和用于分布式跟踪的工具,它不仅提供了统一标准的 API,还致力于各种工具,帮助开发者或服务提供者开发程序。

OpenTracing 为标准 API 提供了接入 SDK,支持这些语言:Go, JavaScript, Java, Python, Ruby, PHP, Objective-C, C++, C#。

当然,我们也可以自行根据通讯协议,自己封装 SDK。

接下来我们要一点点弄清楚 OpenTracing 中的一些概念和知识点。由于 jaeger 是 OpenTracing 最好的实现,因此后面讲 Jaeger 就是 Opentracing ,不需要将两者严格区分。

Jaeger 结构

首先是 JAEGER 部分,这部分是代码埋点等流程,在分布式系统中处理,当一个跟踪完成后,通过 jaeger-agent 将数据推送到 jaeger-collector。jaeger-collector 负责处理四面八方推送来的跟踪信息,然后存储到后端,可以存储到 ES、数据库等。Jaeger-UI 可以将让用户在界面上看到这些被分析出来的跟踪信息。

OpenTracing API 被封装成编程语言的 SDK(jaeger-client),例如在 C# 中是 .dll ,Java 是 .jar,应用程序代码通过调用 API 实现代码埋点。

jaeger-Agent 是一个监听在 UDP 端口上接收 span 数据的网络守护进程,它会将数据批量发送给 collector。

OpenTracing 数据模型

在 OpenTracing 中,跟踪信息被分为 Trace、Span 两个核心,它们按照一定的结构存储跟踪信息,所以它们是 OpenTracing 中数据模型的核心。

Trace 是一次完整的跟踪,Trace 由多个 Span 组成。下图是一个 Trace 示例,由 8 个 Span 组成。

Tracing:

a Trace can be thought of as a directed acyclic graph (DAG) of Spans。

有点难翻译,大概意思是 Trace 是多个 Span 组成的有向非循环图。

在上面的示例中,一个 Trace 经过了 8 个服务,A -> C -> F -> G 是有严格顺序的,但是从时间上来看,B 、C 是可以并行的。为了准确表示这些 Span 在时间上的关系,我们可以用下图表示:

有个要注意的地方, 并不是 A -> C -> F 表示 A 执行结束,然后 C 开始执行,而是 A 执行过程中,依赖 C,而 C 依赖 F。因此,当 A 依赖 C 的过程完成后,最终回到 A 继续执行。所以上图中 A 的跨度最大。

Span 格式

要深入学习,就必须先了解 Span,请读者认真对照下面的图片和 Json:

json 地址:https://github.com/whuanle/DistributedTracing/issues/1

后续将围绕这张图片和 Json 来举例讲述 Span 相关知识。

Trace

一个简化的 Trace 如下:

注:不同编程语言的字段名称有所差异,gRPC 和 Restful API 的格式也有所差异。

            "traceID": "790e003e22209ca4",
            "spans":[...],
            "processes":{...}

前面说到,在 OpenTracing 中,Trace 是一个有向非循环图,那么 Trace 必定有且只有一个起点。

这个起点会创建一个 Trace 对象,这个对象一开始初始化了 trace id 和 process,trace id 是一个 32 个长度的字符串组成,它是一个时间戳,而 process 是起点进程所在主机的信息。

下面笔者来说一些一下 trace id 是怎么生成的。trace id 是 32个字符串组成,而实际上只使用了 16 个,因此,下面请以 16 个字符长度去理解这个过程。

首先获取当前时间戳,例如获得 1611467737781059 共 16 个数字,单位是微秒,表示时间 2021-01-24 13:55:37,秒以下的单位这里就不给出了,明白表示时间就行。

在 C# 中,将当前时间转为这种时间戳的代码:

        public static long ToTimestamp(DateTime dateTime)
        {
            DateTime dt1970 = new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return (dateTime.Ticks - dt1970.Ticks)/10;
        }

// 结果:1611467737781059

如果我们直接使用 Guid 生成或者 string 存储,都会消耗一些性能和内存,而使用 long,刚刚好可以表示时间戳,还可以节约内存。

获得这个时间戳后,要传输到 Jaeger Collector,要转为 byet 数据,为什么要这样不太清楚,按照要求传输就是了。

将 long 转为一个 byte 数组:

            var bytes = BitConverter.GetBytes(time);
			// 大小端
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(bytes);
            }

long 占 8 个字节,每个 byte 值如下:

0x00 0x05 0xb9 0x9f 0x12 0x13 0xd3 0x43

然后传输到 Jaeger Collector 中,那么获得的是一串二进制,怎么表示为字符串的 trace id?

可以先还原成 long,然后将 long 输出为 16 进制的字符串:

转为字符串(这是C#):

Console.WriteLine(time.ToString("x016"));

结果:

0005b99f1213d343

Span id 也是这样转的,每个 id 因为与时间戳相关,所以在时间上是唯一的,生成的字符串也是唯一的。

这就是 trace 中的 trace id 了,而 trace process 是发起请求的机器的信息,用 Key-Value 的形式存储信息,其格式如下:

                        {
                            "key": "hostname",
                            "type": "string",
                            "value": "Your-PC"
                        },
                        {
                            "key": "ip",
                            "type": "string",
                            "value": "172.6.6.6"
                        },
                        {
                            "key": "jaeger.version",
                            "type": "string",
                            "value": "CSharp-0.4.2.0"
                        }

Ttace 中的 trace id 和 process 这里说完了,接下来说 trace 的 span。

Span

Span 由以下信息组成:

  • An operation name:操作名称,必有;
  • A start timestamp:开始时间戳,必有;
  • A finish timestamp:结束时间戳,必有;
  • Span Tags.:Key-Value 形式表示请求的标签,可选;
  • Span Logs:Key-Value 形式表示,记录简单的、结构化的日志,必须是字符串类型,可选;
  • SpanContext :跨度上下文,在不同的 span 中传递,建立关系;
  • Referencest:引用的其它 Span;

span 之间如果是父子关系,则可以使用 SpanContext 绑定这种关系。父子关系有 ChildOfFollowsFrom 两种表示,ChildOf 表示 父 Span 在一定程度上依赖子 Span,而 FollowsFrom 表示父 Span 完全不依赖其子Span 的结果。

一个 Span 的简化信息如下(不用理会字段名称大小写):

{
                    "traceID": "790e003e22209ca4",
                    "spanID": "4b73f8e8e77fe9dc",
                    "flags": 1,
                    "operationName": "print-hello",
                    "references": [],
                    "startTime": 1611318628515966,
                    "duration": 259,
                    "tags": [
                        {
                            "key": "internal.span.format",
                            "type": "string",
                            "value": "proto"
                        }
                    ],
                    "logs": [
                        {
                            "timestamp": 1611318628516206,
                            "fields": [
                                {
                                    "key": "event",
                                    "type": "string",
                                    "value": "WriteLine"
                                }
                            ]
                        }
                    ]
}

OpenTracing API

在 OpenTracing API 中,有三个主要对象:

  • Tracer
  • Span
  • SpanContext

Tracer可以创建Spans并了解如何跨流程边界对它们的元数据进行Inject(序列化)和Extract(反序列化)。它具有以下功能:

  • 开始一个新的 Span
  • Inject一个SpanContext到一个载体
  • Extract一个SpanContext从载体

由起点进程创建一个 Tracer,然后启动进程发起请求,每个动作产生一个 Span,如果有父子关系,Tracer 可以将它们关联起来。当请求完成后, Tracer 将跟踪信息推送到 Jaeger-Collector中。

SpanContext 是在不同的 Span 中传递信息的,SpanContext 包含了简单的 Trace id、Span id 等信息。

我们继续以下图作为示例讲解。

A 创建一个 Tracer,然后创建一个 Span,代表自己 (A),再创建两个 Span,分别代表 B、C,然后通过 SpanContext 传递一些信息到 B、C;B 和 C 收到 A 的消息后,也创建一个 Tracer ,用来 Tracer.extract(...) ;其中 B 没有后续,可以直接返回结果;而 C 的 Tracer 继续创建两个 Span,往 D、E 传递 SpanContext。

这个过程比较复杂,笔者讲不好,建议读者参与 OpenTracing 的官方文档。

详细的 OpenTracing API,可以通过编程语言编写相应服务时,去学习各种 API 的使用。

到此这篇关于.NET Core分布式链路追踪框架的基本实现原理的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • ASP.NET Core框架探索之Authentication的权限认证过程解析

    今天我们来探索一下ASP.NET Core中关于权限认证,所谓权限认证,就是通过某些方式获取到用户的信息. 需要开启权限认证,我们首先需要在容器中注入认证服务,使用services.AddAuthentication.进入该方法的源码,最重要的其实就是AddAuthenticationCore方法,他向容器中注入了认证体系中很重要的对象:IAuthenticationService.IAuthenticationHandlerProvider.IAuthenticationSchemeProvi

  • .NET Core基于EMIT编写的轻量级AOP框架CZGL.AOP

    目录 1,快速入门 1.1继承ActionAttribute特性 1.2标记代理类型 2,如何创建代理类型 通过API直接创建 2,创建代理类型 通过API 通过Microsoft.Extensions.DependencyInjection 通过Autofac 3,深入使用 代理类型 方法.属性代理 上下文 拦截方法或属性的参数 非侵入式代理 Nuget 库地址:https://www.nuget.org/packages/CZGL.AOP/ Github 库地址:https://github

  • .NET Core实现简单的Redis Client框架

    目录 0,关于RedisRESP 1,定义数据类型 2,定义异步消息状态机 3,定义命令发送模板 4,定义RedisClient 5,实现简单的RESP解析 6,实现命令发送客户端 7,如何使用 8,更多客户端 9,更多测试 10,性能测试 0,关于 Redis RESP RESP 全称 REdis Serialization Protocol ,即 Redis 序列化协议,用于协定客户端使用 socket 连接 Redis 时,数据的传输规则. 官方协议说明:https://redis.io/

  • .Net使用分表分库框架ShardingCore实现多字段分片

    目录 介绍 项目地址 背景 原理 直接开始 添加依赖 创建一个订单对象 创建DbContext 创建分片路由 ShardingCore启动配置 测试 默认配置下的测试 测试无路由返回默认值 总结 介绍 本期主角:ShardingCore 一款ef-core下高性能.轻量级针对分表分库读写分离的解决方案,具有零依赖.零学习成本.零业务代码入侵 dotnet下唯一一款全自动分表,多字段分表框架,拥有高性能,零依赖.零学习成本.零业务代码入侵,并且支持读写分离动态分表分库,同一种路由可以完全自定义的新

  • ASP.NET Core 6框架揭秘实例演示之如何承载你的后台服务

    目录 [S1401]利用承载服务收集性能指标 [S1402]依赖注入的应用 [S1403]配置选项的应用 [S1404]提供针对环境的配置 [S1405]日志的应用 [S1406]在配置中定义日志过滤规则 借助 .NET提供的服务承载(Hosting)系统,我们可以将一个或者多个长时间运行的后台服务寄宿或者承载我们创建的应用中.任何需要在后台长时间运行的操作都可以定义成标准化的服务并利用该系统来承载,ASP.NET Core应用最终也体现为这样一个承载服务. 借助 .NET提供的服务承载(Hos

  • .NET Core使用APB vNext框架入门教程

    目录 快速入门案例 .NET Core 控制台应用 1. 安装 ABP 框架核心依赖 2. 新建 ABP 应用的启动模块 3. 新建服务,并注册到启动模块中 4. 根据启动模块创建 ABP应用,调用应用中注册的服务方法 ASP.NET Core Web 应用程序 1. 安装 ABP 框架核心依赖 2.新建 ABP 应用的启动模块 3. 注册 ABP 启动模块,并初始化 ABP 应用 4. 新建控制器,测试 ABP 应用运行状态 各个击破案例 在模块中注册自定义服务 使用标签属性注册自定义服务 A

  • .Net Core3.0 WebApi 项目框架搭建之使用Serilog替换掉Log4j

    为什么使用Serilog Serilog 是一个用于.NET应用程序的日志记录开源库,配置简单,接口干净,并可运行在最新的.NET平台上,与其他日志库不同, Serilog 是以功能强大的结构化事件数据为基础构建的, 支持将日志输出到控制台.文件.数据库和其它更多的方式,支持参数化日志模板,非常灵活. 之前我们项目使用的是Log4j来记录用户日志的,在开发的过程中,慢慢的发现Log4j好像并不能满足我们的需求,比如结构化,日志分析等,于是决定使用serilog来替换掉Log4j,在使用的过程中发

  • ASP.NET Core  依赖注入框架的使用

    目录 一.IoC框架 二.IoC-Autofac 三..NET Core中自带DI的使用 四.Autofac 使用 五.批量注入 前言: 还记得上篇文章中ASP.NET Core 依赖注入详细最后提及到,假如服务越来越多怎么处理呢,本篇文章将会带来解决办法.这篇是接上一篇文章的,概念方面的可以参考上一篇文章. 一.IoC框架 先说说常见的Ioc框架吧. Autofac: 目前net用的比较多,好多大佬的项目比较优先选择的框架. Ninject: 已经很少用了,还时在很早的文章中见过. Unity

  • .NET Core分布式链路追踪框架的基本实现原理

    分布式追踪 什么是分布式追踪 分布式系统 当我们使用 Google 或者 百度搜索时,查询服务会将关键字分发到多台查询服务器,每台服务器在自己的索引范围内进行搜索,搜索引擎可以在短时间内获得大量准确的搜索结果:同时,根据关键字,广告子系统会推送合适的相关广告,还会从竞价排名子系统获得网站权重.通常一个搜索可能需要成千上万台服务器参与,需要经过许多不同的系统提供服务. 多台计算机通过网络组成了一个庞大的系统,这个系统即是分布式系统. 在微服务或者云原生开发中,一般认为分布式系统是通过各种中间件/服

  • .NET Core分布式链路追踪框架的基本实现原理

    目录 分布式追踪 什么是分布式追踪 分布式系统 分布式追踪 分布式追踪有什么用呢 Dapper 分布式追踪系统的实现 跟踪树和 span Jaeger 和 OpenTracing OpenTracing Jaeger 结构 OpenTracing 数据模型 Span 格式 Trace Span OpenTracing API 分布式追踪 什么是分布式追踪 分布式系统 当我们使用 Google 或者 百度搜索时,查询服务会将关键字分发到多台查询服务器,每台服务器在自己的索引范围内进行搜索,搜索引擎

  • php链路追踪框架skywalking介绍

    目录 Skywalking介绍 Skywalking功能介绍 Skywalking介绍 Skywalking是一个国产的开源框架,2015年有吴晟个人开源,2017年加入Apache孵化器,国人开源的产品,主要开发人员来自于华为,2019年4月17日Apache董事会批准SkyWalking成为顶级项目,支持Java..Net.NodeJs等探针,数据存储支持Mysql.Elasticsearch等,跟Pinpoint一样采用字节码注入的方式实现代码的无侵入,探针采集数据粒度粗,但性能表现优秀,

  • Go 分布式链路追踪实现原理解析

    目录 为什么需要分布式链路追踪系统 微服务架构给运维.排障带来新挑战 分布式链路追踪系统如何帮助我们 分布式链路追踪系统架构概览 核心概念 一般架构 协议标准和开源实现 应用侧调用链跟踪实现方案概览 应用侧核心任务 基于 OTEL 库实现调用拦截 HttpServer Handler 生成 Span 过程 HttpClient 请求生成 Span 过程 基于 OTEL 库实现调用链跟踪总结 非侵入调用链跟踪实现思路 Go 非侵入链路追踪实现原理 在分布式.微服务架构下,应用一个请求往往贯穿多个分

  • spring cloud 分布式链路追踪的方法

    一篇讲了微服务之间的调用spring cloud eureka 微服务之间的调用 微服务之间进行调用 那么如果我负责一个模块 别人负责另一个模块 我调用了他的方法 测试那边却报了错 那是我的问题还是他的问题 这个时候大家应该就能想到日志可以解决这个问题 如何使用日志呢 先在配置文件中加 logging: path: D:\logs\poppy-mall #日志的存放地址 最好再加个项目名的文件夹 可以更容易的区分 level: org.poppy.mall: info #日志的级别 org.po

  • net core下链路追踪skywalking安装和简单使用教程

    当我们用很多服务时,各个服务间的调用关系是怎么样的?各个服务单调用的顺序\时间性能怎么样?服务出错了,到底是哪个服务引起的?这些问题我们用什么方案解决呢,以前的方式是各个系统自己单独做日志,出了问题从暴出问题的服务开始一个一个服务的排查,耗时耗力,有些日志不全的,还不一定查得出来.好在现在有Skywalking链路追踪系统,可以不用写任何代码,就追踪到各个服务间的调用关系和性能状态等. 本文将从0开始搭建两个webapi项目,使用Skywalking来追踪他们之间的调用关系及响应时间.开发环境为

  • ASP.Net Core中的日志与分布式链路追踪

    目录 .NET Core 中的日志 控制台输出 非侵入式日志 Microsoft.Extensions.Logging ILoggerFactory ILoggerProvider ILogger Logging Providers 怎么使用 日志等级 Trace.Debug 链路跟踪 OpenTracing 上下文和跟踪功能 跟踪单个功能 将多个跨度合并到一条轨迹中 传播过程中的上下文 分布式链路跟踪 在不同进程中跟踪 在 ASP.NET Core 中跟踪 OpenTracing API 和

  • Jaeger Client Go入门并实现链路追踪

    目录 Jaeger 部署 Jaeger 从示例了解 Jaeger Client Go 了解 trace.span tracer 配置 Sampler 配置 Reporter 配置 分布式系统与span 怎么调.怎么传 HTTP,跨进程追踪 客户端 Web 服务端 Tag . Log 和 Ref Jaeger OpenTracing 是开放式分布式追踪规范,OpenTracing API 是一致,可表达,与供应商无关的API,用于分布式跟踪和上下文传播. OpenTracing 的客户端库以及规范

  • Jaeger Client Go入门并实现链路追踪

    目录 Jaeger 部署 Jaeger 从示例了解 Jaeger Client Go 了解 trace.span tracer 配置 Sampler 配置 Reporter 配置 分布式系统与span 怎么调.怎么传 HTTP,跨进程追踪 客户端 Web 服务端 Tag . Log 和 Ref Jaeger OpenTracing 是开放式分布式追踪规范,OpenTracing API 是一致,可表达,与供应商无关的API,用于分布式跟踪和上下文传播. OpenTracing 的客户端库以及规范

  • .NET core项目AsyncLocal在链路追踪中的应用

    目录 前言 老传统做法 AspNetCore的TraceIdentifier AsyncLocal在链路追踪的应用 定义 示例 项目应用 AspNet4 AspNetCore 前言 在项目生产中日志的记录是必不可少的,在.net项目中,要说日志组件,log4net绝对可有一席之地,随着公司业务的发展,微服务则必定无可避免.在跨服务中通过日志进行分析性能或者排查故障点,如何快速定位日志尤为关键.链路追踪技术的出现正是解决这些痛点的. 分布式链路追踪需要收集单次请求所经过的所有服务,而且为了知道请求

随机推荐