31.【学习心得】学习心得-全链路日志

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 【学习心得】学习心得-全链路日志

文档参考:书名:《从程序员到架构师:大数据量、缓存、高并发、微服务、多团队协同等核心场景实战》-王伟杰

image.png

前文如下:


23.【学习心得】学习心得-冷热分离概述

24.【学习心得】学习心得-如何分离冷热数据

25.【学习心得】学习心得-基于MySQL的分表分库

26.【学习心得】学习心得-读缓存

27.【学习心得】学习心得-如何更新redis缓存

28.【学习心得】学习心得-写缓存

29.【学习心得】学习心得-写缓存实现思路

30.【学习心得】学习心得-秒杀架构


1.全链路日志

1.1 业务场景:这个请求到底经历了什么


当时公司的某一个业务线本来是基于自研的微服务架构,刚刚迁移到Spring Cloud。因为公司原来的微服务架构是基于ZooKeeper做注册发现的,为了复用原来的中间件,迁移到Spring Cloud后,服务的注册发现基于Spring Cloud ZooKeeper实现,不过组件方面只使用了Spring Cloud的服务间调用(Feign)。


迁移到微服务后,就得考虑日志跟踪的事情了。


之前只是简单地把日志打印到本地文件上,然后使用ELK(ElasticSearch、Logstash和Kibana)进行日志收集和分析,因此日志记录比较随意,且没有形成一个统一的规范。


没有统一的规范,在做线上问卷调查的时候,难度非常大。比如有一次碰到了某一个用户总是登录失败的问题。服务调用链路是这样的:UserAPI→AuthService→UserService在UserAPI中还能找到登录信息,因为日志里面打印出了用户名,而后根据相应的时间点可以找到线程ID,那么这个时间点的这个线程ID下所有的日志就都属于要跟踪的活动了


但是要去AuthService查找这个请求的下一个服务的日志时就复杂了。因为同一时间点有多个服务器节点,每个节点有多个线程ID在活动,所以无法判断哪个服务器节点的哪个线程ID是用来处理UserAPI中在调查的那次请求的


那怎么办?等没流量的时候运维人员又重试了几次,最终才定位到AuthSer vice中相应的日志。后来调查到的问题根源是,UserAPI调用AuthService的时候,有个参数因为含有特殊字符而被Tomcat自动摒弃了,导致AuthService收不到那个参数的值。


项目组商量后,决定把日志进一步规范化,于是总结了以下3点需求。

1)记录什么时候调用了缓存、MQ、ES等中间件,在哪个类的哪个方法中耗时多久。
2)记录什么时候调用了数据库,执行了什么SQL语句,耗时多久。
3)记录什么时候调用了另一个服务,服务名是什么,方法名是什么,耗时多久。


一般来说,一个请求会跨多个服务节点,针对这种情况又梳理了两条重要需求。

1)把同一个请求在全部服务中的以上所有记录进行串联,最终实现一个树状的记录。

2)设计一个基于这些基础数据的查询统计功能。


网络异常,图片无法展示
|


需求确定后,就需要选择一款合适的开源技术进行方案实现,这就涉及技术选型过程。


2.技术选型


在进行技术选型时,可以对照表9-1中的全链路日志中间件对比。


网络异常,图片无法展示
|


2.1 日志数据结构支持OpenTracing


平时日志行都是独立记录的,只能通过线程ID把它们关联起来。因此需要一个数据结构把每个请求在全部服务中的相关日志关联起来。


目前已经有一种比较通用的全链路数据格式——OpenTracing,它的标准和API是由一个开源组织Cloud Native Computing Foundation(云原生计算基金会)进行维护的.

OpenTracing通过提供一个与平台/厂商无关的API,使得开发人员能够更方便地添加(或更换)追踪系统,这样即使之前引入的全链路日志不好用,以后想换掉也是非常方便的。


接下来解释一下OpenTracing标准,它主要包含两个概念:一个是Trace,一个是Span。

网络异常,图片无法展示
|


从图9-3中可以看到一个客户端调用Order API的请求时经历的整个流程

(①⑩),即一个Trace;Order API调用了Produc Service的整个过程(②⑤),

这就是一个Span。每个Span代表Trace中被命名且被计时的连续性执行片段。


通过图9-3还能发现,Span中又包含了一个子Span,比如调用Product Service的过程中,Product Service会访问一次数据库(③④),这也是一个Span。因此可以得出,一个Span可以包含多个子Span,而Span与Span之间的关系就叫Reference。


2.2 支持Elasticsearch作为存储系统


诚然,因为流量大的原因,导致记录的日志数据量也很大,这就要求存储这些日志的系统必须支持海量数据且保证查询高效。最终,因为公司运维人员对Elasticsearch比较熟悉,所以提出可以使用Elasticsearch对日志进行存储。


2.3 保证日志的收集对性能无影响


当服务在记录日志时,需要确保日志的记录与收集对服务器的性能不会产生影响。比如之前调研过Pinpoint,当服务在记录日志时,Pinpoint的并发数达到一定数量时整体吞吐量少了一半,对服务器的性能影响很大,这是不能接受的。


2.4 查询统计功能的丰富程度


一般来说,查询统计功能越丰富越好,但必须首先满足一个基础功能:支持每个请求树状结构的全链路日志(如图9-4和图9-5所示),比如SkyWalking的功能就非常适用。查询统计系统除了满足基本功能以外,也要实现监控报警、指标统计等功能,以此帮助减轻二次开发的工作量。如何以最小的业务代码侵入性引入这些功能?


项目组希望日志数据的收集过程对写业务代码的人保持透明,因此,一种比较理想的解决方案是使用Java的探针,通过字节码加强的方式进行埋点。 不过,这种方式对系统性能也会产生一定影响。

而且在实际业务中,公司都会把访问数据库、Redis、MQ的代码进行封装,无法通过字节码加强的方式实现埋点,就只能尝试在封装的代码中实现,这样对开发业务代码的人来说同样透明


2.5 最终选择


根据以上问题剖析及性能测试结果分析,可以发现SkyWalking比较符合需求。

项目组做性能测试时发现,对于500线程压力以下的服务,是否使用SkyWalking对其吞吐量影响不大,一般相差不超过10%。SkyWalking官方测试报告中也提到:假如有500个并发用户,每个用户的每次请求间隔是10毫秒,TPS基本没什么变化,如图9-6所示。


网络异常,图片无法展示
|


3.注意事项


3.1 SkyWalking的数据收集机制


中间件在收集日志的时候,不可能是同步的。为什么呢?如果每次记录日志都要发一个请求到中间件,等中间件返回结果以后,才算日志记录完成,进入下一个动作,那么这个请求的响应时间肯定变慢。而且这种情况下,业务系统和日志系统是耦合的,业务系统要保证绝对高可用,而日志系统只是用来为研发人员调研问题提供方便的,对可用性的要求没有那么高。也不可能让高可用的系统依赖中可用的系统。


所以这个日志收集的过程必须是异步的,和业务流程解耦


**SkyWalking的数据收集机制是这样的:服务中有一个本地缓存,把收集的所有日志数据先存放在这个缓存中,然后后台线程通过异步的方式将缓存中的日志发送给SkyWalking服务端。**这种机制使得在日志埋点的地方无须等待服务端接收数据,也就不影响系统性能。


3.2 如果SkyWalking服务端宕机了,会出现什么情况


如果服务端宕机了,理论上日志缓存中的数据会出现没人消费的情况,这样会不会导致数据越积越多,最终超出内存呢?在SkyWalking中会设置缓存的大小,如果这部分数据超出了缓存大小,Trace不会保存,也就不会超出内存了。


3.3 流量较大时,如何控制日志的数据量


流量大时,不可能收集每个请求的日志,否则数据量会过大。那SkyWalking如何控制采样比例呢?SkyWalking会在每个服务器上配置采样比例,比如设置为100,代表1%的请求数


网络异常,图片无法展示
|


样就可以通过sampleRate来控制采样比例了。一般而言,流量越大,采样比例越小。 不过,这里有两点需要特别注意。


1)一旦启用forceSampleErrorSegment,出现错误时就会收集所有的数据,此时sampleRate对出错的请求不再适用。


2)所有相关联服务的sampleRate最好保持一致,如果A调用B,然后A、B的采样比例不一样,就会出现一个Trace串不起来的情况。


3.4 日志的保存时间

一般来说,日志不需要永久保存,通常是保存3个月的数据,关于这一点大家结合公司的实际情况进行配置即可。按照以前的设计方案,需要自己设计一个工具将数据进行定时清理,不过此时可以直接使用SkyWalking进行配置,代码如下所示。


网络异常,图片无法展示
|


3.5 集群配置:如何确保高可用


先来看看SkyWalking官方文档给出的SkyWalking架构,如图9-7所示。在此架构中,需要关注SkyWalking的收集服务(Receiver)和聚合服务(Aggregator),它们支持集群模式。同时,在集群服务里,多个服务节点又需要一些协调服务来协调服务间的关系,它们支持Kubernetes、ZooKeeper、Consul、etcd、Nacos(开源的协调服务基本都支持)。


网络异常,图片无法展示
|



相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
3月前
|
存储 Go
Go 浅析主流日志库:从设计层学习如何集成日志轮转与切割功能
本文将探讨几个热门的 go 日志库如 logrus、zap 和官网的 slog,我将分析这些库的的关键设计元素,探讨它们是如何支持日志轮转与切割功能的配置。
108 0
Go 浅析主流日志库:从设计层学习如何集成日志轮转与切割功能
|
4月前
|
Kubernetes 容器
k8s学习-CKS真题-日志审计 log audit
k8s学习-CKS真题-日志审计 log audit
79 0
|
4月前
|
存储 缓存 关系型数据库
认真学习MySQL的事务日志-Redo日志
认真学习MySQL的事务日志-Redo日志
44 0
|
4月前
|
存储 监控 数据可视化
小白带你学习linux的ELK日志收集系统
小白带你学习linux的ELK日志收集系统
163 0
|
7月前
|
关系型数据库 物联网 PostgreSQL
沉浸式学习PostgreSQL|PolarDB 11: 物联网(IoT)、监控系统、应用日志、用户行为记录等场景 - 时序数据高吞吐存取分析
物联网场景, 通常有大量的传感器(例如水质监控、气象监测、新能源汽车上的大量传感器)不断探测最新数据并上报到数据库. 监控系统, 通常也会有采集程序不断的读取被监控指标(例如CPU、网络数据包转发、磁盘的IOPS和BW占用情况、内存的使用率等等), 同时将监控数据上报到数据库. 应用日志、用户行为日志, 也就有同样的特征, 不断产生并上报到数据库. 以上数据具有时序特征, 对数据库的关键能力要求如下: 数据高速写入 高速按时间区间读取和分析, 目的是发现异常, 分析规律. 尽量节省存储空间
611 1
|
4月前
|
Kubernetes 监控 容器
k8s学习-CKA真题-监控Pod日志
k8s学习-CKA真题-监控Pod日志
78 0
|
6月前
|
Java 测试技术 Docker
Spring Boot 学习研究笔记(十九)-docker部署SpringBoot 日志目录挂载
Spring Boot 学习研究笔记(十九)-docker部署SpringBoot 日志目录挂载
270 0
|
1天前
|
SQL 监控 关系型数据库
【MySQL学习】MySQL的慢查询日志和错误日志
【MySQL学习】MySQL的慢查询日志和错误日志
|
6天前
|
运维 监控 前端开发
[SpringAop + Logback +MDC] 现网必备全链路日志追踪
[SpringAop + Logback +MDC] 现网必备全链路日志追踪
|
7天前
|
监控 Docker 容器
Docker从入门到精通:Docker log 命令学习
了解 Docker 日志管理对容器监控至关重要。`docker logs` 命令用于查看和管理容器日志,例如,`docker logs <container_name>` 显示容器日志,`-f` 或 `--follow` 实时跟踪日志,`--tail` 显示指定行数,`--timestamps` 添加时间戳,`--since` 按日期筛选。Docker 支持多种日志驱动,如 `syslog`,可通过 `--log-driver` 配置。有效管理日志能提升应用程序的稳定性和可维护性。
11 0