1 引言
Elasticsearch(后称ES)作为日志管理、数据搜索与分析工具,在各行各业都有广泛且深入的应用,2021年初Elastic公司不再提供ES的Apache license开源版本,AWS为此推出了基于ES 7.10.2开发的OpenSearch。OpenSearch自2022年发布至今,在DB-Engine的搜索引擎分类的排名迅速攀升到第4,由于与ES同源,OpenSearch成为ES完美的商业替代产品。
图1 DB-Engines搜索引擎分类排名
G行在应用系统全面上云的背景下,进行了基于容器化OpenSearch的全栈云日志平台设计与实践,并开展了一系列性能优化,探索适合全栈云的日志处理、数据分析与数据搜索替换路线。下文详细介绍G行基于OpenSearch开展的日志平台设计与优化工作。
2 设计原则与架构
2.1原则
G行全栈云日志平台以收集并处理全栈云底座管理服务日志为目标,并对管理员提供日志查询视图、日志分析看板等功能。考虑到接入组件服务多、日志量分时差异大、日志查询时间长等实际情况,平台需满足如下几点要求:
- 数据缓存不丢失
在日志量大且集中的时段,OpenSearch可能无法及时处理所有数据,通过日志缓存确保未及时处理的数据可以在后期追溯。
- 日志数据读写分离
避免直接对客户端服务暴露写入端口,降低对OpenSearch集群的冲击,确保平台的运行稳定性。开放适当权限的数据查询视图。
- 数据冷热分离
持续写入的索引作为热数据存放在热节点,不再更新的索引作为温数据存放在温节点,不需查询的数据作为备份存放在对象存储。确保数据读写性能得到保障。
2.2架构
通过kafka实现日志的集中接入与缓存,并且实现对OpenSearch的平滑写入;通过logstash实现日志数据的集中处理,对数据流开展解析与二次加工工作;通过OpenSearch的ISM(Index State Management,索引状态管理)机制实现索引数据的热、温、冷自动化处理,冷数据存储备份于对象存储中;通过Dashboard实现可视化数据查询与看板定制。下图为日志平台架构展示。
图2 全栈云日志平台服务架构
3 性能优化
基于上述架构实现日志处理平台后,随着服务接入变多,接入日志量变大,平台出现kafka端消息积压的情况,经过调试分析,分别从kafka、logstash和OpenSearch三个部分开展优化,并实现了消息数据的实时消费与写入。
3.1问题分析
通过kafka集群节点的磁盘io曲线可以看出磁盘的写入速度约是读取速度的8倍,即消息的消费速度明显跟不上消息的生产速度,这也符合kafka消息积压的现象。
图3 kafka节点的磁盘io曲线
通过logstash节点的监控曲线,发现logstash的cpu利用率和出入站流量较低,而OpenSearch的cpu利用率和吞吐量同样不高。为此考虑从日志平台的整个路径上开展优化以提升消息处理性能。
3.2kafka的优化
kafka通过磁盘顺序写入、操作系统页缓存、零拷贝、消息批量处理和压缩等一系列精妙设计,确保了服务的高性能,但仍需做一些配置调整以应对实际使用环境。如下列出一些当前环境下所做的配置调整。
🔧num.partitions
需要针对topic的实际消息大小、以及kafka集群的规模(避免出现数据倾斜)进行配置,以达到生产和消费的平衡。
🔧auto.create.topics.enable
将自动创建消息配置为false,确保集群管理topic可控。
🔧log.segment.bytes
__consumer_offsets是kafka自行创建的内部topic,用于保存集群内consumer对所有topic的消费位移信息。kafka通过对消费者组group id的哈希值进行求模运算(groupID.hashCode()%numPartitions),从而将消息存储在不同的分区,意味着同一消费者组的消费位移信息会同时更新到同一个分区。
__consumer_offsets的log.segment.bytes默认是100MB。当topic足够多带来的partition数量庞大,可能导致集群更新__consumer_offsets失败从而使得当前消费者无法消费数据,即上图报错。为此,需要适当扩大__consumer_offsets的log.segment.bytes,本环境将其扩大到了1GB。
🔧max.incremental.fetch.session.cache.slots
用于限制每个broker上的最大fetch session数量,当集群的partition数量足够大且消费线程足够多时,会导致消费者session抢占,使消费者组不断rebalance,影响消费性能。该配置默认值为1000,需要根据环境的消费者线程数、分区数等实际情况进行配置调整。
3.3logstash的优化
logstash充当连通kafka和OpenSearch的管道,并对管道中的消息进行加工处理。除了对不同消息进行分组消费,如下列为几个关键参数的配置调整,用于提高logstash的资源利用率和数据吞吐。
🔧pipeline.batch.size
logstash.yml的配置参数,用于设置logstash批量处理的消息总量,以及单次发往OpenSearch的批量请求大小,默认值为125,应当根据OpenSearch性能及logstash资源占用情况尽可能调大。
🔧pipeline.workers
logstash.yml的配置参数,单个logstash实例运行时用于处理消息数据的线程数,根据logstash资源配置(CPU配额)调整。
🔧consumer_threads
logstash.conf中对于kafka input plugin的配置,消费者线程数。可以根据消费的分区数以及logstash资源实际使用情况综合设置,理想配置是与消息分区数保持一致。
🔧partition_assignment_strategy
logstash.conf中对于kafka input plugin的配置,当使用topics_pattern匹配topic进行消费时,默认的partition_assignment_strategy为Range,该策略容易带来部分消费者过载的情况,建议指定为round_robin策略进行分区分配。
3.4OpenSearch的优化
从索引写入配置、索引存储管理以及集群节点资源调整等方面提升OpenSearch的写入性能,同时优化平台的使用体验。
- 索引模板设置
🔧index.refresh_interval
索引数据刷新落盘的周期,根据索引数据需要呈现的时效性进行配置,对于允许推迟查询的数据,加大配置值,比如增加至30s或60s。
🔧index.number_of_shards
索引的分片数,增加分片可以提升写入性能,但分片太多会增加集群管理压力,带来负面影响,根据索引数据大小(建议单个分片大小小于50GB)、数据节点数灵活配置。
🔧index.translog.durability
对于极端情况下(比如数据节点宕机)允许部分数据丢失的情况,将translog同步刷盘调整为异步,提高集群处理性能。
- 读写分离
通过配置节点角色(热/温/冷)以及索引的分配属性,将有数据写入的索引分配到热节点,没有数据写入的索引分配到温节点。
- ISM
ISM(Index State Management)可通过策略实现对索引的生命周期管理,及索引数据的状态切换。通过ISM实现索引从创建、备份到删除的自动化处理。
图5 优化前后logstash的CPU利用率曲线对比
图6 优化后kafka节点的磁盘io曲线
通过前述优化配置处理,日志平台已经实现全栈云底座管理服务的全量日志收集与呈现,并解决了消息积压问题。图5展示了logstash优化前后的CPU利用率占比,从10%不到提升至约70%。图6为某kafka节点的磁盘读写曲线,写入带宽约为读取带宽的2倍,考虑到kafka消息的多副本配置,属于合理预期。
4 改进与优化
经过一系列实践与优化,全栈云日志平台已能平稳处理云底座管理服务日志。在后续过程中,平台计划在以下方面进一步完善和改进,包括:
💡提高日志处理性能
fluent-bit / filebeat / fluentd / logstash等不同语言架构的组件,配置与性能差异均较大,后续将探索使用vector提高日志处理性能。
💡优化对象存储索引设计
由于每天都有索引通过ISM转移到对象存储中,需要对对象存储中的索引快照进行管理设计,以提升索引恢复效率、清理不再需要的快照。
💡提升平台可靠性
由于整个日志处理链路较长,需要对每个阶段的状态进行监控并配置告警,以确保平台的可靠性,及时发现问题并预警。
作为全栈云平台可观测能力的关键组成部分,日志记录了系统发生的所有行为。其不仅可用于系统排错、产品优化,还可为审计、取证等工作提供素材。下一步,全栈云日志平台将以统一日志采集、处理、治理和分析为目标,打造全栈云可观测数据底座,为G行可观测能力建设添砖加瓦。