应用调用链路为
X -> H (一个消息推送的聚合应用) -> E(提供用户信息的各种接口)
H -> 其他接口发送各种消息
X 应用反馈发出的钉钉通知部分新入职的员工无法收到
排查 H 应用日志:
1.发现 H 应用接受到了 X 的请求,但是发送的目标 id 在 H 的逻辑中被过滤掉了导致最终没有发送出去.
2.开始在逻辑中+日志复现请求排查.
3.发现 H 应用缓存了用户信息,而不是每次从 E 应用拿员工信息. H 请求 E.get_by_ids/E.get_by_names 接口的内容进行了缓存.
4.从 Redis 中读取对应用户的缓存信息证实由于 data 中缺少 user_id 字段,所以被 H 应用过滤掉了发送目标,导致没有发送出去.
5.在测试环境无法复现相同的问题,任何情况下 E.get_by_ids/E.get_by_names 接口都会返回全量的用户的信息字段.但是在线上偶现
开始排查 E 应用:
1.仔细翻看代码后发现 E.get_by_ids/E.get_by_names 两个接口逻辑不一致
ps: 后来发现此处有 2 个名单来控制权限 W1 和 W2 ,H 在 W2 中,但是不在 W1 中
2.get_by_ids 接口会根据来源方应用判断是否返回 user_id 这个字段.(后面证实逻辑为只判断了 H 应用是否在 W1 名单)
3.get_by_names 接口会直接判断来源方,如果不允许的来源方直接拒绝。但是一旦返回就是完整数据.
4.此处没有日志,但是根据逻辑基本判断出来是由于 get_by_ids 逻辑判断有问题,加了日志打印后证实。
开始梳理整个 bug 出现的原因:
1.H 应用对外也提供了 H.send_by_ids/H.send_by_names 两个接口,对应调取 E.get_by_ids/E.get_by_names
2.又因为对 E.get_by_ids/E.get_by_names 调用结果进行了缓存,并且 redis 的 key 没有设置过期时间!!!
3.新用户一旦先调用 H.send_by_ids 接口,获取到不带 user_id 的 data 后,后续再也无法正确推送过去。
4.此处又有疑惑,按这个逻辑不应该只会发生在新用户身上啊,老用户按理也会遇到这个问题???
5.继续查看 H 应用的逻辑,发现启动时会全量覆盖一遍当前的缓存,此处调用 H.list_all 接口,此接口没做任何限制,所以能拿到 user_id ,所以这个逻辑问题已经存在 2 年了,一直没有其他人反馈过
开始修复:
1.修复了 E 应用里面 get_by_ids 逻辑与 get_by_names 保持一致(由于不敢大改逻辑,又添了一堆屎上去)
2.修改 H 应用缓存 key 增加了过期时间,然后清理了历史的所有的 redis key (此处有大坑)
3.自信发布后 X 应用负责人表示问题解决了,又开始摸鱼
没多久 A 应用开始反馈调用 H.send_by_ids([张三,李四]) 接口开始报错,提示用户张三不存在。。。
经排查后用户张三是因为已经离职所以接口提示不存在!
但是 A 应用反馈之前一直这样发的也没有报错过, 并且李四也能正确接受到消息。。。
又去仔细翻看 H 应用相关的代码 发现了里面有一段逻辑是判断调用方输入的列表和从 E/缓存 拿到的数据是否一致(判断是否有不存在的人员),此处现在两个列表不一致导致抛出的 not_found error
思考和梳理原因:
1.之前由于 redis key 没有设置过期时间,所以离职的张三信息一直在缓存中,一直能拿到对应的信息!!!
2.刚才清理了所有的 key 之后现在拿不到了,所以提示张三不存在!!!
解决办法 1:
想让 A 应用调用之前判断一下是否存在这个用户,不要把不存在的发过来,A 应用表示段时间内做不到,需要改的地方太多了……
解决办法 2:
1.新增 send_by_ids_v2 接口,支持 ignore_miss 参数
2.A 应用修改源码调用 send_by_ids_v2 接口
最坑的是,这个问题只有在线上能复现,又缺少日志,所以排查问题及其困难!!!然后 H ,E 应用的开发全部已经跑路了.
后来发现其他环境无法复现是因为 E 应用只在生产进行了权限判断,在某个配置里面把其他环境的都关了……
修改和查看代码过程中很多奇怪的逻辑不敢改,怕改坏了又影响其他应用……
至此结束了此次 bug 的问题,在一堆屎山里面找逻辑,还不敢随便改看起来很奇怪的逻辑
又因为上述原因又堆了几坨屎上去
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.