基于 swoole 的多进程消息同步微服务 -- (3)实现 swoole 多进程消息同步微服务

本篇主要内容是介绍如何实现,实现过程分两个方面; 在系统顶层架构方面,需要严格控制由 Swoole Manager 进程 fork 出来的几个逻辑顶层的进程的生命周期,其中: 1、Logagent 进程用于记录系统内部错误、警告日志; 2、Check 进程用于检测各个 logstore 的 shard 数据; 3、Monitor 进程主要检测各个进程的心跳,保证进程运行正确;

2、3两个点是在坑中拆分的,描述下坑的原委,一版的设计中将原先 check 逻辑与心跳逻辑全部写在 monitor 进程中,不过在有一段时间之后发现 monitor 莫名卡死,导致进程 down 之后没办法重新拉取,出现大面积丢失数据的情况,仔细排查原因之后发现:主观原因上, check 过程是一步 curl 请求,在网络抖动和阿里云不稳定的情况下极易导致 monitor 进程异常;客观原因在每隔一两个星期,阿里云日志服务会在晚上零点附近重启服务,此时 puller 进程无法拉取数据直接 down 掉,而阿里云日志拉取的 php sdk 为 curl 的 CURLOPT_TIMEOUT 设置为 5184000(github 修改记录戳我),默哀~;最终的结果就是导致大 boss 差点把我弄死。

然而这还不算完,在业务端中拉取的数据存储到数据库中之后,如何确定数据是正确的?无奈之下只能实现一套根据业务端需求变化而变化的数据校验任务,而这个功能我选择在 crontab 中完成而不是微服务中,理由不赘述; 项目代码属于公司,恕不能开源,之后如果时间足够,我会根据自己的想法重写一套自己的代码。至此“基于 Swoole 的多进程同步微服务”博客记录就完成了 :)

接下来是我在编程中所经历的一些坑的经历和其他,自勉:

一、一次bug的调查

现象:

1、截止写报告时间为止,未出现数据丢失问题。

2、在网络抖动很频繁的情况下,多次出现了服务重启情况,在高峰期是出现了很多的数据重复(依靠mysql unique 索引去重),其中最近一次为11月24号下午三点到八点期间因网络抖动出现几十次服务重启,在日志上可以看到重复数据达到几万条;

数据丢失原因: 1、线上 libcurl 库版本过低,monitor进程卡死导致puller 进程卡死未能及时发现,出现数据丢失由使用者(教师)反馈问题到团队运营人员再反馈到开发人员;

结论: 阿里云可以正常运行,数据丢失属于偶发性底层故障,可通过分离阿里云服务和其他服务、升级服务器中底层依赖库保证阿里云日志拉取的稳定;

数据丢失解决方案如下: 1、check 脚本定时执行检测数据正确性; 2、出现错误之后将人工检测,在日志、数据库、脚本等方面手动再检测一遍是否出现问题,定位问题后判断是否需要执行 recovery 脚本,执行 recovery 之后将最后的结果保存在当前redis 0 库中的 ws_aliyun_pull_log 这个hash 字段,需要通过STARTTIME_ENDTIME_MODEL 组合而成字段取得序列化过的字符串,数据中保存了完整的检查结果; 3、与同事A协商报告的 recovery 方式,通过 recovery 调用接口exec执行;

二、数据校验 1、检测脚本的运行逻辑:

前提:check 脚本检测一小时内的数据量,同步回退一分钟保证数据确定同步;

运行逻辑:php-fpm 方式 http curl 拉取某个 logstore所有数据(这里是有分段拉取逻辑的,不赘述),按照与阿里云日志拉取中完全相同的过滤逻辑对每个数据表应有的数据数量进行统计,最终比较数据库应有数据量和check 脚本检测数量是否相同,不同则发送报警信息到开发者钉钉。

2、数据 recovery 类运行逻辑: 前提:在接收到check脚本发送而来的钉钉报警信息之后,开发人员将登陆服务器检测当前日志,在确定发生了数据丢失之后运行recovery脚本对某个数据表进行恢复; 运行逻辑:根据标准输入的待恢复数据表,查询指定时间段内数据表中的数据,并通过unique 字段组成 hashmap 存放于php 内存中(memory_limit:5GB,测试峰值不会超过1GB,数据量10W),在通过 php-fpm 方式 http curl 拉取某个logstore中对应到某个表中的所有数据(这里有分段逻辑),逐一对比找到那些阿里云中存在但是数据库中不存在的数据并保存下来,最后通过对应的consumer类消费对应数据;

Last updated