事件驱动让服务松绑,但顺序乱了就还得能追回去
事件驱动让服务彼此松绑,松绑之后新增消费者不影响发布者,影响不到发布者系统才稳。但事件这东西顺序一乱、重复一来,比同步调用更难查,难查在链路看不见。一、命名讲人话
看不懂的事件,排查时只能翻代码反推,反推错一次方向,方向错查三天白查。事件追溯要靠编号串,串起来才能把一笔业务从头到尾拼出来。上下文边界画清楚,两个团队改同一块的概率就小,小了冲突少。
命名还要体现业务动作,体现动作而不是技术动作,技术动作如保存到哪。保存到哪是内部细节,细节进事件名,后人看名以为业务含义如此,以为错了就照错理解。事件命名要讲人话,讲人话的团队隔半年还看得懂当时发的啥。公共能力抽出来单独放,放出来别的服务才不用各写一份。边界模糊的地方单列出来,单列了专门有人拍板不悬在空中。
二、顺序乱了要重排
谁先谁后搞反,状态机走到错误分支,分支里逻辑一路往下错,错到对账时才发现差了十万八千里。消费者挂了事件要留,留着的人回来能补齐,补齐才不漏。上下文之间只通过明面接口说话,私底下绕过去早晚出乱子。
重排靠事件里带的时间戳或者序号,带了的才能排,排得对状态才对。对的状态是后续一切的基础,基础歪了上面建什么都斜,斜着建不如推倒重来。事件顺序乱了要有重排,重排不了就追不出到底谁先谁后。拆分要循序渐进,一上来全拆往往拆出一堆难以维护的碎片。上下文不要按部门凑,凑出来的边界往往和真实业务对不上。
三、消费者要幂等
多算一笔的账目对不上,对不上财务来找,找技术查,查到是重复事件,重复事件说明中间件重投了。事件风暴要常做,常做团队对业务流转的理解才不脱节。共享模型要谨慎,一谨慎才不致把一个团队的词强塞给另一个。
幂等靠业务主键去重,靠主键而不是靠运气。靠运气去重,运气差的那天漏一个,漏一个数据就多一份,多一份的报表递上去,上去就被领导打回来。事件消费者要幂等,幂等做不到重复发一次就多算一笔。团队结构照着服务划,划清楚了谁负责哪块不用天天扯皮。
四、丢了要有感知
缺角的报表看起来正常,正常到没人怀疑,怀疑不起来直到月底盘点,盘点差一笔找不出源头。拆分先看业务边界,边界看错了拆出来的服务互相纠缠更费劲。边界变更要走评审,评审过了再动,动错了影响面比想象广。
感知靠对账或者死信,对账定期对,死信收异常。收了异常的集中处理,处理掉缺的角能补,补上报表才齐,齐了的账审计才过,过审计不提心吊胆。事件丢了要有感知,感知不到丢了的那个环节数据悄悄缺角。拆分后接口要先稳,稳了才敢让别的服务依赖,依赖上就难改。
五、结构定义要版本化
打挂的表现是反序列化报错,报错一片消费者停,停了事件堆积,堆积撑爆中间件。拆太细调用链变长,长链上任何一环抖都拖慢整笔请求。上下文内的术语要统一,统一了新人进来才读得懂彼此的代码。
版本兼容要向前,向前兼容老消费者读新事件不报错。不兼容的改动要发新事件名,新名字老消费者忽略,忽略安全,安全比强行兼容省心,省心不易错。事件结构定义要版本化,版本化了老消费者才不会被新格式打挂。数据跟着服务走,数据不拆的话服务拆了也只是表面文章。
六、追溯靠编号串
拼不出来就断在某一环,断环的业务说不清谁触发了谁,说不清责任,责任模糊互相推。拆太粗又回到大单体,大单体改一处要全量发,发一次全停。跨上下文调用要记账,记账后能看清依赖的重心在哪,重心失衡要命。
等的表现是发布者被消费者拖慢,拖慢了本该快的写接口也变慢,变慢用户直接感知,感知差就流失。发事件别顺带做重活,重活塞进去一发慢全场都跟着等。拆分评审拉上运维,运维早介入少踩部署和监控的坑。
事件驱动把服务从硬调用里解放,解放出来才容易扩,但解放不等于放任。命名、顺序、幂等、感知、版本、追溯,六件事做细,事件才真解耦,不是制造一堆看不见的乱麻。 虽然有些地方不太懂,但整体看完还是收获很多,慢慢消化一下。 这个话题确实很值得讨论,我也有类似的经历,非常认同楼主的观点。
页:
[1]