异步日志实时推送
跨服务异步日志实时推送方案
1 背景
后台使用微服务架构之后,多个微服务会部署在不同的服务器上运行,每个微服务产生的日志会分布在各个服务器当中,ELK虽然能够将这些日志进行过滤收集来让用户查看,但是在实时性和定制化方面有所欠缺。
如果采用日志先落盘,再进行收集日志,首先会因为磁盘的IO消耗多余的时间,另外会由于日志落盘之后,用户在运行阶段的运行时信息会丢失,使得日志按照用户运行时信息进行分类变得困难。
2 思路
基于 log4j2设计一个Appender,并加入到微服务日志的配置中,然后采用监听器的设计模式和RPC的服务调用实现日志的跨服务异步实时推送。
3 实现
3.1 Appender组件的设计实现
现在后台开发比较流行的日志框架用slf4j 作为Façade,配合logback或者log4j2等使用,由于log4j2在性能上的优势以及开源的license原因,现在的开源项目都会首选log4j2作为日志打印的框架。
Appender是log4j2日志打印的target(目标地),微服务运行过程中产生日志事件之后,在配置中注册的Appender都会获取到这个日志事件。
Linkis设计的Appender会在日志微服务日志生成之后,将获得的日志事件缓存到队列中,另外在Appender中我们还设置了一个监听器。
3.2 监听器的设计实现
监听器模式是一种常见的设计模式,是异步回调编程的一种常见的实现方式。
监听器需要监听的是日志事件队列,如果监听到日志事件队列已满,就将日志从队列中取出,排队通过HTTP的方式发送。
另外监听器也需要监听任务的状态,任务在本微服务中完成了所有的执行步骤后,需要将在队列中缓存的日志都发送出去防止日志的丢失。
3.3 缓存队列的设计实现
日志使用缓存队列原因在于如果产生一个日志事件就推送,会由于HTTP请求过于频繁而导致接收日志的微服务一直处于繁忙状态,所以必须要进行缓存,一般缓存队列可以设计为有最大缓存数目的阻塞队列。
3.4 日志的收集
日志会统一发到日志收集的微服务中,然后由该微服务进行日志的排序和封装,封装之后的日志会推送给用户界面,同时日志也会异步写盘,为每一个用户备份一个任务的日志。