那我们就直接开始了因为前面设备耽误了一些时间首先谢谢大家在中午吃饭这个时间来到我的session我本次分享的主题是在Open Telemetry中平衡成本和采样质量也就是针对分布式追踪里面采样发案的一个介绍首先自我介绍一下我叫朱杰坤来自去玩科技是因为开发工程师同时也是Open Telemetry的贡献者我前几年的时候是在业务团队做后端开发所以我曾经也是各种可观测试性基础设施特别是分布式追踪这些平台的用户早期因为这些基础设施不怎么好用所以我也提过不少问题排查的公单我们的运为同事就说就是因为你们这些业务研发天天搞一大堆公单天天公单满天飞又不来帮忙解决问题我说OK 那就一起去搞所以我现在就变成了这些基础设施的维护者了分享完之后也得赶紧回去处理我的一堆故障公单我们今天的分享会分为以下几个小节首先我会介绍我们在可观测试性和分布式追踪里面的经历我们现在的情况以及未来想要做一些什么这些东西为我们带来了什么样的挑战在第二和第三小节会介绍这些问题在Open Telemetry体系里面现有的解决方案以及他们都各自有怎样的成本和效果这些现成的方案或许可以解决掉不少的问题但是仍然会有一些更加边缘的情况用Open Telemetry以外的方案覆盖效果可能会更好我们放在第四节讨论最后的第五小节做一点点总结和展望在进入正题之前提醒大家可以随时通过这个地址捷困到DEVGun Hotel来记录你的问题这个地址也会出现在每夜PPT的右上角收集到的问题会在分享之后和大家交流首先分布是追踪在去玩的现状咱们公司是做兴趣社交和电子竞技的主要的业务包括TT语音、TT电竞如果有关注英雄联盟或者王者荣耀的同学可能会经常看到我们PPT的广告我们目前大部分项目都是运行在Kubernetes之上的搭配Azure我们对应用服务的观察数据来自于服务内SDK的上报作为代理的Azure的上报以及其他部署在节点上的Azure等等如果聚焦在分布是追踪这方面我们每天是有超过400亿的Span被上报的上面说的这些通用的技术设施通常能给你完成大部分的工作但是剩下一些在边边角角的场景很有可能没有办法覆盖到针对这些场景我们正在探索EBPF的使用尝试去为各种没有介入East Hill或者说出于各种原因没有去缺乏买点的应用去提供一些请求直别的可观侧性支持那在所有这些探索的过程里面我们会发现越来越多的数据被送进来其实上一场分享也有提到比如说我们自己在当个规模不大的集群用EBPF去采集数据的时候我们看到每天有超过40TB的Trace数据产生那使用这些数据是有成本的我们肯定得考虑它值不值得所以我们就会去想现在有多少的Trace数据对问地排查是有帮助的可能除了少数包含异常的数据有用别的都是数据嘛那怎么样做才可以去减少这些数据的产生呢OpenTalented生态里面提供了一些很简单的手段去应对上面的问题那在详细了解之前我再花几分钟去向不了解分布数追踪的朋友介绍一下分布数追踪具体来说你可以想象成为你描述一次请求所经过的服务形成一张调用的实蓄图或者准确一点来说是干特图用这一次的调用过程为trace而trace是由每个服务或者说每个服务处理一次请求的过程来组成的那这些过程我们称之为spam比如说右边的图里面产生了四个spam而这四个spam组成了一条trace一条trace里面会包含很多信息包括各个spam的耗时然后一些标记位用于标记状态以及很多自定义的key value属性等等我们现在已经知道了trace是长什么样子的了它的信息是由不同的服务上报然后串联而来的如果让你去做筛选采样让每天100万的数据只留下一万你会怎么样去实现呢第一种简单的方法就是当请求抵达整个链路里面的第一个服务的时候这个服务会为这次请求生成一个独一无二的trace ID这个trace ID在生成trace ID的同时也会有其他的标记位生成其中一个标记位就是我们的采样标记位依照一定的概率或者规则如果第一个服务决定要采样或者上报这个标记位也会随着Trace的上下文信息通过rpc header或者metadata等等的各种方式传播给后续的服务后续的服务只要遵循第一个服务的采样决定要么都跟着他上报要么都随之不上报这种采样的方式我们称为头部采样头部采样的特点在于它是由头部服务也就是第一个产生的span决策的传播到后续的span去整个采样的决策是发生在应用层面或者说client SDK的层面因此只有很少的数据被应用上报到应用之外那后续的流程里面的自然也只有很少的数据流转很少的数据存储以及很少的数据作展示头部采样带来最大的问题是在采样的时候我们第一个span或者说我们的gunspan它的视角是非常有限的它并不知道未来要发生什么所以呢并没有办法依照是否有错误或者说整个调用耗时是否有增长等等的问题去做决策那为了解决这些问题我们也可以选择无脑地把所有的数据上报然后由一个中间的平台去暂存清洗最后再来决定要保留还是丢弃掉整条trace如图所示在请求抵达的时候每个服务都把它自身产生的span发送给Open Telemetry的collectorcollector上面的尾部采样组件在接收到第1个span的时候会等待一段时间比如说5秒钟来继续收集其他服务发送过来的TraceID相同的span在等待结束之后这些数据到的span按照TraceID放在一起然后collector会对其每个span进行便利检查里面有没有一些错误的信息或者说所有span加起来的耗时有没有特别长等等这样子可以有依据的去筛选一些高价值的trace发到下一个流程比如说发到存阻组件里面去这种采样的模式我们称为尾部采样它是由collector依据整个trace的信息来进行决策的决策的依据会比头部采样丰富很多但是因为collector要承载大量的临时数据所以它对基础设施的要求会很高它的效果在于第一它减少了最终持久化的数据第二这些持久化的数据都是有依据有规律有价值的不像头部采样那样子是完全随机的需要注意的是这里这些数的service跟collector的模型是做了一定程度的减化的在实际的部数里面我们往往会有非常多的collector节点那同一个trace的不同span又是由不同服务产生的这些服务位于不同的地方为了就是实现这个尾部采你肯定会希望这些span能够被发往相同的collector去做暂存和处理那因此肯定会有一层负载均衡部署在collector之前介绍到traceID进行转发这些负载均衡器可以是另一堆的open telemetry collector因为Otel本身是支持负载均衡导出数据的那也可以直接实现在客户端的sdk里面那以上就是open telemetry提供的采样或者说减少trace数量的一些现成的手段那你们可能会想知道实施这些东西大概需要什么样的成本呢在这个小节里面我们将以一个demo伪力去减压的分析为了直观的去对比头部采样和尾部采样的差异我们准备了这样一个demo的系统包括最左边的是一个可配置的trace生成器中间的是open telemetry collector那最右边红色的是OTLP协议的trace receivertrace生成器自然是根据我们的测试要求去生成大量的span而中间的collector用于根据完全的不同去处理或者说不处理这些数据这些数据最后都会被发往receiver进行统计和分析每个组件的支援使用量会被限制在4CPU和8GB内存在生成器这一边它有两种可能有1%或者说100%的上报100%的概率进行上报以此去模拟头部采样的情况当生成器100%上报的时候又会分了两种情况第一种collector这些数据暂存5秒然后对包含错误或者说耗时超过5秒的trace进行违不采样另外一组对照组collector会不进行违不采样也就是直接把所有的数据送往receiver所有的测试都会被执行很多次每次平均都要处理超过40万个span大概是2万条trace我们来看一下测试的结果在处理耗时的比较里面可以看到不同的采样设计它的耗时差异是非常大的1%头部采样的时候它的平均耗时为20毫秒到100%头部采样的时候这个耗时涨到了260毫秒在进一步加入违不采样也就是红色这几根线的时候它的耗时是在600毫秒左右我们看到红色的线其实是红色的折变图其实是缺了一部分的这是因为在压力进一步增大的时候违不采样的数据因为它的内存已经超过了我们的限制值所以后面没有办法继续去记录这些指标耗时的结果其实很好理解不同的头部采样比例也就是1%和100%这个比例的耗时跟它每秒发送的Span数量基本上是成正比的刚好是一个10倍的关系而在进一步增加了违不采样里面因为我们的违不采样策略会针对错误和耗时这两个策略会去执行然后便利所有的Span因此会需要一些额外的时间处理数据才能最终抵达Receiver导致了延迟上的一些差异而在CPU的使用率方面1%的头部采样与另外两种采样的方案差距基本上是在15到20倍左右当数据100%上报的时候有或者没有进行违不采样也就是下面图里面的蓝色和红色它们对CPU的使用率影响相对来说要小很多基本上只有10%的差异我们可以合理地推测CPU其实是有更多的时间花在了对上报的数据的序列化反序列化等等的一些过程而不是在这些采样决策的本身我们之前也提到过说违不采样会需要更多的基础设施资源这个在内存上会体现得比较明显随着每秒上报数量的不断增加在每秒上报超过2万个Span之后实施违不采样红色的线所需要的内存就已经涨到了7GB以上后面是没有办法记录的因为超过了限制相对来说投不采样1%的时候内存压力就非常小了只用了200兆所以为了搭建这个违不采样的体系有很多成本是要被投资在内存上面的例如如果我们把同样是100%上报有违不采样和没有违不采样这两种情况相比他们的内存使用率基本上是一个翻倍的比例那投资了这么多的资源之后我们能获得什么呢如果我们检查receiver收到的数据权量上报的时候你能收集到平均能收集到超过22万个Span而投不采样1%的投不采样和违不采样的时候都只收集到了几千个Span数量是有很大减少的他们之间的量级差距影响的是存储的成本以及数据减锁的时候的性能那我们再来看违不采样和投不采样1%这两个相比他们的数据量是比较接近的在这个前提之下违不采样能获得对排查更有价值的数据因为违不采样的结果都是包含error或者说耗时超过了我们设定预值的一些trace这对程序人排账是非常有帮助的以上就是我们对几个测试场景的对比的概述那我们本来在这里准备了一个很明显的表格去给大家计算这些使用CPU内存的一个成本但是呢因为实验有限我们没有办法依依去解读我们会把它放在最后面的一些引用资料里面基于这个结果我们通常会推荐大家在违不采样里面要为8000span每秒的压力去增加1CPU跟2GB内存的collector资源这个刚好也是Open Telemetry官方现在推荐的一个比例但是在我们的研究里面会发现这些数字其实是受实际的数据集影响非常大的Demo更多是为了给到大家基本的一个成本的印象如果想要使用违不采样的话还是得依照自己生产环境里面的数据去做调整和优化然后另外一个可能有助于控制成本的建议就是一定得把SDK上面的配置动态化中心化然后让它能够接受信息的反馈不管是Open Telemetry也好还是说其他的一些分布式追踪提供的SDK它们的配置基本上都是静态的然后是在科物端本地的可观测试平台作为这些基础设施的提供方必须得有能力去实时的控制用户的配置这样子有助于在发生问题的时候可以及时的去做调整防止单点的问题拖垮整个平台其次可观测试平台通常也会具有一定的数据分析能力分析之后的结果我们可以用来动态的修正这些链路的残酯率因为每条链路它的重要程度都是不一样的都是有分三六九等的甚至同一条链路你在上午和下午它的QPS或者说重要程度也不一样动态调整就是接受反馈并且动态调整这些残酯率可以让我们的每一分成本都花在一些更有意义的地方OK 前面已经简要分析过一些现有的采样策略了他们能够覆盖到生产里面的很多场景但是生产环境的数据混沌程度是原比想像中高的依然会有非常多边缘的case无法通过这些策略去识别我们这个小节针对这些边缘情况介绍和讨论一些还没有进入open telemetry里面的采样策略先举例一个trace左边这里有好几个服务如果他们按照顺序正常的调用的话正常情况下你就会得到形如右边的trace当你的系统每天有几百万条请求所有请求都长这个样子的时候那其实我作为用户或者开发者这么多重复的信息我只要有一两个样本就可以了那头部采样就是针对这种情况去做的你可以通过头部采样拿到像右边这样子的样本某一天你发现你的系统里面出现了很多像黄色的这些慢的调用或者说像红色这种有错误的调用那你可能需要我们刚刚提到的尾部采样去拿到右边的这样子的样本方便去排查但是随着时间的推移生产环境的数据越来越奇怪比如左边图里面框柱的两个例子他们比起正常调用来说就是有的是多了一个spam有的是少了一个spam但是他们的执行速度可能还是很快而且也不包含任何的错误比如说这其实非常常见比如说我们某些逻辑分支它有可能会多执行一条seco语句或者说会多一次的RBC调用这都非常常见那作为开发者我在观察我这个业务的健康情况的时候自然会希望不同的这些所谓的调用路径或者执行路径执行分支都有一定量的数据样本对吧那我们怎么样去识别这些所谓的调用路径执行路径不同的调用呢如果我们这里讲的不是trace而是二差数在一堆二差数里面去找出一些与众不同的数这个问题好像就非常简单了是吧一种很暴力的方法就是我如果把所有的数据都能序列化序列化之后再求个MD5很简单那找出MD5跟别人不一样的目标就是我们想要找的东西了那trace也可以做类似的一个处理在尾部采样的时候我们对原始的trace数据按照他们的名字 时间或者说调用的父子关系把它序列化然后序列化之后通过摘要的计算比如说刚刚举例的MD5去得到一个新的结果那这个结果呢我们可以称之为一个type IDtype ID代表的是一类请求路径相同的trace如果collect里面用简单的频率技术去统计每个类型的频率那就可以让所有的类型都留下样本这种方案呢目前在社区里面是有相关提案的但是还没有实现但是如果我们从成本上去考虑这种方案依然是基于尾部采样的那意味着整个处理流程里面你首先还是得有足够量的数据上报才可以继续运作下去那上报的数据量是影响CPU和内存用量的最主要的因素其次才是我们的这些便利和分析的过程有没有办法进一步的去减少这个上报的数据量呢要减少数据量的话那可能得从上报的client SDK这一端去入手以往trace的上下文信息包括一些采样决策等等都是自顶向下单向去传播的那也就造成了头部采样无法感知后续连络的情况采样决策的信息有限的一个痛点那很自然的我们就会想如果trace的决策信息可以返向传递从下往上传递会怎么样呢如图所示服务在收到调用的时候去执行它自己的逻辑感知有没有错误或者有没有需要采样的情况那把这个决策放在RPC的响应里面返回给调用方调用方此时可能还没有结束自己的流程也就是还没有上报trace信息所以它是仍然有机会去上报的如果每个服务都能从响应里面拿到采样的一个提示修改自己的采样决策并且把这个东西再返回给自己的调用方这样子就可以做到返向采样或者我们说回溯采样很显然这样子的采样方式是有好几个好处的第一个 相比头部采样它授予了所有应用这个采样决策的控制权力第二个 相比尾部采样需要大量的收集数据这种方案能显著降低流通在数据采集链路里面的数据量因为它从一开始就已经降低了整个上报的体量这对于整体的资源成本控制是非常有力的但是有力肯定也会有不好的地方这样子的采样很显然它没有办法去收集到一些已经结束的spam比如我们图里面最左边的这个服务它在整个链路发生问题之前它就已经完成了它的请求的处理和响应因此它不会收到任何采样的通知最终采样的结果也只能是全链路的其中一部分比如说我们这里标红的部分其次 这样子的采样方案会高度依赖于统一的通信框架或者协议在基建不同意的情况下你其实是非常难去推动整个公司都插装或者说修改它的一个响应的自断的非常非常难去推行但是很显然这种方式和对比起头部采样 尾部采样来说它的效果依然是非常让人期待的所以我们会想有没有办法绕过这些条条框框的限制去落地呢这里左边我们已经把刚刚提到的优缺点或者我们或者说我们认为比较理想的采样策略的特点列了出来那咱在探索如何实现他们的时候关注到了今年NSTI上面的一篇论文它解决的是非常类似的痛点所以会希望在这里作为Further Reading推荐给大家我们来看一下它是怎么样绕过这个所谓依赖统一的框架或者说只能采集到部分链路的问题了我们先来看这样子的整体架构不同的服务位于不同的Kubernetes节点每个节点上都有一个回溯采样用的Agent节点之外还会有用于协调全局的一个Collector当请求发酵的时候每个服务都把自己的Trace信息以及有没有错误或者说就是采样决策发送给Agent在正常的情况下Agent可以选择不与Collector进行通信或者只把极少量的Metadata数据进行通信例如它本身的Agent ID加上一个Trace ID当某个服务认为自己需要采样的时候它就会把自己的信息进行上报Agent收到了这个消息它就会把完整的Trace数据发送给Collector完整的Trace数据比如说这里我们服务D的上报就会包含了它自身的Span数据以及它所能感知到的一个调用链路比如说在服务D这里它可能能看到前面的调用是从A到B到C 到D过来的这个调用链路以面包线的形式一并地发往CollectorCollector收到SovisD过来的消息之后它发现要采样了它就会依照刚刚说的调用路径或者说依照TraceID以及它前面收到的TraceID跟AgentID之间的关系它会知道这个Trace相关的Span会存在于哪个Agent里面它会再去反向地找对应的Agent去索要这些数据以此就可以完成回溯采样最终形成一条有价值的Trace这种方式的回溯采样在大多数时间网络之间也就是物理节点之外只有Metadata的传输一定程度是可以降低流通在外的数据量当且仅当有问题发生的时候Collector才反向地去索要完整的数据对比伪布采样它也是有一些优缺点的优点显然是刚刚已经提过了它是缩小了在节点之外流通的数据量就节约了很大部分的网络贷宽缺点是在于它把本来属于Collector就是Collector在做伪布采样的时候它需要很大的内存去暂存这些数据它把原来属于Collector的压力转移到了同机的Agent上面下面我们再花几十秒简单的过一下这种论文上面的方案的资源评估情况先给结论在每秒200兆Trace数据产生的情况下方案对延迟和吞吐量的影响不足3.5%图中的两条曲线现在是对应没有Trace也就是绿色焦曲线以及做伪布采样的时候的延迟可以看到他们现在的差距已经是非常大的论文里面的方案论文里面的回溯采样它的延迟曲线可以看到是蓝色焦曲线非常贴近于没有采样的情况如果我们再去比较其他的采样方案可以看到没有采样1%头部采样或者说论文里面回溯采样的结果它都非常接近而对于头部采样来说它的采样率上升的时候它的吞吐量就会逐步的受到影响最差的情况是做伪布采样的时候在带宽边缘场景覆盖率等等的方面论文里面都有一些文外的数据支撑回溯采样跟其他的采样方案相比很多的指标都是处于第一梯队的这里就不一去解读了还推荐感兴趣的同学可以顺着PPD莫为的指引去翻一下论文最后一个小节我们可以来简单的总结一下以及聊一下这里面新宠儿EBPF采样策略其实自DAPR出来之后已经发展了很多年了但是我们依然可以看到现在主流的头部采样尾部采样它都有各自的一些优缺点甚至我们可以说它缺点是非常明显的而其他新兴的一些采样方案要么依赖特定的基础设施要么还没有经过大规模的实验验证所以还是有很大的发展空间的公司除了在做采样以外采样是用来降低数据量的但是从另一头看如何去获得更加全面的数据量也是我们或者说社区或者说可玩策性领域在探索的这就得聊一下EBPF了在以往我们要手动位程序特别是购义员的业务运用里面去买点买点是否完善是否全面是限制可玩策性体系搭建的一个障碍之一我们想要做的东西是监控买点和业务完全分离比如说图里面的紧依靠在同机的agent去监听检测和采集TCP包然后送往serverserver来构建最终的日治指标和trace数据现在接触一些EBPF的工具或者平台已经可以实现这些事情了但是我们发现也议入了很多问题需要处理比如说EBPF对网络包的数据的采集它是非常广而全的如果左图是代表我们利用层手动买点看到的trace那EBPF能采集到的数据很可能就像右图这样子更细腻的数据确实是做所有事情的一个基础这是个好事情但是在使用的时候我们还是要考虑成本你要投入多少的资源去做流射的处理清洗然后要投入多少的成本去存储以及说看到这些所谓的底层的span对问题排查的帮助到底是大还是不大然后另一方面EBPF和传统的应用程序SDK买点它的可见范围是不一样的应用里面有些可以简单买点的地方EBPF可能会需要花费很大的代价才能够去实现所以我们觉得EBPF和手动插装它其实有很多重叠的领域但是也有少数自己擅长的地方所以我们或者说社区在做的事情就在这些重叠的领域里面尽可能地去利用他们实现零插装没有感知的插装最终去提高微服务的一些可观测性说到自动买点的话可能在夹带一点点私货前面说的EBPF其实更像是我们平台方在所有机器上都会不属于A卷去覆盖的它并不是业务应用应该去做的如果业务应用团队想实现类似的效果比如说像java里面有成熟的字节码插装的方案了而购语员一条就是我们刚刚提过的EBPF的例子的路子我们前面讲过然后另一种方案我们看到Skywalking社区在做的是混合编译和代码生成它解决的问题是第一 你不用去改代码它帮你插装它在编译的时候直接帮你把这些额外的代码加进去然后第二个是不需要显示的context传递我们知道购语员里面很多方法的第一个参数都是context参数它会包含一些Trace的信息如果我们有一些业务应用它写了很多年它最早的时候很多方法都没有加这个参数你让它改是非常难的Skywalking会在编译的时候可以就是实现了就是它的agent会帮你完成这个事情让你在同一个协成的任何位置都可以拿到这个Trace的上下文也是推荐感兴趣的做业务应用的同学去了解一下他们的解决方案然后最后的最后Otel是CNCF托管项目里面活液度仅次于Kubernetes的项目所以它有着很好的社区氛围在可观测试方向如我们前面所说能做的事情也很多所以会希望大家能够发挥想象力在社区里面多多交流采样也好或者其他方面的一些想法那就不耽误大家吃饭的时间以上就是我今天的分享内容然后会留一点点时间Q&A也欢迎通过这里的联系方式线上的交流后续Q&A或者说分享的PBT 文字稿等等也都会丢到这个地址看一下线上的同学有没有想交流的问题你好就是我关注OpenTallimetry这个点就是我是从原原生的安全的角度去关注的就是说未来的话包括它的一个采集力度和一个因为它会采集到Metrix Logs还有所谓的我们Spam它这种数据的它的消费能力有没有说在安全这一个领域内有一个社区或者单独的一个发展的情况了解这位同学的问题是OpenTallimetry在安全这一块有没有终点去关注或者说成立一些社区或者说这个之类的那因为OpenTallimetry它确实很大所以我首先第一个我肯定是不会完全的去了解所有东西的然后第二个在我个人来看OpenTallimetry最近可能最近半年在哪些地方会花费更多的实验经历呢因为OpenTallimetry最早做的时候是先针对Trace做的然后它现在在做的事情包括Magics和Log这两个东西都还是非常不完善的所以我们会看到很多成员的一些讨论都还是在围绕这两个点以及怎么样去比如说用一些Connect或者说Promise里面的Example去打通Trace和Magics之类的事情那在安全这一块呢以我个人现在的印象可能还没有这么早的去投入大量的资源去做或者说大量的关注这个事情非常感谢OK那可能讲得比较简单大家没有太多的问题后续有问题的话也可以接着去提问那就谢谢大家今天来到我的Session