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://flume.apache.org

https://github.com/facebookarchive/scribe

https://kafka.apache.org

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://elasticsearch.cn

https://www.elastic.co/cn/products/beats/filebeat

https://www.elastic.co/guide/en/beats/filebeat/5.6/index.html

posted on 2021-12-31 15:51  JeffWong  阅读(913)  评论(1编辑  收藏  举报