1 概述
日志是记录系统中各种问题信息的关键,也是一种常见的海量数据。做好日志可以有效的解决排查问题效率低、业务异常无法及时发现等等问题。
斗鱼的业务是经典的高并发场景:我们会由于某些业务场景,用户请求量会十倍秒级突增。为了针对这种场景,提高服务性能,我们不仅要优化业务逻辑,同时还要提升日志等基础组件的性能。以下是我们斗鱼go的日志类库架构图:
从架构图的日志组件中我们列举了三个重要组成部分。首先是日志的使用,我们提供了sugar、desugar、lazy-output的三种模式。根据使用场景,业务方可以选择不同的模式。例如在高并发场景情况下,可以使用编码稍微麻烦,但性能较好的desugar模式。在后台业务场景,可以使用性能差点,但编码友好的sugar模式;第二部分是日志的落盘,我们提供了配置项可以让业务方开启同步落盘,还是异步落盘,并且在异步落盘的时候,我们还针对落盘的时间和大小进行了测试,下文中会详细介绍;第三部分是日志的降级功能,我们也提供了配置项可以让业务方选择是否开启降级功能,我们的框架会将日志会拆分成info,err两种日志文件(参考ngx的日志)。这样的好处就是我们可以对info日志很好的降级,但err日志不会受任何影响,能够更好的去监控我们服务的错误问题。
2 日志库实践
直播流服务作为斗鱼的核心服务,记录的日志价值比较重要,我们能根据日志内容做报表分析、问题排查、流防刷等事情。但过多的日志又会影响服务性能。一方面我们需要日志帮我们解决业务上的问题,一方面又希望能日志不影响服务性能。
基于我们的业务场景,我们对日志库的需求如下:
高性能:我们的业务场景中有很多服务是会有突发流量的,因此日志的性能必须不能成为业务的瓶颈;
结构化:我们的很多业务会产生有价值的日志,因此日志必须结构化以便进行业务和服务的报表分析;
分级:在一定的场景下异步日志会退化成同步,为了保证业务的性能和可用性,不可避免的会需要对日志进行分级处理,即丢弃一部分非核心日志,保留核心日志;
标准化:日志标准化后可以方便做告警、报表等;
在golang日志库上我们没有必要完全重新造轮子,那么现有的开源组件中我们应该选择使用哪个呢?
2.1 日志库选型
基于以上我们对日志的需求,我们研究了部分golang主流开源日志库,最后我们选择了性能最好的zap。以下为各日志类库的性能对比表:
zap是一个比较优秀的日志组件。提供了sugar和desugar模式。方便业务方根据不同场景,选择不同的日志使用方式。并且提供了大量接口,方便业务方去改造日志类库。因此我们的日志是在zap的基础上进行了wrap,规范了日志用法、提供了日志插件。更好的适用于我们斗鱼的业务场景。
2.2 日志规范
斗鱼后端已经全面微服务化,线上运行上几百个各类业务服务。大量的服务每时每刻都在