java io高效记录日志_第5章 高效的多线程日志

本文介绍了日志的两种类型——诊断日志和交易日志,探讨了日志库的功能需求,包括日志级别、目的地、格式和过滤器。文章强调在运行时调整日志级别的重要性,并分享了几项简化日志管理的技巧。性能方面,日志系统应具备高效率,尤其是在多线程环境中。提出了多线程异步日志的概念,以解决并发写入和性能损失的问题,确保日志系统的线程安全和高效性。
摘要由CSDN通过智能技术生成

日志有两个意思:

诊断日志(diagnostic log)   即 log4j、 logback、 slf4j、 glog、 g2log、 log4cxx、 log4cpp、 log4cplus、 Pantheios、 ezlogger 等 常用 日志 库 提供 的 日志 功能。

交易 日志( transaction log)   即 数据库 的 write- ahead log1、 文件 系统 的 journaling2 等, 用于 记录 状态 变更, 通过 回 放 日志 可以 逐步 恢复 每一 次 修改 之后 的 状态。

1. 功能需求

常规的通用日志库如log4j13/ logback14 通常会提供丰富的功能,但这些功能不一定全都是必需的。

日志 消息 有多 种 级别( level), 如 TRACE、 DEBUG、 INFO、 WARN、 ERROR、 FATAL 等。

日志 消息 可能有 多个 目的地( appender), 如 文件、 socket、 SMTP 等。

日志 消息 的 格式 可 配置( layout), 例如 org. apache. log4j. PatternLayout。 4. 可以 设置 运行时 过滤器( filter), 控制 不同 组件 的 日志 消息 的 级别 和 目的地。

在上面 这 几项 中, 我 认为 除了 第一 项 之外, 其余 三项 都是 非 必需 的 功能。

日志 的 输出 级别 在 运行时 可调, 这样 同一个 可执行 文件 可以分 别在 QA 测试 环境 的 时候 输出 DEBUG 级别 的 日志, 在 生产 环境 输出 INFO 级别 的 日志。 在必 要的 时候 也可以 临 时在 线 调整 日志 的 输出 级别。

例如 某台 机器 的 消息 量过 大、 日志 文件 太多、 磁盘 空间 紧张, 那么 可以 临时 调整 为 WARNING 级别 输出, 减少 日志 数目。 又比 如 某个 新 上 线 的 进程 的 行为 略显古怪,则可以来临时调整为DEBUG级别输出,打印更细节的日志消息一遍分析查错。调整日志的输出级别不需要重新翻译,也不需要重启进程,主要调用muduo::Logger::setLogLevel()就能即时生效。

有几个简单的技巧:

对于分布式系统中的服务进程而言,日志的目的地只有一个:本地文件。

以本地文件为日志的destination,那么日志文件的滚动是必须的,这样可以简化日志的归档的实现。

日志文件压缩与归档不是日志库应有的功能,而应该交给专门的脚本去做,这样C++和Java的服务程序就可以共享这一基础设施。如果想更改日志压缩算法或归档策略也不必动业务程序。

往文件写日志的一个常见问题就是,万一程序崩溃,那么最后若干条日志往往就丢失了,因为日志库不能每条信息都flush硬盘,更不能每条日志都open/close文件,这样开销太大。muduo采用的做法是:

定期(默认3s)将缓冲区内的日志消息flush到硬盘;

每条内存中的消息都带有cookie,其值为某个函数的地址,这样通过在core dump文件中查找cookie就能找到尚未来得及写入磁盘的消息。

日志消息的格式主要有以下几个要素:

尽量每条日志都占一行;

时间戳精确到微秒

始终使用GTM时区

打印线程id

打印日志级别

打印源文件名和行号

2. 性能需求

高效性体现在几方面:

每秒写几千上万条日志的时候没有明显的性能损失;

能应对一个进程产生大量的日志数据的场景;

不阻塞正常的执行流程;

在多线程程序中,不造成争用;

磁盘带宽约是110MB/s,日志库应该能瞬间写满这个带宽;

假设每条日志消息的平均长度是110个字节,这个意味着1s要写100万条日志。

3. 多线程异步日志

多线程程序对日志库提出了新的需求:线程安全,即多个线程可以并发写日志,两个线程的日志消息不会出现交织。

线程安全不难办到,简单的办法就是用一个全局的mutex保护IO,活着每个线程单独写一个日志文件,这两种做法会损失高效性。前者会造成全部线程抢一个锁,后者有可能让业务线程阻塞在写磁盘操作上。

一个多线的程序的每个进程最好只写一个日志文件,这样分析日志更方便。再说多线程写多个文件也不一定能够提速。解决办法可以用一个背景线程负责收集日志消息,并写入日志文件,其他业务线程只管往这个“日志线程”发送日志消息,这称为“异步日志”。

在多线程服务程序中,异步日志是必须的,因为如果在网络IO线程或业务线程中直接往磁盘写数据的话,写操作偶尔可能阻塞长达数秒之久。这可能导致请求方超时,活着耽误发送心跳消息,在分布式系统中更可能造成多米诺骨牌效应,例如误报死锁引发自动failover等。因此,正常的实时业务处理中,应该彻底避免磁盘IO,这里使用one loop per thread模型的非阻塞服务程序中尤为重要。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值