关于「日志采样」的一些思考及实践

京东云开发者
• 阅读 280

一、背景: 系统日志可用于追踪用户操作轨迹,异常情况下,合理的日志有助于快速排查、定位问题,毫无疑问,打印日志对于系统是很重要的。

当业务规模较小时,大家都倾向于享受日志带来的便利,从而忽略日志带来的潜在的负面影响,缺乏对日志的管控。在JD当前用户量、业务规模下,绝大多数C端系统、甚至B端系统都是高吞吐的,毫无疑问,过大的日志量对系统的性能、磁盘IO有着显著负面影响,赶上大促时,问题尤为突出。日志在为我们提供便利的同时,也无时无刻成为一根刺,时不时刺我们一下。

作为一个共性问题,由于集团暂没推出统一的日志框架,不少团队都会尝试基于log4j、logback 进行轻度的封装,通过跟配置中心联动,增加一些诸如 '动态降级' 的功能、来缓解日志带来的负面影响。降级带来的效果是显著的,但同时也让系统丧失了记录 '操作轨迹' 的能力,从而又带来了新的问题。

此时,很容易想到,可以通过对 '请求' 采样,实现请求日志的采样输出,并通过控制采样比例平衡不同场景下日志对性能的影响,系统吞吐量较大时,降级采样比例,系统吞吐量较低时,提高采样比例。



二、正文: Ⅰ 在请求入口处,通过一定的采样算法,计算当前请求是否采样,并借助 Java 的 ThreadLocal 机制,可以实现当前请求线程的日志采样。但是,大部分关注日志性能的系统,往往处理逻辑也是复杂的,会有各样的异步运算逻辑,因此,大量的日志不一定来自请求线程,更多的可能来自子线程、线程池线程,甚至嵌套在线程池线程下的线程。

如何将请求线程、子线程、线程池线程统一协调起来,实现 '采样标识' 的跨线程透传,从而确保请求维度采样的一致性,是本文关注的重点,希望可以给大家提供一些思路、并附上我们业务场景下的具体案例。

(1) 可以像 Transmittable Thread Local 一样,通过对线程池类、或者任务类(Runnable、Callable)进行包装,将透传逻辑封装起来,JD内部比较典型的用法有 pfinder、jade。

必须承认,使用这种方式实现是有一定优势的,但是奈何现在各团队都有自己独特功能的线程池包装类,并已经在业务系统中广泛使用,如果此时再增加一个处理 '日志采样' 的包装,会出现嵌套包装的情况,这样会让程序变得混乱,增加理解成本,由于各包装实现之间缺乏磨合,甚至面临不可控的风险,这样做甚至有 '添乱' 的嫌疑,我认为至少在当前的环境下是不可取的。

(2)直接粗暴一些,在业务系统中,涉及子线程、线程池的地方,通过代码 '显式的' 将 '采样标识' 不断透传。

这样做是能达到目的的,但是,会有大量的逻辑代码和业务耦合的情况(线程池越多,业务越复杂,耦合越严重),虽然单系统改造量不大(当然,这个也是因系统而异),但是辐射面太广,需要各业务系统都要配合改造,同时有影响业务逻辑的风险,也不可取。

(3)将请求线程的控制逻辑跟具体业务解耦开来,封装为一个组件,并在组件中提供合适的 api,将组件复用于各业务系统,并根据业务系统具体情况,来决策是否使用 api 来处理异步线程(子线程、线程池线程的统一简称)的情况。

在没有特别合适的、集团级统一api的情况下,这是一种较为务实的做法,通过接入抽象组件来控制请求线程的日志采样,并通过扩展 api 来协调请求线程和异步线程的采样一致性,并根据业务系统的实际情况,来决策是否需要 '修改代码' 来协调异步线程。

① 如果业务系统中使用异步线程的处理逻辑较少,只接入组件,进行请求线程的日志采样即可

② 如果业务系统中大量使用异步线程做逻辑,可接入组件再针对必要的地方通过扩展 api 来协调请求线程和异步线程的采样一致性

除上述外,应该还有其他的办法,比如 AOP 机制,但是 AOP 只能到最低方法粒度,对于存量系统来说,改造量还是偏大,如果是新系统开发,可以考虑。

最后,上面的思考都是偏向全局的,在具体实现时,需要考虑、斟酌的细节还有很多、下面抛砖引玉列出一些,希望对大家拓展思路有所帮助!

① 采样的算法,是 '随机' 还是 '对 traceId 取模',然后通过配置中心控制取样比例

甚至跟入参关联起来,对特定场景(对哪个接口、方法,按什么规则进行入参筛选)进行采样,即所谓场景化采样

② 扩展 api 应该提供哪些功能,怎么封装能做到让业务应用改动量最少?

③ 怎么保证全局(包括异步线程日志)请求 traceId 的一致性,这方面其实 pfinder 也有方案可供参考

④ 采样比例的最小粒度,是 百分之一、千分之一、还是万分之一?

⑤ 整系统使用一个采样概率(即当前请求命中采样时,各级别都打),还是各级别分别设置(分别设置时还要考虑联动)

⑥ 通常,我们倾向于,如果需要对当前请求进行采样,可能 info、error 一块打,也可能只打 error,但是不太可能只打 info 不打 error,所以需要有一个策略去控制

⑦ 当大量 error 产生时,怎么收敛日志?控制打印速率?甚至可以晋级一步,将磁盘IO 和打印速率联动



三、实践: 促销交易这边目前恰好在做这方面相关的技术改造,通过在目前既存日志组件(通过 JD JSF 前置过滤器实现)基础上,实现请求线程的日志采样,并提供扩展 api 给业务系统,实现整体上请求维度的日志采样,从而尽可能的减少业务系统的改造,以下流程图描述了大致落地过程,供参考,有兴趣的可以评论区留言进一步探讨具体落地细节。





涉及异步线程时,使用扩展 api 改造也相对简洁:

// 改造前,线程池任务执行逻辑 threadPoolExecutor.execute(() -> "your business logic");

// 使用扩展 api 改造后,对 '线程池执行逻辑' 进行包装,实现 '采样标识' 的跨线程透传 threadPoolExecutor.execute(XxxUtils.wrap(() -> "your business logic")); 

作者:京东零售 卢吉欣

来源:京东云开发者社区 转载请注明来源

点赞
收藏
评论区
推荐文章
Bahar76 Bahar76
3年前
用 Go 写个日志监控系统
日志收集系统架构1.项目背景a.每个系统都有日志,当系统出现问题时,需要通过日志解决问题b.当系统机器比较少时,登陆到服务器上查看即可满足c.当系统机器规模巨大,登陆到机器上查看几乎不现实2.解决方案
Stella981 Stella981
2年前
Linux日志系统
一、Linux系统日志与分类内核及系统日志:这种日志数据由系统服务syslog统一管理,根据其主配置文件"/etc/syslog.conf"中的设置决定将内核消息及各种系统程序消息记录到什么位置。用户日志:这种日志数据用于记录Linux系统用户登录及退出系统的相关信息,包括用户名、登录的终端、登录
Stella981 Stella981
2年前
Kafka Consumer端的一些解惑
最近一直忙着各种设计和文档,终于有时间来更新一点儿关于kafka的东西。之前有一篇文章讲述的是kafkaProducer端的程序,也就是日志的生产者,这部分比较容易理解,业务系统将运行日志或者业务日志发送到broker中,由broker代为存储。那讲的是如何收集日志,今天要写的是如何获取日志,然后再做相关的处理。之前写过kafka是讲日志按照topic
Stella981 Stella981
2年前
ELK项目es+kibana+jdk配置问题
简介ELK需求背景业务发展越来越庞大,服务器越来越多各种访问日志、应用日志、错误日志量越来越多开发人员排查问题,需要到服务器上查日志,不方便运营人员需要一些数据,需要我们运维到服务器上分析日志说白了就是日志那么多我要给你们搞牛逼的系统如果有机会再搞日志系统加消息列队eskafka消化来的数据ELK包含Elasti
人间小土豆 人间小土豆
2年前
请问日志审计什么意思呢?
这里的“日志”和我们日常生活中的理解大有不同。什么是日志?简单的说,日志就是计算机系统、设备、软件等在某种情况下记录的信息。具体内容取决于日志的来源。例如:unix操作系统会记录用户登录和注销等信息的日志防火墙会记录访问控制协议acl通过和拒绝等消息的日志有些系统在用户登录时或者在系统本身认为会发生一些故障时发出带有告警信息的日志有些产品会在本身存储不足时发
Wesley13 Wesley13
2年前
Java日志系统 Commons
如何记录日志?商业应用系统一般是混合使用业务操作日志记录到数据库中,因为可能需要分析统计一般系统运行及异常日志可以用日志文件,因为可能无法连接数据库重要系统运行、安全及异常日志可以用系统日志,方便系统管理员查看Commonslogging:apache最早提供的日志的门面接口。所谓门面日志系统,是指它们本身并不实现具体的
京东云开发者 京东云开发者
4个月前
2024了,我不想再用AOP收集业务操作日志了 | 京东云技术团队
0.背景在近期的项目中,系统涉及到针对系统的业务操作日志统计功能,由于本系统位于业务链路的中心环节,负责接收上游系统的数据,并将基于用户操作产生的数据传递至下游系统,鉴于业务链路的复杂性和操作场景的多样性,我们计划通过对核心业务数据进行全生命周期的日志记录
京东云开发者 京东云开发者
4个月前
分布式日志追踪ID实战 | 京东物流技术团队
本文通过介绍分布式应用下各个场景的全局日志ID透传思路,以及介绍分布式日志追踪ID简单实现原理和实战效果,从而达到通过提高日志查询排查问题的效率。背景开发排查系统问题用得最多的手段就是查看系统日志,相信不少人都值过班当过小秘吧:给下接口和出入参吧,麻烦看看
京东云开发者 京东云开发者
1个月前
技术分享-日志链路追踪
1.背景简述在技术运维过程中,很难从某服务庞杂的日志中,单独找寻出某次API调用的全部日志。为提高排查问题的效率,在多个系统及应用内根据统一的TraceId查找同一次请求链路上的日志,根据日志快速定位问题,同时需对业务代码无侵入,特别是在高频请求下,也可以