业务场景
公司的微服务刚刚迁移到 Spring Cloud,服务的注册发现基于 Spring Cloud ZooKeeper 实现,不过组件方面只使用了 Spring Cloud 的服务间调用(Feign)。迁移到微服务后,就得考虑日志跟踪的事情了
之前我们只是简单地把日志打印到本地文件上,然后使用 ELK 进行日志收集、分析,因此日志记录比较随意且没有形成一个统一的规范,后来决定把日志进一步规范化,于是提出了如下 3 点需求
- 记录什么时候调用了缓存/MQ/ES 等中间件,在哪个类的哪个方法中耗时多久/li>
- 记录什么时候调用了数据库,执行了什么 SQL,耗时多久/li>
- 记录什么时候调用了另一个服务,服务名是什么法名是什么时多久/li>
一般来说,一个请求会跨多个服务节点,针对这种情况又梳理了 2 条重要需求
- 把同一个请求在全部服务的以上所有记录进行串联,最终实现一个树状的记录
- 设计一个基于这些基础数据的查询统计功能
技术选型
在技术选型时,可以对照下方给出的一个知名框架的对比表,如下表所示
在上表中发现,可供选择的系统太多了,我们该如何选择呢终得出了如下标准
1.日志数据结构支持 OpenTracing
平时日志行都是独立记录的,只能通过线程 id 把它们关联起来。因此我们需要一个数据结构把每个请求在全部服务的相关日志关联起来,而目前市面上已经有 1 个比较通用的全链路数据格式—— OpenTracing,它的标准和 API 是由一个开源的组织(Cloud Native Computing Foundation 云原生计算基金会孵化)进行维护,这个开源组织也包含了一些全链路日志系统的维护者
OpenTracing 通过提供一个与平台/厂商无关的 API,使得开发人员能够更方便地添加(或更换)追踪系统。这样就算之前引入的全链路日志不好用,以后想再换掉也是超级方便
OpenTracing 标准,它主要包含两个概念:一个是 Trace,一个是 Span。先来看看下面的例子,如下图所示
在上图中,看到一个客户端调用 Order API 的请求时经历的整个流程(1 到 10),即 1 个 Trace,之后它又调用了 Product Service 的整个过程(2 到 5),这就是 1 个 Span,每个 Span 代表 Trace 中被命名且被计时的连续性执行片段
通过上图我们还发现,Span 中又包含了一个子 Span,比如调用 Product Service 的过程中,Product Service 会访问一次数据库(3 到 4),这也是一个 Span。因此,我们可以得出一个 Span 可以包含多个子 Span,而 Span 与 Span 之间的关系就叫 Reference
在技术选型时,必须保证系统的可替代性,尽量别在一项开源技术上绑死。所以这次选型坚决使用基于 OpenTracing 的日志系统
2.支持 Elasticsearch 作为存储系统
因为流量大的原因,导致我们记录的日志数据量也很大,这就要求存储这些日志的系统必须支持海量数据且保证查询高效。发现Elasticsearch很符合这种需求,所以提出使用 Elasticsearch 对日志进行存储
3.保证日志的收集对性能无影响
当服务正在记录日志,我们需要确保日志的记录与收集对服务器的性能不会产生影响。
比如之前调研过 Pinpoint,当服务正在记录日志,Pinpoint 的并发数达到了一定数量且整体吞吐量少了一半,对服务器的性能影响很大,这肯定不行
4.查询统计功能的丰富程度
一般来说,查询统计的功能越丰富越好,但必须首先满足一个基础功能:支持每个请求树状结构的全链路日志,比如 SkyWalking 的功能就非常适用
查询系统除了满足基本功能以外,也想实现监控 警、指标统计等功能,以此帮助减轻一堆二次开发的工作量
5.如何以最小的业务代码侵入性引入系统
希望日志数据的收集过程对写业务代码的人保持透明,因此,最理想的解决方案是使用 Java 的探针,通过字节码加强的方式进行埋点。不过,这种方式对系统性能也会产生一定影响
而且在实际业务中,公司都会把对数据库、Redis、MQ 访问的代码进行封装,我们无法通过字节码加强的方式实现埋点,只能尝试在封装的代码中实现埋点了,这样对开发业务代码的人来说同样透明
6.客户案例
技术选型时,往往还需要了解哪些知名公司使用了这个技术,因为大公司的业务场景相对复杂些,提前踩的坑较多,一个技术如果被很多公司都使用过了,那我们使用起来也就会平稳很多
7.最终选择
根据以上问题的剖析及性能测试结果的分析,发现 SkyWalking 比较符合需求
在 SkyWalking 官方测试 告中提道:假如有 500 个并发用户,每个用户的每次请求间隔是 10ms,TPS 基本没什么变化,如下图所示
技术选型时我们经常提到,不仅仅需要关注需求本身,还需要考虑组织或个人主观上的因素
注意事项
在安心使用 SkyWalking 之前,还需要注意如下 5 大注意事项
1. SkyWalking 的数据收集机制
SkyWalking 数据收集机制是这样的:服务中有一个本地缓存,我们把收集的所有日志数据先存放在这个缓存中,然后后台线程通过异步的方式将缓存中的日志发送给 SkyWalking 服务端。通过这种机制,在日志埋点的地方,无须等待服务端接收受数据,也就不影响系统性能
2. 如果 SkyWalking 服务端宕机了,会出现什么情况/strong>
如果服务端宕机了,理论上日志缓存中的数据会出现没人消费的情况,这样会不会导致数据越积越多,最终撑爆内存呢/p>
在 SkyWalking 中,我们会设置缓存的 size,如果这部分数据超出了缓存 size,Trace 不会保存,也就知道内存会不会撑爆了
3. 流量较大时,如何控制日志的数据量/strong>
流量大时,不可能收集每个请求的日志,这样数据量太大了。那 SkyWalking 如何控制采样比例呢/p>
SkyWalking 会在每个服务器上配置采样比例,比如设置为 100,代表 1% 的请求数据会被收集,如下代码所示
agent-analyzer:
default:
…
sampleRate: ${SW_TracE_SAMPLE_RATE:1000} # The sample rate precision is 1/10000. 10000 means 100% sample in default.
forceSampleErrorSegment: ${SW_FORCE_SAMPLE_ERROR_SEGMENT:true} # When sampling mechanism activated, this config would make the error status segment sampled, ignoring the sampling rate.
这样,我们就可以通过 sampleRate 控制采样比率了,一般而言,流量越大,采样比例越小
不过,这里有 2 点你需要特别注意
- 一旦启用 forceSampleErrorSegment ,出现错误时所有的数据全部会收集,此时 sampleRate 对出错的请求不再适用
- 所有相关联服务的 sampleRate 最好保持一致,如果 A 调用 B,然后 A、B 的采样率不一样,就会出现一个 Trace 串不起来的情况
4. 日志的保存时间
一般来说,日志不需要永久保存,通常我们是保存 3 个月的数据,关于这点大家结合公司的实际情况进行配置即可
按照以前的设计方案,需要自己设计一个工具将数据进行定时清理,不过此时我们可以直接使用 SkyWalking 进行配置,如下代码所示
# Set a timeout on metrics data. After the timeout has expired, the metrics data will automatically be deleted.
recordDataTTL: ${SW_CORE_RECORD_DATA_TTL:3} # Unit is day
metricsDataTTL: ${SW_CORE_METRICS_DATA_TTL:7} # Unit is day
5. 集群配置:如何确保高可用/strong>
先来看看 SkyWalking 的架构
在以上架构中,需要关注 SkyWalking 的收集服务(Receiver)和聚合服务(Aggregator),它们支持集群模式。同时呢,在集群服务里,多个服务节点又需要一些协调服务来协调服务间的关系,它们支持 Kubernetes-ZooKeeper、Consul、Etcd、Nacos
文章知识点与官方知识档案匹配,可进一步学习相关知识云原生入门技能树首页概览8665 人正在系统学习中
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!