在 SkyWalking 中,TraceSegment 是一个介于 Trace 与 Span 之间的概念,它是一条 Trace 的一段,可以包含多个 Span。在微服务架构中,一个请求基本都会涉及跨进程(以及跨线程)的操作,例如, RPC 调用、通过 MQ 异步执行、HTTP 请求远端资源等,处理一个请求就需要涉及到多个服务的多个线程。TraceSegment 记录了一个请求在一个线程中的执行流程(即 Trace 信息)。将该请求关联的 TraceSegment 串联起来,就能得到该请求对应的完整 Trace。

1、一个Tracesegemnt记录了一个请求在一个线程中的执行流程,一个trace由多个tracesegment构成,一个TraceSegment 是由多个 Span 构成的

下面我们先来介绍 TraceSegment 的核心字段:

traceSegmentId(ID 类型):TraceSegment 的全局唯一标识,是由前面介绍的 GlobalIdGenerator 生成的。
refs(List<TraceSegmentRef> 类型):它指向父 TraceSegment。在我们常见的 RPC 调用、HTTP 请求等跨进程调用中,一个 TraceSegment 最多只有一个父 TraceSegment,但是在一个 Consumer 批量消费 MQ 消息时,同一批内的消息可能来自不同的 Producer,这就会导致 Consumer 线程对应的 TraceSegment 有多个父 TraceSegment 了,当然,该 Consumer TraceSegment 也就属于多个 Trace 了。
relatedGlobalTraces(DistributedTraceIds 类型):记录当前 TraceSegment 所属 Trace 的 Trace ID。
spans(List<AbstractTracingSpan> 类型):当前 TraceSegment 包含的所有 Span。
ignore(boolean 类型):ignore 字段表示当前 TraceSegment 是否被忽略。主要是为了忽略一些问题 TraceSegment(主要是对只包含一个 Span 的 Trace 进行采样收集)。
isSizeLimited(boolean 类型):这是一个容错设计,例如业务代码出现了死循环 Bug,可能会向相应的 TraceSegment 中不断追加 Span,为了防止对应用内存以及后端存储造成不必要的压力,每个 TraceSegment 中 Span 的个数是有上限的(默认值为 300),超过上限之后,就不再添加 Span了。

TraceSegment 中除了 Span 之外,还有另一个需要介绍的重要依赖 —— TraceSegmentRef,TraceSegment 通过 refs 集合记录父 TraceSegment 的信息,它的核心字段大概可以分为 3 类:

逻辑概念:

我们来看下span的管理,当请求通过tomcat的时候,创建一个entryspan,然后调用entryspan的start方法,会把entryspan放入到span队列的activespanstack中,当请求经过springmvc的时候,不会在创建entryspan,只会重新调用entryspan的start方法,当在业务方法中调用接口的first方法的时候,会创建一份localspan,并且把localspan添加到activespanstack中,当firts方法调用结束的时候,localspan会出栈,当调用业务的end方法的时候,会创建一份localspan,并且把localspan添加到activespanstack中,当end方法调用结束的时候,localspan会出栈

接下来使用dubbo接口远程调用say方法的时候,会创建一个exitspan,然后将exitspan添加到activespanstack中,当say方法调结束的时候,会将exitspan出栈,最后方法介绍,第一个entryspan出栈

接下来我们总结下skywalking的核心概念的理论

skywalking的框图如下所示

1.博客参考https://www.upyun.com/opentalk/334.html

我们在一次调用里面,所经历的一个线程,会生成一个 TraceSegment 。这里它经历了 4 个线程,不管是否跨 JOM ,A 里面 1 个,B 里面 1 个,B 里面的 New Thread 1 个,C 里面 1 个,所以它经历了四个线程后就会生成四 TraceSegment 对象。一次调用经过调用经历一个线程就是产生一个TraceSegment,整个一个trace的调用链就是由多个TraceSegment构成的。

TraceSegment对应的就是数据库中segment表,该表中记录了对于的segment信息,我们来看该表的字段信息

  1. CREATE TABLE `segment` (
  2. `id` varchar() CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  3. `segment_id` varchar() CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  4. `trace_id` varchar() CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  5. `service_id` int() DEFAULT NULL,
  6. `service_instance_id` int() DEFAULT NULL,
  7. `endpoint_name` varchar() CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  8. `endpoint_id` int() DEFAULT NULL,
  9. `start_time` bigint() DEFAULT NULL,
  10. `end_time` bigint() DEFAULT NULL,
  11. `latency` int() DEFAULT NULL,
  12. `is_error` int() DEFAULT NULL,
  13. `data_binary` mediumtext CHARACTER SET utf8 COLLATE utf8_general_ci,
  14. `version` int() DEFAULT NULL,
  15. `time_bucket` bigint() DEFAULT NULL,
  16. PRIMARY KEY (`id`) USING BTREE,
  17. INDEX `SEGMENT_TRACE_ID`(`trace_id`) USING BTREE,
  18. INDEX `SEGMENT_ENDPOINT_ID`(`endpoint_id`) USING BTREE,
  19. INDEX `SEGMENT_LATENCY`(`latency`) USING BTREE,
  20. INDEX `SEGMENT_TIME_BUCKET`(`time_bucket`) USING BTREE
  21. ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
  22.  
  23. SET FOREIGN_KEY_CHECKS = ;
  • trace_id:本次调用的唯一id,通过snowflake模式生成
  • endpoint_name:被调用的接口
  • latency:耗时
  • end_time:结束时间戳
  • endpoint_id:被调用的接口的唯一id
  • service_instance_id:被调用的实例的唯一id
  • version:本数据结构的版本号
  • start_time:开始时间戳
  • 我们现在来看下面的一个案例:

这里有一个很重要的字段信息,data_binary,这里面保存了当时TraceSegment下面的全部的span的信息,这里span的信息都是采用Base64编码存储到数据库中的

我们模拟一个user应用调用order应用,我们发起了一个http://10.8.62.148:8094/testport这次调用在segment表中产生了下面三条记录

在链路追踪的页面展示如下情况如下,链路展示是依据segment表中存储的3条数据展示出来的

当在上面的图上选择某一条记录点击的时候,可以在右侧弹出当前TraceSegment下面保存的span信息,span信息数据保存到data_binary这个字段中的

大概的效果就是上面的形式,接下来我们研究具体的原理

TraceSegment下面有span,整个trace的依赖依赖于span

以一个Trace为例:

首先是外部请求调用A,然后A依次同步调用了B和C,而B被调用时会去同步调用D,C被调用的时候会依次同步调用E和F,F被调用的时候会通过异步调用G,G则会异步调用H,最终完成一次调用。

上图是通过Span之间的依赖关系来表现一个Trace,而在时间线上,则可以有如下的表达:

上面我们了解了span之间的关系,接下来我们来看skywalking中是如何实现的

在应用访问serverA的时候,对于入口,不管外围调用是否前置,都会创建一个 entry span,在entryspan中会记录下面的一些字段的信息,当前span属于哪个TraceSegment,当前span是否有父span,当前span的访问的方法的名称等

要创建span, 我们要从当前的http的请求头中提取前置上下文,这里seriviceA是入口的请求第一个点没有前置,所以什么都没拿到。然后会创建一个 exit span ,创建一个最出的埋点。之后会做一个 inject的操作,把当前的上下文例如当前span的id、当前span的访问的方法等放在 HTTP 的头里面,顺带这个 HTTP的调用发到 Service B 上。接下来就会创建一个TraceSegment记录以及包当前创建的entrySpan保存到当前的这个TraceSegment记录中,保存之后就会在segment表中增加一条记录

接下来,

首先是外部请求调用A,然后A依次同步调用了B和C,而B被调用时会去同步调用D,C被调用的时候会依次同步调用E和F,F被调用的时候会通过异步调用G,G则会异步调用H,最终完成一次调用。

上图是通过Span之间的依赖关系来表现一个Trace,而在时间线上,则可以有如下的表达:

skywalking的核心概念的更多相关文章

  1. 领域驱动设计(DDD)部分核心概念的个人理解

    领域驱动设计(DDD)是一种基于模型驱动的软件设计方式.它以领域为核心,分析领域中的问题,通过建立一个领域模型来有效的解决领域中的核心的复杂问题.Eric Ivans为领域驱动设计提出了大量的最佳实践 ...

  2. Javascript本质第一篇:核心概念

    很多人在使用Javascript之前都至少使用过C++.C#或Java,面向对象的编程思想已经根深蒂固,恰好Javascript在语法上借鉴了Java,虽然方便了Javascript的入门,但要深入理 ...

  3. [程序设计语言]-[核心概念]-02:名字、作用域和约束(Bindings)

    本系列导航 本系列其他文章目录请戳这里. 1.名字.约束时间(Binding Time) 在本篇博文开始前先介绍两个约定:第一个是“对象”,除非在介绍面向对象语言时,本系列中出现的对象均是指任何可以有 ...

  4. spring技术核心概念纪要

    一.背景 springframework 从最初的2.5版本发展至今,期间已经发生了非常多的修正及优化.许多新特性及模块的出现,使得整个框架体系显得越趋庞大,同时也带来了学习及理解上的困难. 本文阐述 ...

  5. ElasticSearch学习笔记-01 简介、安装、配置与核心概念

    一.简介 ElasticSearch是一个基于Lucene构建的开源,分布式,RESTful搜索引擎.设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便.支持通过HTTP使用JSON进 ...

  6. Playmaker Input篇教程之引入的核心概念

    Playmaker Input篇教程之引入的核心概念 Playmaker Input引入的核心概念 Playmaker引入了4个核心概念:状态机.动作.变量和事件.了解它们是学习操作Playmaker ...

  7. Maven的几个核心概念

    POM (Project Object Model) 一个项目所有的配置都放置在 POM 文件中:定义项目的类型.名字,管理依赖关系,定制插件的行为等等.比如说,你可以配置 compiler 插件让它 ...

  8. 刀哥多线程GCD核心概念gcd

    GCD GCD 核心概念 将任务添加到队列,并且指定执行任务的函数 任务使用 block 封装 任务的 block 没有参数也没有返回值 执行任务的函数 异步 dispatch_async 不用等待当 ...

  9. cocos2d-x一些核心概念截杀

    Cocos2d-x中有很多概念,这些概念很多来源于动画.动漫和电影等行业,例如:导演.场景和层等概念,当然也有些有传统的游戏的概念.Cocos2d-x中核心概念:导演, 场景,层,节点,精灵,菜单动作 ...

随机推荐

  1. Bank4

    Account: package banking4; public class Account { private double balance; public Account(double int_ ...

  2. 微软:悬赏10万美金破解 Linux 系统

    微软选择了 Linux 系统作为物联网平台,并且悬赏10万美金邀请黑客来进行破解. 当然,该悬赏计划不是针对所有的 Linux 系统,而是特别针对微软的物联网端对端安全平台Azure Sphere.本 ...

  3. 网络编程TCP/IP详解

    网络编程TCP/IP详解 1. 网络通信 中继器:信号放大器 集线器(hub):是中继器的一种形式,区别在于集线器能够提供多端口服务,多口中继器,每个数据包的发送都是以广播的形式进行的,容易阻塞网络. ...

  4. FTP免费工具,FTP免费工具推荐!

    IIS7服务器管理工具是FTP操作的客户端软件,能够作为批量操作FTP命令!同时,它还能够作为VNC的操作客户端进行VNC的相关操作!能够连接Windows和Linux的服务器和PC,并进行实时的检测 ...

  5. 最好用的FTP工具,最好用的FTP工具推荐!

    IIS7服务器管理工具是一个良好的FTP的客户端,可以进行FTP的操作!同时,还可以作为VNC的客户端进行VNC的相关操作!它还能连接Windows和Linux的服务器和PC,并对他们的连接状态进行实 ...

  6. 3. OpenCV-Python——图像梯度算法、边缘检测、图像金字塔与轮廓检测、直方图与傅里叶变换

    一.图像梯度算法 1.图像梯度-Sobel算子 dst = cv2.Sobel(src, ddepth, dx, dy, ksize) ddepth:图像的深度 dx和dy分别表示水平和竖直方向 ks ...

  7. JAVASE(十五) 泛型 :泛型用例、自定义泛型类、通配符

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 1.泛型在集合中的使用 1.1 在集合中使用泛型之前的例子 ​ 为什么要有泛型(Generic)? 1. ...

  8. Linux (三) 基础命令 上

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一 . 背景知识 1. Linux系统中一切皆文件 在Linux系统中任何东西都是以文件形式来存储的.这 ...

  9. Java实现 LeetCode 791 自定义字符串排序(桶排序)

    791. 自定义字符串排序 字符串S和 T 只包含小写字符.在S中,所有字符只会出现一次. S 已经根据某种规则进行了排序.我们要根据S中的字符顺序对T进行排序.更具体地说,如果S中x在y之前出现,那 ...

  10. (Java实现) 删数问题

    删数问题(需知道的数学定理) 给定n位正整数a,去掉其中任意k≤n 个数字后,剩下的数字按原次序排列组成一个新 的正整数.对于给定的n位正整数a和正整数 k,设计一个算法找出剩下数字组成的新数最 小的 ...