全链路设计与实践

简介:

image

背景

随着沪江业务的高速发展,公司服务之间的调用关系愈加复杂,如何理清并跟踪它们之间的调用关系就显的比较关键。线上每一个请求会经过多个业务系统,并产生对各种缓存或者 DB 的访问,但是这些分散的数据对于问题排查,或者流程优化提供的帮助有限。在这样复杂的业务场景下,业务流会经过很多个微服务的处理和传递,我们难免会遇到这些问题:

  • 一次请求的流量从哪个服务而来? 最终落到了哪个服务中去?
  • 为什么这个请求这么慢? 到底哪个环节出了问题?
  • 这个操作需要依赖哪些东西? 是数据库还是消息队列? Redis挂了,哪些业务受影响?

设计目标

  • 低消耗性:跟踪系统对业务系统的影响应该做到足够小。在一些高度优化过的服务,即使一点点损耗也容易察觉到,而且有可能迫使在线负责的部署团队不得不将跟踪系统关停
  • 低侵入性:作为非业务组件,应当尽可能少侵入或者无侵入业务系统,对于使用方透明,减少开发人员的负担
  • 时效性:从数据的收集产生,到数据计算处理,再到最终展现,都要求尽可能快
  • 决策支持:这些数据是否能在决策支持层面发挥作用,特别是从 DevOps 的角度
  • 数据可视化:做到不用看日志通过可视化进行筛选

实现功能

  • 故障定位:调用链路跟踪,一次请求的逻辑轨迹可以完整清晰的展示出来。
  • 性能分析:调用链的各个环节分别添加调用耗时,可以分析出系统的性能瓶颈,并针对性的优化。
  • 数据分析:调用链是一条完整的业务日志,可以得到请求的行为路径,汇总分析应用在很多业务场景

设计思路

对于上面那些问题,业内已经有了一些具体实践和解决方案。通过调用链的方式,把一次请求调用过程完整的串联起来,这样就实现了对请求链路的监控。

在业界,目前已知的分布式跟踪系统,比如「Twitter Zipkin 与淘宝鹰眼」,设计思想都是来自 Google Dapper 的论文 「Dapper, a Large-Scale Distributed Systems Tracing Infrastructure」

典型分布式调用过程

image

图1:这个路径由用户的X请求发起,穿过一个简单的服务系统。用字母标识的节点代表分布式系统中的不同处理过程。

分布式服务的跟踪系统需要记录在一次特定的请求后系统中完成的所有工作的信息。举个例子,图1展现的是一个和5台服务器相关的一个服务,包括:前端(A),两个中间层(B和C),以及两个后端(D和E)。当一个用户(这个用例的发起人)发起一个请求时,首先到达前端,然后发送两个 RPC 到服务器 B 和 C 。B 会马上做出反应,但是 C 需要和后端的 D 和 E 交互之后再返还给 A ,由 A 来响应最初的请求。对于这样一个请求,简单实用的全链路跟踪的实现,就是为服务器上每一次你发送和接收动作来收集与跟踪

调用链路关系图

image

cs - CLIENT_SEND,客户端发起请求
sr - SERVER_RECIEVE,服务端收到请求
ss - SERVER_SEND,服务端处理完成,发送结果给客户端
cr - CLIENT_RECIEVE,客户端收到响应

技术选型

公司 选项 是否开源 优缺点
淘宝 EagleEye 主要基于内部 HSF 实现,HSF 没有开源,故鹰眼也没有开源
Twitter Zipkin 基于 Http 实现,支持语言较多,比较适合我们公司业务
点评 CAT 自定义改造难度大,代码比较复杂,侵入代码,需要埋点
京东 Hydra 主要基于 Dubbo 实现,不适合公司 Http 请求为主的场景

综上,考虑到公司目前以 Http 请求为主的场景,最终决定采用参考 Zipkin 的实现思路,同时以 OpenTracing 标准来兼容多语言客户端

系统设计

整体架构图及说明

image

一般全链路跟踪系统主要有四个部分:数据埋点、数据传输、数据存储、查询界面

数据埋点

  • 通过集成 SDK 到沪江统一开发框架中,进行低侵入性的数据收集
  • 采用 AOP 切面方式,将收集的数据存储在本地线程变量 ThreadLocal 中,对应用透明
  • 数据记录 TraceId、事件应用、接口、开始时间、耗时
  • 数据采用异步线程队列的方式发送到 Kafka 队列中,减少对业务的影响

目前支持的中间件有:

  • Http 中间件
  • Mysql 中间件
  • RabbitMQ 中间件

数据传输

我们在 SDK 与后端服务之间加了一层 Kafka ,这样做既可以实现工程解耦,又可以实现数据的延迟消费,起到削峰填谷的作用。我们不希望因为瞬时 QPS 过高而导致数据丢失,当然为此也付出了一些实效性上的代价。

Kafka Manager 展示

image

数据存储

数据存储采用 ElasticSearch ,主要存储 Span 与 Annotation 相关的数据,考虑到数据量的规模,先期只保存最近 1 个月的数据。

ELasticSearch Head 数据

image

查询界面

通过可视化 Web 界面来查询分布式调用链路,同时还提供根据项目维度分析依赖聚合

查询页面

image

Trace 树

image

依赖分析

image

遇到的一些坑

Web 页面加载超时

问题

使用 Zipkin 官网 UI 的时候,会偶发性的出现业务加载超时。

解决方案

原因是 Zipkin 加载页面的时候会一次性加载该项目里面所有的 Span ,当项目使用 Restful 形式的 API 时,就会产生几百万的 Span。最后,我们重写 UI 页面采用懒加载的方式,默认展示最近 10 条 Span,同时支持输入字符来动态查询 Span 的功能。

Span 堆积过多

image

问题

当使用页面查询 Trace 的时候,发现某个链路堆积到上千条 Span

解决方案

排查下来,业务方使用 HttpClient 中间件发送 Http 请求超时的时候,SDK 并未拦截超时对应的异常,导致事件一直在存储在线程对应的 ThreadLocal 中

总结

全链路跟踪系统关键点:调用链。

每次请求都生成全局唯一的 TraceID,通过该 ID 将不同的系统串联起来。实现调用链跟踪,路径分析,帮助业务人员快速定位性能瓶颈,排查故障原因。

参考资料

目录
相关文章
|
移动开发 前端开发 JavaScript
做前端技术方案选型的时候,你是怎么做决策的?
做前端技术方案选型的时候,你是怎么做决策的?
167 0
|
7月前
|
设计模式 架构师 安全
如何提高自己的架构设计能力?
提升架构设计能力涉及深入学习基础知识、业务理解、技术广度与深度、实践经验等多方面。要关注代码的清晰结构、抽象能力、系统性能和可扩展性。学习编程语言、设计模式、系统设计原则和分布式系统是关键。通过实际项目和不断学习反思,可以增强架构设计技能。例如,上述代码展示了清晰的结构和设计原则应用。
394 0
|
7月前
|
存储 SQL 搜索推荐
业务系统架构实践总结
作者从2015年起至2022年,在业务平台(结算、订购、资金)、集团财务平台(应收应付、账务核算、财资、财务分析、预算)、本地生活财务平台(发票、结算、预算、核算、稽核)所经历的业务系统研发实践的一个总结。
|
SQL 消息中间件 存储
从理论到实践,实时湖仓功能架构设计与落地实战
实时湖仓是「实时计算」和「数据湖」的一种结合应用场景,并不是具体指一个产品模块。本文主要介绍了平台通过相关功能的设计,让数据开发可以更简单更直观地了解 Flink Catalog、数据湖、流批一体等概念,并在实际业务场景中更方便地去落地实践。
320 0
|
运维 负载均衡 Kubernetes
技术方案(开源方案)选型的考量和方法论
技术方案(开源方案)选型的考量和方法论
|
存储 缓存 边缘计算
架构师的视角进行全链路系统性能的优化
一、前端优化 前端的优化主要有三个环节:减少请求次数、页面静态化、边缘计算 减少请求次数:减少前端脚本与后端服务的请求次数,有三种方案 (1)增加缓存控制:前端开发经常设置HTML的缓存控制头部(Cache-Control头),这样浏览器在请求同一个文件的时候,只访问本地保存的资源副本,从而加速文件的访问速度。
127 0
|
JavaScript Serverless 定位技术
从业务开发中学习和理解架构设计
在设计代码目录划分方案的过程中,看了一些工程结构设计的资料,读了一些关于架构设计的书,对于架构有了一些理解。本文是对这段学习和任务完成过程的思考和沉淀。希望能够解答“架构到底是什么?架构和业务之间的关系?”,“好的架构的设计出发点是什么?好的架构应该是什么样的?”这几个问题。
从业务开发中学习和理解架构设计
|
存储 运维 监控
业务全链路追踪最佳实践|学习笔记
快速学习业务全链路追踪最佳实践
业务全链路追踪最佳实践|学习笔记
|
数据可视化 数据挖掘 大数据
方案_技术方案|学习笔记
快速学习方案_技术方案
176 0
方案_技术方案|学习笔记