/s/1HuEUiKfxjrydNzIOg0xv3A 提取码:qa98
随着微服务架构的流行,服务按照不同的维度进行拆分,一次请求往往需要涉及到多个服务。
互联网应用构建在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发、可能使用不同的编程语言来实现、有可能布在了几千台服务器,横跨多个不同的数据中心。
因此,就需要一些可以帮助理解系统行为、用于分析性能问题的工具,以便发生故障的时候,能够快速定位和解决问题。
全链路监控组件就在这样的问题背景下产生了。最出名的是谷歌公开的论文提到的 Google Dapper。
想要在这个上下文中理解分布式系统的行为,就需要监控那些横跨了不同的应用、不同的服务器之间的关联动作。
所以,在复杂的微服务架构系统中,几乎每一个前端请求都会形成一个复杂的分布式服务调用链路。
一、为什么要进行全链路监控
在微服务架构中,服务会被拆分成多个模块,这些模块可能由不同的开发团队开发、维护,也可能使用不同的编程语言来实现、也有可能分布在多台服务器上,由于服务的拆分,单个用户的请求会经过多个微服务,相互之间形成复杂的调用关系,传统的监控手段已经不能实现如此复杂的链路之间的监控了,因此,就需要一些可以帮助理解系统行为、用于分析性能问题的工具,以便发生故障的时候,能够快速定位和解决问题。
二、全链路监控能解决哪些问题
1. 请求链路追踪,故障快速定位:可以通过调用链结合业务日志快速定位错误信息。
2. 可视化: 各个阶段耗时,进行性能分析。
3. 依赖优化:各个调用环节的可用性、梳理服务依赖关系以及优化。
4. 数据分析,优化链路:可以得到用户的行为路径,汇总分析应用在很多业务场景。
三、随着现代应用微服务化,客户端的请求往往需要服务器端多个组件的协调工作。
事务的处理是由分布式的服务架构完成,在这个过程中,问题的定位变得较为困难,我们需要梳理组件之间的依赖,并准确定位到问题所在。
这时候我们需要借助一些手段实现问题的定位和跟踪。
通常的做法有两种:
静态链路拓扑绘制
在系统交付之前,我们需要对系统的各个组件及相互关系有个比较清晰的认识,能够绘制并展示各个模块的调用关系。
通过挥着组件链路拓扑能够帮助我们从理性的角度白盒方式定位问题。
这个思路适合于业务开发团队,因为自己对自己的系统有足够清晰的认识,能够更快速定位问题。
动态链路跟踪
通过在日志中添加traceID的方式跟踪调用关系。各个模块、组件运行过程中都使用同一个ID,这样方便可视化整个调用链路。
除了添加traceID这种针对单次request的定位能力,我们还可以添加模块标识。显式的勾勒出组件依赖关系。
不同组件通过特定的日志收集工具将日志汇总到ELK统一日志平台实现检索。
四、实现步骤
再请求 Header 中打上标签,例如再 Header 中添加 "gray-tag: true" ,其表示要进行灰度测试(访问灰度服务),而其他则访问正式服务。
在负载均衡器 Spring Cloud LoadBalancer 中,拿到 Header 仲的 "gray-tag" 进行判断,如果此标签不为空,并等于"true" 的话,表示要访问灰度发布的服务,否则只访问正式的服务。
在网关 Spring Cloud Gateway 中,将 Header 标签 "gray-tag:true" 继续往下一个调用服务中传递。
在后续的调用服务中,需要实现两个关键功能:
● 在负载均衡器 Spring Cloud LoadBalancer 中,判断回复发布标签,将请求分发到对应服务
● 将灰度发布标签继续传递给下一个调用的服务.如此反复传递
五、全链路追踪组件追踪的数据遵循的规则:
1,Span:基本单元;
执行一次服务调用就生成一个span,用于记录当时的情况 ,以一个64位ID作为唯一标识.span还有其他数据标识如摘要,时间戳信息,关键tag等;
2,Trace:一次请求;
以一个64位ID为唯一标识,可以是一个业务号,通过该ID标识多个span为同一个业务请求,会以一个树状图的形式展示服务的调用;
3,Annotation:注解;
代表调用的客户端和服务端的行为,
Cs :客户端发起一个服务调用,即span的开始
Sr:服务端获取请求信息,并开始处理,sr-cs的时间得到一个时间戳即网络延迟时间;
Ss:服务端处理完请求,将结果返回客户端 ss-sr 的时间得到一个时间戳,即服务端处理请求的所用时间;
Cr:客户端成功接收到服务端的恢复,cr-cs得到的时间戳即客户端从服务端获取响应的时间;
六、其他业务代码
① user-service 模块的 controller
import com.example.userservice.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private OrderService orderService;
@RequestMapping("/getname")
public String getName() {
String result = orderService.getOrder();
return "正式版:User Service getName." +
result;
}
}
有疑问加站长微信联系(非本文作者)