1. 项目介绍
本项⽬主要实现⼀个日志系统, 其主要支持以下功能:
• 支持多级别日志消息
• 支持同步日志和异步日志
• 支持可靠写⼊日志到控制台、文件以及滚动文件中
• 支持多线程程序并发写日志
• 支持扩展不同的日志落地⽬标地
2. 开发环境
• CentOS 7
• vscode/vim
• g++/gdb
• Makefile
3. 核心技术
• 类层次设计(继承和多态的应用)
• C++11(多线程、auto、智能指针、右值引用等)
• 双缓冲区
• 生产消费模型
• 多线程
• 设计模式(单例、工厂、代理、模板等)
4. 环境搭建
本项⽬不依赖其他任何第三方库, 只需要安装好CentOS/Ubuntu + vscode/vim环境即可开发。
5. 日志系统介绍
5.1 为什么需要日志系统
• 生产环境的产品为了保证其稳定性及安全性是不允许开发人员附加调试器去排查问题, 可以借助日志系统来打印⼀些日志帮助开发人员解决问题
• 上线客⼾端的产品出现bug无法复现并解决, 可以借助日志系统打印日志并上传到服务端帮助开发人员进行分析
• 对于⼀些高频操作(如定时器、心跳包)在少量调试次数下可能无法触发我们想要的行为,通过断点的暂停方式,我们不得不重复操作⼏⼗次、上百次甚⾄更多,导致排查问题效率是⾮常低下,可以借助打印日志的方式查问题
• 在分布式、多线程/多进程代码中, 出现bug⽐较难以定位, 可以借助日志系统打印log帮助定位bug
• 帮助⾸次接触项⽬代码的新开发人员理解代码的运行流程
5.2 日志系统技术实现
日志系统的技术实现主要包括三种类型:
• 利用printf、std::cout等输出函数将日志信息打印到控制台
• 对于⼤型商业化项⽬, 为了方便排查问题,我们⼀般会将日志输出到文件或者是数据库系统方便查询和分析日志, 主要分为同步日志和异步日志方式
◦ 同步写日志
◦ 异步写日志
5.2.1 同步写日志
同步日志是指当输出日志时,必须等待日志输出语句执行完毕后,才能执行后⾯的业务逻辑语句,日志输出语句与程序的业务逻辑语句将在同⼀个线程运行。每次调用⼀次打印日志API就对应⼀次系统调用write写日志文件。
在高并发场景下,随着日志数量不断增加,同步日志系统容易产生系统瓶颈:
• ⼀方⾯,⼤量的日志打印陷⼊等量的write系统调用,有⼀定系统开销.
• 另⼀方⾯,使得打印日志的进程附带了⼤量同步的磁盘IO,影响程序性能
5.2.2 异步写日志
异步日志是指在进行日志输出时,日志输出语句与业务逻辑语句并不是在同⼀个线程中运行,⽽是有
专⻔的线程用于进行日志输出操作。业务线程只需要将日志放到⼀个内存缓冲区中不用等待即可继续执行后续业务逻辑(作为日志的生产者),⽽日志的落地操作交给单独的日志线程去完成(作为日志的消费者), 这是⼀个典型的生产-消费模型。
这样做的好处是即使日志没有真的地完成输出也不会影响程序的主业务,可以提高程序的性能:
• 主线程调用日志打印接口成为⾮阻塞操作
• 同步的磁盘IO从主线程中剥离出来交给单独的线程完成