ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

PlumeLog实战:构建轻量级分布式日志采集与监控平台

PlumeLog实战:构建轻量级分布式日志采集与监控平台 开篇一个真正能“少睡好觉”的分布式日志系统做后端开发的谁没被日志坑过我前两年在一家业务增长很快的互联网公司带团队每天最怕就是线上出故障几百台机器几十个微服务日志散落在各个节点上查一个问题要先ssh到三四台机器用tail -f和grep一路翻过去运气不好还得让运维帮忙拉日志包。最崩溃的是日志量一大磁盘直接被撑爆应用挂了还不知道是哪个模块写日志写疯了。后来我们引入了Elasticsearch做日志中心确实能搜了但接入成本和维护成本都不低。直到我在开源社区翻到PlumeLog算是真正找到了一个轻量、上手快、还带分析能力的分布式日志收集方案。PlumeLog是一个开源的分布式日志系统定位很明确日志采集、日志检索、日志分析、监控告警。它自带轻量级Agent不需要你在业务代码里埋什么点通过配置就能把日志实时传输到Kafka再由消费端写入Elasticsearch前端做了一套可视化平台配规则、查日志、看统计一条龙搞定。对我来说它最大的价值是“不折腾”不用自己拼Spark Streaming不用手写Kafka Consumer更不用从零开发一套日志查询UI。如果你团队规模中等、没有专职的日志平台研发但又受够了在服务器上翻日志PlumeLog值得花一个下午研究一下。1. 整体架构与设计逻辑为什么它让你“不用重复造轮子”1.1 核心组件拆解PlumeLog的架构在很多技术分享里都有提到但真正自己搭一遍才能理解每个组件存在的价值。它主要由五个部分组成Agent端plume-log-agent安装在业务服务器上负责采集日志文件。默认支持Log4j、Log4j2、Logback等主流日志框架采集方式支持文件Tail和Socket直推。数据传输层Kafka作为日志传输的缓冲队列起到了削峰填谷的作用。日志高峰期不会直接压垮后面的Elasticsearch。消费端plume-log-consumer从Kafka拉取日志数据解析后交给Elasticsearch存储。它内部做了分区路由保证同一应用的日志能够有序落盘。存储/检索引擎Elasticsearch负责日志的分布式存储和全文检索。PlumeLog推荐配套使用Kibana做可视化但控制台自身也提供了查询页面。Web控制台plume-log-web用Spring Boot写的后端前端页面负责应用管理、日志查询、告警规则配置、统计报表展示。这套结构并不算新奇但它最大的优点就是“各司其职、替换方便”。比如你要换掉Kafka用RocketMQ消费端改改依赖和配置就行你想跳过Elasticsearch直接对接ClickHouse做日志分析理论上也是可行的。我搭建的时候有一个很直观的感受它把每个环节都做成了可插拔的模块这比那些“全家桶”式的日志系统灵活太多。1.2 为什么选择这个技术栈有人说日志系统直接FilebeatELK不就好了为什么还要套一层Kafka和自研消费端我当年也有这个疑问直到经历了“日志峰值打挂ES”的线上事故才明白没有缓冲层的日志系统在高并发环境下就是定时炸弹。Filebeat确实很轻量但它的职责只是传输不支持复杂的日志解析和告警判断。而PlumeLog选择Kafka做消息队列相当于在日志产生端和存储端之间加了一个“水库”。比如你们业务大促时日志量瞬间冲到每秒几十万条ES集群如果直接面对这个流量分分钟写崩但有了Kafka先扛住消费端可以按ES的写入能力匀速消费这就是削峰填谷的作用。再讲Elasticsearch为什么选它而不是MySQL因为日志检索场景核心是“全文模糊查询”和“多维过滤”ES的倒排索引天然适配这类需求。MySQL用LIKE %error%查几千万行的日志表慢得让你怀疑人生而ES在亿级数据下查询基本是秒级返回。PlumeLog在ES里按天建索引配合生命周期管理过期自动清理运维成本也低。1.3 和ELK/EFK全家桶相比它强在哪参考一下我用过的多套方案简单列个对比表对比项PlumeLogELK/EFK自建日志采集方式自带Agent支持多框架接入Filebeat/Logstash需自行配置数据缓冲内置Kafka支持需自己部署Kafka或Redis告警能力控制台内置告警规则无需额外开发通常需要另接Elasticsearch Watcher或第三方告警查询界面自带中文控制台开箱即用Kibana为主配置相对复杂部署复杂度Docker Compose一键拉起核心组件组件多调优项多二次开发成本基于Spring Boot扩展点清晰视组件而定我并不是说ELK不好它在通用性和生态上是标杆。但如果你的目标是“一个月内上线一套能用的日志平台而不是花三个月去调Logstash的管道配置”PlumeLog这种自带控制台、自带采集器、自带告警的一体化方案明显更符合中小团队的节奏。2. 环境准备与搭建从零部署一套可用的PlumeLog2.1 机器规划与版本选型我在测试环境用的是3台4核8G的云服务器操作系统是CentOS 7.9部署结构如下节点AKafka Zookeeper Elasticsearch节点BPlumeLog Web控制台 Consumer消费端节点C业务服务模拟 PlumeLog Agent这里有个细节要注意真实生产环境Kafka和ES千万不要混部在同一台机器上两者都是吃内存的大户Kafka的PageCache和ES的JVM堆会互相抢内存。测试环境无所谓生产环境建议Kafka单独节点ES集群至少3节点起步避免脑裂。版本选择上我踩过一个小坑PlumeLog的GitHub仓库对ES版本有要求我用的是Elasticsearch 7.6.2配套的PlumeLog版本是1.3.0。如果你用ES 8.x版本需要确认PlumeLog的客户端依赖是否兼容否则启动消费端时会报TransportClient连接错误。2.2 Docker Compose快速部署PlumeLog官方提供了docker-compose配置我建议先用它把环境跑通再深入内部折腾。以下是我整理的最小化配置已去除与核心功能无关的组件version: 3 services: zookeeper: image: zookeeper:3.5 container_name: pl_zookeeper ports: - 2181:2181 environment: ZOO_MY_ID: 1 volumes: - ./data/zk:/data kafka: image: bitnami/kafka:2.8.0 container_name: pl_kafka ports: - 9092:9092 environment: KAFKA_CFG_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_CFG_ADVERTISED_LISTENERS: PLAINTEXT://192.168.1.100:9092 KAFKA_CFG_LISTENERS: PLAINTEXT://0.0.0.0:9092 depends_on: - zookeeper volumes: - ./data/kafka:/bitnami/kafka elasticsearch: image: elasticsearch:7.6.2 container_name: pl_es ports: - 9200:9200 environment: discovery.type: single-node ES_JAVA_OPTS: -Xms1g -Xmx1g volumes: - ./data/es:/usr/share/elasticsearch/data plumedb: image: mysql:5.7 container_name: pl_mysql ports: - 3306:3306 environment: MYSQL_ROOT_PASSWORD: plume_log_2024 MYSQL_DATABASE: plume_log command: --default-authentication-pluginmysql_native_password volumes: - ./data/mysql:/var/lib/mysql这里重点说下KAFKA_CFG_ADVERTISED_LISTENERS这个IP必须填你自己服务器的内网地址或者能被客户端访问到的地址。我第一次用默认的localhost启动结果Agent节点根本连不上Kafka报Connection refused折腾了半天才发现是listener配置的问题。ES的ES_JAVA_OPTS最开始没设直接导致容器启动后JVM占用过大被内核OOM Kill。单测环境1G的堆内存足够了生产环境按内存总量的一半设置上限不要超过32G。2.3 初始化数据库和配置控制台PlumeLog Web服务需要MySQL存放元数据比如应用信息、用户信息、告警规则等。连接参数在application.properties里配置spring.datasource.urljdbc:mysql://192.168.1.100:3306/plume_log?useUnicodetruecharacterEncodingUTF8serverTimezoneAsia/Shanghai spring.datasource.usernameroot spring.datasource.passwordplume_log_2024 spring.datasource.driver-class-namecom.mysql.jdbc.Driver # ES连接地址 plume.es.host192.168.1.100:9200 plume.kafka.bootstrap-servers192.168.1.100:9092数据库建表语句在项目源码的doc/sql目录下直接用source命令导入即可。这里提醒一下MySQL如果需要远程连接测试记得先确认防火墙规则和用户授权很多“控制台起不来”的问题最后查出来都是数据库连不上导致Spring Boot启动失败。启动Web服务的命令非常简单mvn clean package -DskipTests cd target java -jar plume-log-web.jar --spring.config.location/etc/plumelog/application.properties等控制台日志出现Tomcat started on port 8899访问http://服务器IP:8899就能看到登录页了默认账号密码是admin/admin。生产环境一定要第一时间改密码这个系统默认密码太容易被爆破了。3. 核心配置与业务接入真正跑通一条日志链路3.1 Agent采集配置实战PlumeLog Agent支持两种模式一种是嵌入业务应用内作为日志Appender一种是独立进程采集文件。我更推荐后一个方式因为它对业务代码零侵入。在业务服务器上我建了一个目录/opt/plume-agent放置以下文件plume-log-agent.jar agent.propertiesagent.properties的配置内容是# Kafka地址 plume.kafka.bootstrap.servers192.168.1.100:9092 # 采集模式files表示从文件采集 plume.agent.modelfiles # 日志文件路径支持通配符 plume.agent.files/data/logs/app-demo/*.log # 应用名称对应控制台注册的应用 plume.agent.appNameapp-demo # 扫描间隔毫秒 plume.agent.scan.interval3000启动Agentnohup java -jar plume-log-agent.jar agent.properties agent.log 21 这里有个“隐含知识点”Agent的日志是有游标记录的重启Agent不会导致日志全部重采而是从上次的位置继续读。如果你希望重新采集历史日志要去~/.plumeLog目录下删掉对应的偏移量文件。这个细节官方文档没写清楚我当时排查“日志重复上报”问题耗时大半天最后发现是游标文件指向了旧的位置。3.2 业务应用接入Log4j2如果你的业务系统不想走独立的Agent进程PlumeLog也提供了Log4j2的Socket接入方式。这种方式适合应用本身能方便添加依赖的场景配置如下先在pom.xml中加入依赖dependency groupIdcom.plumelog/groupId artifactIdplumelog-log4j2/artifactId version1.3.0/version /dependency然后在log4j2.xml里配置AppenderAppenders Socket nameplumeLog host192.168.1.100 port9900 protocolTCP PatternLayout pattern%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n/ /Socket Async nameasyncPlume AppenderRef refplumeLog/ /Async /Appenders同步改成异步的意思是业务线程写入日志时不直接发送网络IO而是先放到一个队列中后台线程批量上报。这样既不影响业务性能又能保证日志不丢。AsyncAppender的队列大小默认是1024如果你的单机日志激进一些建议调成bufferSize8192。3.3 控制台查询和统计的玩法日志接入后打开控制台的“日志查询”页面能看到按应用名筛选、按日志级别筛选、按关键字搜索。这条查询语句走的是ES的全文检索速度非常快。我日常排查问题用得最多的是两个功能TraceId检索如果你的系统在日志中打印了链路ID直接在搜索框输入TraceId几秒钟就能把一次请求在多个服务间的完整调用日志捞出来。这一点在微服务排障中确实是刚需。日志级别占比统计通过仪表盘看WARN和ERROR的占比趋势能提前发现系统走向异常的苗头。我曾经通过这个统计发现支付服务在某个时间点ERROR日志突然上升提前在用户投诉前定位到了问题。3.4 告警规则配置与通知接入PlumeLog支持关键字告警和日志级别告警配置路径在“告警管理 - 新增规则”这里分享下我配置关键字告警的示例规则名称支付超时异常应用名pay-service关键字queryOrderTimeout统计窗口5分钟触发阈值3次通知方式Webhook/邮件通知渠道建议优先配Webhook因为有现成的机器人接口发到团队群里全员都能看到。告警触发之后控制台会生成一条告警记录点击可以查看命中的日志原文这对快速定位问题很有帮助。我第一次配置时漏了“关键字”的填法——它支持正则表达式而不是简单的contains匹配。比如要匹配“订单创建失败”和“订单创建超时”我直接写订单创建(失败|超时)就可以了不需要配两条规则。4. 常见问题与排查技巧实录4.1 日志不采集的三大原因日志接入了但控制台搜不到数据是最常遇到的问题。我总结三个高频原因检查Kafka连通性在业务服务器上执行telnet 192.168.1.100 9092连不上就去看Kafka的listener配置。如果Topic没有自动创建需要打开Kafka的auto.create.topics.enable参数或者手动创建kafka-topics.sh --create --topic plume_log_topic --partitions 3 --replication-factor 1 --bootstrap-server localhost:9092。检查ES索引是否生成访问http://192.168.1.100:9200/_cat/indices看看有没有类似plume_log_2024.xx.xx的索引。没有生成说明消费端没正常运行去Consumer日志中排查解析错误。文件路径和扫描权限Agent的plume.agent.files路径写错了或者/data/logs/app-demo/目录没有读取权限Agent日志里会报AccessDeniedException。用chmod -R 755能解决大部分权限问题。4.2 ES写入性能瓶颈怎么破日志量每天超过500GB之后ES单节点的写入会明显变慢具体表现是Kafka消费组Lag不断上涨。我调优经验包括加大ES的批量写入线程数在Consumer的配置里调整plume.consumer.batch.size5000配合plume.consumer.concurrent.threads8可以显著提升消费吞吐。使用SSD磁盘ES写入是磁盘IO密集型操作机械盘在大量写入时性能衰减严重换上SSD之后同样的集群配置写入性能翻倍不夸张。合理设置索引分片数单分片的索引并发写入能力有限我已经将按天索引的分片数设定为3或5具体取决于节点数规则是“一个分片不超过30GB”。4.3 日志查询变慢怎么办查询慢通常跟ES的查询深度有关。PlumeLog默认查询是翻页拉数据当from size超过10000时会报错控制台会提示“日志数据量大建议缩小时间范围”。解决办法有两个一个是尽量用筛选条件缩小数据量避免一次性全量查询另一个是在查询界面的“时间范围”选择上不要默认选“今天全部”尽量设置到小时级别查询速度会明显改善。4.4 常见问题速查表问题现象可能原因解决思路Agent启动正常但Kafka无消息文件路径配置错误/权限不足检查采集路径查看Agent日志消费端启动报ES连接异常ES地址配置错误或ES未就绪确认ES健康状态调整端口和协议控制台页面显示500MySQL连接失败或初始化表缺失检查数据库配置重新导入SQL脚本日志重复上报游标文件被删除或重置清理agent日志缓存文件重新采集搜索关键字无结果字段分词策略不匹配使用ES的match_phrase语法或keyword字段告警误报频繁规则阈值设置过低调高统计窗口或添加正则排除项4.5 几条“过来人”的避坑建议最后写几条个人体会也许能帮你少走弯路第一不要在日志采集端做复杂的字段解析。日志系统首要职责是“收得全、存得住、查得快”字段解析、结构化抽取这些工作可以放在消费端统一处理。如果所有解析都写在Agent侧每改一次解析逻辑都要重新发布Agent运维成本不可控。第二ES的索引生命周期管理ILM必须提前配好。很多团队用PlumeLog半年后才发现ES磁盘爆了原因就是索引没有自动清理。PlumeLog的ES索引是按天切割的但注意保存时间不会自动设置我建议在ES层面设一个策略保留30天、超过30天自动删除索引。脚本很简单网上搜一下就能找到但这个操作一定要做。第三日志系统的告警规则不要贪多。我见过有人一上来就配置了几十条规则结果每天告警轰炸最后重要的告警反而没人看了。我的习惯是“核心应用先设置ERROR级别告警和系统关键字告警稳定之后再逐步细化”先保证不漏重要故障再保证不被打扰。5. 从能用走向好用一套自建日志系统的延展思考PlumeLog解决了“日志从分散到聚合”的第一步但真正把日志用起来、变成数据资产还有很长的路可以走。除开上文提到的查询和告警闭环我在实际项目中还做了几件事供你参考。一是将日志数据和业务监控指标打通。PlumeLog的统计页只能看日志本身的占比和趋势但如果你想了解“某个接口在发出大量ERROR日志时它的RT指标和QPS是多少”需要把日志系统的输出接入到Prometheus或者Grafana体系里。技术实现上不难用Logstash或自研脚本定时从ES查询异常日志量推到Prometheus再由Grafana统一展示。二是在日志平台之上做沉淀错误码和知识库。通过PlumeLog的告警记录我按周汇总Top10的ERROR关键字形成一份历史问题台账。每一次线上故障处理完毕把时间窗口内的日志链接存到团队Wiki里下次再出类似问题时三分钟就能重现上次排查路径节省的时间非常可观。三是关注日志脱敏。业务系统日志里经常会有手机号、身份证号等敏感信息直接采集到ES里存在合规风险。我在方案设计时加了一条规则所有落地到日志存储的字段必须先经过脱敏过滤器。如果你也有合规要求一定要在日志配置阶段就加入脱敏逻辑而不是事后从ES里清洗。这套日志系统上线后我的核心感受是它不像很多大数据项目那样一开始就要“规划宏大的数据中台”而是先把最急迫的“日志看不清、查不快、告不了警”这些痛点解决掉。等团队习惯用数据排查问题之后再慢慢迭代替换组件这是一个很务实的演进路径。我在实际使用中还有一个特别深的体会日志平台的价值取决于团队用不用得起来。如果你只是搭好了给老板看那它永远只是个摆设。一定要把PlumeLog的查询入口放到开发工具导航页的第一屏让每个人遇到问题第一时间想的是“去日志平台搜一下”而不是“去服务器上找日志”这个习惯养成了整个团队的排障效率会有一个天翻地覆的提升。就聊到这里吧开源世界变化很快PlumeLog也不一定是最终解但把它吃透、用好你一定能收获一套属于自己的日志排查方法论。如果你在接入过程中踩了什么不一样的坑欢迎随时来找我交流。
返回列表