正文
文:老曹
本文原创,转载请注明作者及出处
背景
随着沪江业务的高速发展,公司服务之间的调用关系愈加复杂,如何理清并跟踪它们之间的调用关系就显的比较关键。线上每一个请求会经过多个业务系统,并产生对各种缓存或者 DB 的访问,但是这些分散的数据对于问题排查,或者流程优化提供的帮助有限。在这样复杂的业务场景下,业务流会经过很多个微服务的处理和传递,我们难免会遇到这些问题:
设计目标
-
低消耗性:跟踪系统对业务系统的影响应该做到足够小。在一些高度优化过的服务,即使一点点损耗也容易察觉到,而且有可能迫使在线负责的部署团队不得不将跟踪系统关停
-
低侵入性:作为非业务组件,应当尽可能少侵入或者无侵入业务系统,对于使用方透明,减少开发人员的负担
-
时效性:从数据的收集产生,到数据计算处理,再到最终展现,都要求尽可能快
-
决策支持:这些数据是否能在决策支持层面发挥作用,特别是从 DevOps 的角度
-
数据可视化:做到不用看日志通过可视化进行筛选
实现功能
-
故障定位:调用链路跟踪,一次请求的逻辑轨迹可以完整清晰的展示出来。
-
性能分析:调用链的各个环节分别添加调用耗时,可以分析出系统的性能瓶颈,并针对性的优化。
-
数据分析:调用链是一条完整的业务日志,可以得到请求的行为路径,汇总分析应用在很多业务场景
设计思路
对于上面那些问题,业内已经有了一些具体实践和解决方案。通过调用链的方式,把一次请求调用过程完整的串联起来,这样就实现了对请求链路的监控。
在业界,目前已知的分布式跟踪系统,比如「Twitter Zipkin 与淘宝鹰眼」,设计思想都是来自 Google Dapper 的论文 「Dapper, a Large-Scale Distributed Systems Tracing Infrastructure」
典型分布式调用过程
1:这个路径由用户的X请求发起,穿过一个简单的服务系统。用字母标识的节点代表分布式系统中的不同处理过程。
分布式服务的跟踪系统需要记录在一次特定的请求后系统中完成的所有工作的信息。举个例子,图1展现的是一个和5台服务器相关的一个服务,包括:前端(A),两个中间层(B和C),以及两个后端(D和E)。当一个用户(这个用例的发起人)发起一个请求时,首先到达前端,然后发送两个 RPC 到服务器 B 和 C 。B 会马上做出反应,但是 C 需要和后端的 D 和 E 交互之后再返还给 A ,由 A 来响应最初的请求。对于这样一个请求,简单实用的全链路跟踪的实现,就是为服务器上每一次你发送和接收动作来收集与跟踪
调用链路关系图
-
cs
- CLIENT_SEND,客户端发起请求
-
sr
- SERVER_RECIEVE,服务端收到请求
-
ss
- SERVER_SEND,服务端处理完成,发送结果给客户端
-
cr
- CLIENT_RECIEVE,客户端收到响应
技术选型
综上,考虑到公司目前以 Http 请求为主的场景,最终决定采用参考 Zipkin 的实现思路,同时以 OpenTracing 标准来兼容多语言客户端
系统设计
整体架构图及说明
一般全链路跟踪系统主要有四个部分:数据埋点、数据传输、数据存储、查询界面
数据埋点