PowerDotNet平台化软件架构设计与实现系列(11):日志平台
所有后端应用几乎都会记录日志,日志系统可以统一抽象出来提供服务。
最近被Log4j2的安全漏洞刷屏了,作为开发人员的我只能咩哈哈几次表示日志处理太难了,只有折腾过的人才知道这里面的艰辛啊。
在实现PowerDotNet日志系统之前,参考调研了Flume、ELK、Scribe和kafka的日志解决方案,对比后最终选择Facebook的日志系统Scribe作为目标,实现了基于thrift协议(当然也支持http协议)无锁且异步的更高性能简洁而稳定的可扩展日志系统Power.XLogger。
本文讲讲PowerDotNet内置的日志平台系统。
环境准备
1、(必须).Net Framework4.5+
2、(必须)MySQL或SqlServer或PostgreSQL或MariaDB或MongoDB或ElasticSearch
3、(必须)PowerDotNet数据库管理平台,主要使用DBKey功能
4、(必须)PowerDotNet配置中心Power.ConfigCenter
5、(必须)PowerDotNet注册中心Power.RegistryCenter
6、(必须)PowerDotNet基础数据平台Power.BaseData
7、(必须)PowerDotNet缓存平台Power.Cache
8、(必须)PowerDotNet消息平台Power.Message
9、(必须)PowerDotNet人员管理平台Power.HCRM,后续文章详细介绍
一、Scribe简介
Scribe是Facebook开源的日志收集系统,它能够从各种日志源上收集日志,存储到一个中央存储系统(可以是NFS,分布式文件系统等)上,以便于进行集中统计分析处理。
Scribe为日志的“分布式收集,统一处理”提供了一个可扩展的高容错的方案。
Scribe从各种数据源上收集数据,放到一个共享队列上,然后push到后端的中央存储系统上。
当中央存储系统出现故障时,Scribe可以暂时把日志写到本地文件中,待中央存储系统恢复性能后,Scribe把本地日志续传到中央存储系统上。
Scribe主要包括三部分,分别为Scribe Agent, Scribe和存储系统。
1、 Scribe Agent
Scribe Agent实际上是一个thrift client。 向Scribe发送数据的唯一方法是使用thrift client, Scribe内部定义了一个thrift接口,用户使用该接口将数据发送给server。
2、Scribe
Scribe接收到thrift client发送过来的数据,根据配置文件,将不同topic的数据发送给不同的对象。Scribe提供了各种各样的store,如 file, HDFS等,Scribe可将数据加载到这些store中。
3、Store
Scribe中的Store也就是我们所理解的存储系统,当前Scribe支持非常多的Store,包括:
file(文件)
buffer(双层存储,一个主储存,一个副存储)
network(另一个Scribe服务器)
bucket(包含多个 store,通过hash的将数据存到不同store中)
null(忽略数据)
thriftfile(写到一个Thrift TFileTransport文件中)
multi(把数据同时存放到不同store中)
二、日志存储
PowerDotNet的日志平台设计借鉴了Scribe,也支持从各种数据源上收集数据,放到一个共享队列上,然后push或pull到后端的中央存储系统上。
不过考虑到不同的应用场景,这个共享队列被设计成动态可配置的日志容器,容器可以是主流的几种消息队列(RabbitMQ、MSMQ、RocketMQ、Kafka等),redis,本地缓存等。
当存储系统出现故障时,PowerDotNet也会把日志“消息”暂时(序列化)写到本地文件中,待存储系统恢复性能后,再把本地日志(反序列化)续传到中央存储系统上。这种日志记录容错思想其实比较简单直白,非常容易理解。
PowerDotNet内置的日志存储媒介(也就是中央存储系统)包括MongoDB、MySQL、MariaDB、PostgreSQL、SQLServer和ElasticSearch,也给Exceptionless和ELK预留了接口,后续开发考虑把Hive也加进去,毕竟对于日志系统而言,大数据量处理和较为完善的分析工具链是极其重要的参考指标。
在创建后端应用的时候,配置中心会自动分配一个记录日志的DBKey,默认为PostgreSQL,但是个人在公司里碰到的更多的是使用MongoDB或者ElasticSearch或者ELK。
配置好DBKey,日志系统自动生效。写代码的时候调用现有的PowerDotNet记录日志方法即可。
PowerDotNet记录日志方法默认是全异步收集,不会影响业务主流程。
PowerDotNet日志组件支持敏感信息脱敏,这也是非常常见的业务需求功能。
对比Scribe的存储系统,PowerDotNet.XLogger做了大量裁剪。
三、日志管理
1、获取DBKey
因为每个应用默认都配置了一个DBKey,所以查询应用的日志时,需要通过DBKey间接找到存储,最后再将查询数据显示出来。
考虑到由于日志量通常都非常庞大,所以我们设计日志系统的时候都需要考虑分片处理。
DBKey配置日志这种方式天然就适合日志分片存储,在日志发展到一定数据量级以后,不需要运维和DBA介入,直接换个DBKey或者通过DataX数据同步平台修改DBKey连接串就可以切换新的日志存储介质,历史日志如果需要,通过其他工具直接访问,简直不要太容易。
2、日志查询
日志查询界面自动根据应用适配DBKey找到自己的日志记录。
3、调用链查询
对于调用链路复杂冗长的接口,调用链查询支持非常重要,根据个人开发运维经验,在排查线上问题的时候,调用链查询功能发挥了非常直观高效的作用。
调用链支持多系统多应用的查询,不同系统的DBKey可能不同,数据存储在不同的数据库中,这时候需要我们自己在内存中进行聚合分页展示。
有些开源的优秀组件,如zipkin或SkyWalking+SkyApm,在你的服务中埋点相应代码,可以实现分布式链路追踪系统。
调用链查询对于排查调用异状非常有帮助。
四、其他
对于日志系统而言,我们几乎不会强调ACID、CAP、BASE这些要求。日志系统应该尽可能做到快速高效不影响主业务流程,如果在保证日志高可用的同时,能不丢数据那是最好的结果。
Power.XLogger默认推荐各应用使用AOP方式记录日志,统一日志记录格式,当然为了便于排查问题,也需要在某些步骤埋点记录特定日志。
对于某些系统,日志可能非常重要,比如支付、财务、账户等系统。
如果日志是业务逻辑里非常重要的一部分,尤其关键环节的重要日志,不但业务逻辑可能要用到,而且排查追踪问题也很有用处,这种情况下,就不建议直接使用日志平台了。
PowerDotNet对于这些日志敏感系统,都会在自身系统里建立日志表进行核心关键日志记录,当然也支持按需在Power.XLogger记录日志。
对于日志系统的埋点操作,建议使用Power.XLogger的异步批量处理方法,并且显式带上超时时间,Power.XLogger记录日志默认2秒超时,默认批量处理200条数据,这两个参数可通过配置中心动态调整。
日志队列堆积到一定阈值(默认20万条,可在配置中心动态配置)自动裁剪日志,防止系统内存不足或其他原因导致崩溃。
参考:
https://github.com/facebookarchive/scribe
https://www.elastic.co/cn/products/logstash
https://www.elastic.co/guide/en/logstash/5.6/index.html
https://www.elastic.co/cn/products/kibana
https://www.elastic.co/guide/en/kibana/5.5/index.html
https://www.elastic.co/cn/products/elasticsearch
https://www.elastic.co/guide/en/elasticsearch/reference/5.6/index.html
https://www.elastic.co/cn/products/beats/filebeat
https://www.elastic.co/guide/en/beats/filebeat/5.6/index.html
作者:Jeff Wong
出处:http://jeffwongishandsome.cnblogs.com/
本文版权归作者和博客园共有,欢迎围观转载。转载时请您务必在文章明显位置给出原文链接,谢谢您的合作。