【基于 Swoole+Hyperf 的微服务实战】第十一周·周二:构建异步日志采集与分析系统
【基于 SwooleHyperf 的微服务实战】第十一周·周二构建异步日志采集与分析系统今天我们进入第十一周周二继续构建异步日志采集与分析系统。昨天我们实现了日志接收服务将日志投递到 Kafka。今天要打造系统的消费与存储能力编写 Kafka 消费者拉取原始日志解析富化后批量写入 Elasticsearch让日志可被搜索、分析和可视化为后续的实时统计打下数据基础。今日目标创建log-consumer服务配置 Kafka 消费者与 Elasticsearch 客户端。实现消费者拉取raw_logs消息解析User-Agent、IP归属地等字段丰富日志内容。使用批量写入的方式将日志索引到 Elasticsearch提升吞吐效率。验证日志能通过 Kibana 搜索并观察消费者组的并行处理能力。配置消费者 Offset 自动提交保证消息不丢失、不重复。一、环境准备约 30 分钟1. 启动依赖确保 Kafka、Elasticsearch、Kibana 容器运行Elasticsearch 已在第六周部署若未部署请参考docker-compose.yml添加。确认 Kibana 可访问http://localhost:5601。2. 创建消费者项目docker-composeexecswoolebashcd/var/wwwcomposercreate-project hyperf/hyperf-skeleton log-consumercdlog-consumercomposerrequire hyperf/kafka elasticsearch/elasticsearch hyperf/redis hyperf/metric端口设为9601项目专注于消费可以不需要 HTTP 服务或保留简单健康检查。3. 配置 Kafka 消费者编辑config/autoload/kafka.php增加消费者配置consumers[[topicraw_logs,group_idlog-processors,client_idlog-consumer-1,auto_commitfalse,// 手动提交 offset保证处理完再提交enable_auto_commitfalse,max_poll_records500,// 一次拉取最大条数consume_timeout3000,],],4. 配置 Elasticsearch创建config/autoload/elasticsearch.php?phpreturn[hosts[env(ES_HOST,elasticsearch:9200)],retries2,handler\Hyperf\Guzzle\RingPHP\CoroutineHandler::class,// 协程化 HTTP 客户端];二、知识核心Kafka 消费者组、日志富化与 ES 批量写入约 1 小时1. Kafka 消费者组与分区同一个消费者组内的多个实例或协程会分摊 Topic 的分区实现并行消费。组 ID 必须相同。增加消费者实例时Kafka 会触发 Rebalance重新分配分区。分区数应 消费者实例数才能充分利用并发。Offset 管理我们采用手动提交在处理完一批消息后统一提交确保消息被成功写入 ES 后才标记已消费。2. 日志富化Enrichment原始日志只包含基础信息我们可以添加User-Agent 解析提取浏览器、操作系统、设备类型。可以使用whichbrowser/parser或ua-parser/uap-php库。IP 归属地利用离线库如 GeoIP2或调用内部服务添加国家、城市、ISP。时间戳标准化统一为 ISO 8601 格式方便 ES 的时间字段索引。业务字段补齐根据日志中的service或trace_id关联额外元数据。3. Elasticsearch 批量索引逐条插入 ES 效率极低。我们收集一批消息如 500 条使用BulkAPI 一次性写入可大幅降低网络往返。ES 客户端提供了bulk()方法我们只需构造[body [...actions...]]。三、实战消费者实现与 ES 写入约 2.5 小时步骤 1安装日志富化库composerrequire uap-php/uap-php geoip2/geoip2准备 GeoIP2 数据库如 GeoLite2-City.mmdb放入项目storage/目录可从 MaxMind 免费下载。步骤 2创建消费者类新建app/Kafka/Consumer/LogConsumer.php?phpnamespaceApp\Kafka\Consumer;useHyperf\Kafka\AbstractConsumer;useHyperf\Kafka\Annotation\Consumer;uselonglang\phpkafka\Consumer\ConsumeMessage;useHyperf\Kafka\Result;useHyperf\Di\Annotation\Inject;useElasticsearch\ClientBuilder;#[Consumer(topic:raw_logs,groupId:log-processors,name:LogConsumer,nums:4)]classLogConsumerextendsAbstractConsumer{#[Inject]private\Hyperf\Contract\ConfigInterface$config;private$esClient;private$uaParser;private$geoReader;publicfunction__construct(){$this-esClientClientBuilder::create()-setHosts($this-config-get(elasticsearch.hosts))-build();$this-uaParser\UAParser\Parser::create();// 加载 GeoIP 数据库$this-geoReadernew\GeoIp2\Database\Reader(BASE_PATH./storage/GeoLite2-City.mmdb);}publicfunctionconsume(ConsumeMessage$message):string{$datajson_decode($message-getValue(),true);if(!$data)returnResult::ACK;// 富化if(!empty($data[user_agent])){$ua$this-uaParser-parse($data[user_agent]);$data[browser]$ua-ua-family. .$ua-ua-toVersion();$data[os]$ua-os-family. .$ua-os-toVersion();}if(!empty($data[ip])){try{$record$this-geoReader-city($data[ip]);$data[geo][country$record-country-name,city$record-city-name,lat$record-location-latitude,lon$record-location-longitude,];}catch(\Exception$e){}}// 存入待批量写入的缓冲区使用协程安全的 Channel 或 Redis List// 简单起见每条消息直接记录到内存数组由定时器批量写入本章后面实现// 但消费者是多协程并发需要共享安全队列。我们使用 Swoole\Coroutine\Channel// 在进程启动时创建全局 Channel消费者 push另一个协程 pop 批量写入 ES。// 由于时间关系今天先实现逐条写入性能差明天改造批量。$params[indexapp-logs-.date(Y.m.d),body$data,];$this-esClient-index($params);returnResult::ACK;}}注意逐条写入 ES 性能较差仅用于今天的功能验证。明天我们将用协程 Channel 定时器实现批量写入。步骤 3配置消费者进程与并发在config/autoload/processes.php中添加\Hyperf\Kafka\Process\ConsumerProcess::class。消费者nums: 4表示启动 4 个协程并发消费。步骤 4启动消费者并测试启动服务php bin/hyperf.php start发送日志通过昨天的采集服务或直接向 Kafka 发送测试数据curl-XPOST http://localhost:9600/api/logs-HContent-Type: application/json\-d[{service:gateway,message:request,ip:8.8.8.8,user_agent:Mozilla/5.0 ...,timestamp:2025-01-01T00:00:00}]观察消费者日志确认无异常。然后在 Kibana 中创建索引模式app-logs-*在 Discover 中搜索应能看到富化后的日志包含browser,os,geo等字段。步骤 5验证 Offset 提交消费者抛出异常时消息不会被确认会重新消费。我们可以手动制造异常如暂时停止 ES消息会堆积但不会丢失待 ES 恢复后继续写入。auto_commit设为 false由ConsumerProcess自动在成功返回后提交。四、成果测试与验证约 1 小时测试清单检验项方法通过标准Kafka 消费者连接服务启动日志显示Kafka consumer started日志富化Kibana 查看文档包含browser,os,geo字段多分区并行设置 6 分区nums4日志分布均匀4 个协程各自消费不同分区ES 索引自动创建每天新索引app-logs-YYYY.MM.DD索引自动出现消息不丢失停止消费者积累消息重启后继续消费Kibana 文档数等于发送数错误重试写入 ES 时故意返回错误如端口错消息重新消费不会被跳过性能观察尽管逐条写入较慢但当前功能已跑通。记录消费速率约 200 条/秒为明天批量优化提供基准。五、今日作业与学习产出提交代码消费者服务及相关配置。完善富化添加referer解析提取来源网站。尝试关联trace_id从缓存获取额外上下文。学习笔记画出 Kafka 消费者组与分区分配示意图。解释为什么批量写入 ES 能显著提高吞吐。挑战任务实现死信处理无法解析的日志写入 Kafka 死信 Topic单独监控。使用Elasticsearch Ingest Pipeline替代部分 PHP 富化如 GeoIP减轻消费者负担。今天你成功将原始日志变成了结构化、可搜索的数据资产。明天我们将实现批量写入优化和实时统计让日志分析系统更具实用价值。

相关新闻

nuScenes数据集深入解析:多模态自动驾驶数据读取与坐标系变换

nuScenes数据集深入解析:多模态自动驾驶数据读取与坐标系变换

简介:面向自动驾驶研究与开发者,这份代码包围绕nuScenes数据集的下载、安装与可视化分析展开,完整梳理了1000个复杂场景、40万关键帧、140万相机图、1400万3D标注框以及多传感器配置和23类目标对象的处理逻辑,可帮助中高级算法工程…

2026/10/18 5:40:42 阅读更多 →
LabelImg 目标检测标注工具安装使用与VOC转YOLO实战

LabelImg 目标检测标注工具安装使用与VOC转YOLO实战

简介:LabelImg 是一款基于 Python Qt 开发的开源目标检测标注工具,本教程 PDF 面向机器学习初学者、算法工程师及数据标注人员,旨在解决目标检测任务中训练数据难以快速准备的问题。文档从环境要求讲起,给出使用清华源安装 label…

2026/10/18 5:40:42 阅读更多 →
x64dbg字符串搜索:逆向调试中的精准定位与实战技巧

x64dbg字符串搜索:逆向调试中的精准定位与实战技巧

做逆向调试,拿到一个陌生程序,很多人的第一反应是跟API、翻反汇编,绕来绕去半小时找不到北。我的习惯恰恰相反——先搜字符串。字符串是程序跟用户“说话”的痕迹,也是开发者留在代码里的路标。x64dbg里的字符串搜索功能&#xff…

2026/10/18 5:40:42 阅读更多 →

最新新闻

Servlet+JSP+MySQL:手把手拆解经典Java Web新闻发布系统

Servlet+JSP+MySQL:手把手拆解经典Java Web新闻发布系统

简介:基于Java Servlet、JSP和MySQL的Web新闻发布系统源码,适合正在学习Java Web开发的初学者,以及需要课程设计或毕业设计参考的学生。项目采用MVC分层模式,实现了新闻的发布、编辑、删除和展示,还包含用户登录认证、…

2026/10/18 6:30:52 阅读更多 →
老系统重构实战:从数据库连接池打爆到模块化单体选型复盘

老系统重构实战:从数据库连接池打爆到模块化单体选型复盘

这期节目聊完,我在整理笔记的时候发现,Dirk和Linus两个人聊得最投入、最没有嘉宾包袱的一次,反而是这期讲"旧系统改造"的。原因很简单:他们俩都亲手拆过自己的烂摊子,也都被人用"别动,动了出…

2026/10/18 6:30:52 阅读更多 →
基于SAM的多阶段细化橄榄树遥感分割方案与实践

基于SAM的多阶段细化橄榄树遥感分割方案与实践

做农业遥感这几年,“橄榄树分割”这个需求我前前后后碰过好几回。刚开始觉得这事不难——树冠是圆的、叶子是常绿的,卫星图上看起来就是一片片绿色圆斑,做个阈值分割加形态学处理,应该分分钟搞定。真上了项目才发现,远…

2026/10/18 6:30:52 阅读更多 →
贪吃蛇不是玩具:JavaScript状态机驱动的游戏内核设计

贪吃蛇不是玩具:JavaScript状态机驱动的游戏内核设计

1. 这不是玩具代码,而是一次对前端基础能力的全面压力测试“使用 JavaScript 开发贪吃蛇游戏”——看到这个标题,很多人第一反应是:“老掉牙了,网上教程一抓一大把。”但如果你真去翻过那些所谓“5分钟上手”的教程,就…

2026/10/18 6:30:52 阅读更多 →
自动化测试框架选型:Selenium、Cypress与Playwright深度对比

自动化测试框架选型:Selenium、Cypress与Playwright深度对比

聊到自动化测试框架,圈子里每隔一阵就要吵一轮:Selenium这么老还这么稳,Cypress开发体验爽到飞起,Playwright又带着一堆黑科技来抢地盘,旁边还站着Puppeteer和Appium盯着移动端那块蛋糕。到底选谁?这个问题…

2026/10/18 6:30:52 阅读更多 →
力扣198打家劫舍补充(滚动数组)

力扣198打家劫舍补充(滚动数组)

补充力扣198打家劫舍(动态规划)-CSDN博客的滚动数组写法,只有小改动 原未使用滚动数组代码: class Solution {public int rob(int[] nums) {int length nums.length;if(nums null || length 0){ return 0; }if(length 1){re…

2026/10/18 6:29:52 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →