MQ 正在变成臭水沟

MQ 对于业务系统建模非常重要,是解决分离关注点、依赖反转、CQRS、最终一致等业务问题的重要法宝。

然而企业对于 MQ 中的数据管理却并不重视。从互联网企业发展的历程来看这个问题,最初 MQ 不是很可靠,大家不会把让特别重要的业务依赖 MQ,所以接入到 MQ 的业务事件并不多。总共也就两三个 topic,开发相应的系统对这些内容进行管理看起来没什么必要,甚至可能连详尽的业务信息都要从生产者的代码注释中去寻找。公司规模不大,这些都是可以接受的。

经历过 1Mb 小水管的朋友大概还记得当初火爆的 Flashget 的 Slogan:

下载的最大问题是什么——速度,其次是什么——下载后的管理。

虽然 Flashget 命运多舛,但不妨碍我们学习这种思考方式。当下载任务较多的时候,我们会非常直觉地对下载任务进行多级类别划分(这个目录是游戏;这个目录是用来学习的,那个目录,嗯。。也是用来学习的!),甚至需要给一些任务补充相应的标注(例如这个软件是从哪里下载的;在安装的时候会有什么问题;绕过了什么样的坑才能正确地让它工作)。因为已经使用过太多的工具,受过太多相应的教育和训练,“分类”和“元信息”管理已经深深刻入了我们的思想。

除了分类和元信息管理,对于在下载工具里下载好的任务,我们肯定要试试能不能用,好不好看。如果是垃圾,那自然得删;如果是宝贝,那肯定是要留下来。这可以理解为一种人肉“校验”。

虽然分类、管理和校验是非常显见的道理,在面对同类问题时,很多企业却在此陷入困境。

通常来讲,企业中和 MQ 打交道的团队可以分为三种角色:

  1. 消息生产者,大多为业务流程系统,KPI 是给系统增加功能,加的越多越好,并希望其它部门尽量不要阻碍我们加功能。MQ 里的消息 80% 其实和他们自己的业务无关,主要提供给下游进行统计、计算、判责、场景还原等等。剩余 20% 可能涉及到业务状态流转。
  2. 消息消费者,一般是另外的团队,这里面可能有进行业务指标计算的团队;有基于数据指标做运营的团队;有基于统计接入机器学习(其实也是运营啦)的团队;还有涉及安全、antispam 等等周边支持团队。这些团队对于 MQ 中的数据是非常关注的。
  3. MQ 开发/运维团队,对于这些人来说,MQ 中的数据并不是他们关注的重点。不管你消息长什么样,对于他们来说只不过是一些 byte 数据。他们只关注 MQ 本身的技术特性和运维需求。

三方各怀鬼胎,真正关心 MQ 数据的只有整个消息流的末端团队,因为这里面的数据是真的关系到他们自己的 KPI,要是数算错了钱多发了,薅羊毛的没封了,那都是直接资损。

然而 MQ 两端的业务团队在大多数情况下却是 DDD 中讲的 conformist 关系:

追随者-Conformist
当两个开发团队具有上/下游关系时,如果上游团队没有动机来满足下游团队的需求,那么下游团队将无能为力。出于利他主义的考虑,上游开发人员可能会做出承诺,但他们可能不会履行承诺。下游团队出于良好的意愿会相信这些承诺,从而根据一些永远不会实现的特性来制定计划。下游项目只能被搁置.直到团队最终学会利用现有条件自力更生为止。下游团队不会得到根据他们的需求而量身定做的接口。
这时候“客户/供应商”模式就不凑效了,那么下游系统只能去追随上游系统,下游系统严格遵从上游系统的模型,简化集成。

这些问题本质上是公司的组织架构导致的,但你非要说把安全之类的团队也合并到业务部门来比较扯。很多情况下上下游就是会分属不同部门,这会触发各种意想不到的糟糕问题。所以 DDD 中比这个 Conformist 更靠前的是 Customer/Supplier 模式:

客户/供应商-Customer/Supplier
不同系统之间存在依赖关系时,下游系统依赖上游系统,下游系统是客户,上游系统是供应商,双方协定好需求,由上游系统完成模型的构建和开发,并交付给下游系统使用,之后进行联调、测试。这种模式建立在团队之间友好合作和支持的情况下。当两个具有上游/下游关系的团队不归同一个管理者指挥时,Customer/Supplier这样的合作模式就不会奏效。勉强应用这种模式会给下游团队带来麻烦。

而所谓的 Customer/Supplier 模式又是一种纯粹的理想,是不现实的。部门都拆了,老板总归是不能尿到一个壶里的。虽然现状有点令人绝望,作为技术人员还是希望能有一点曙光。来分析一下这个问题:

无论企业实际使用了上述两种模式的哪一种,消息总还是上游发出的。要求上游系统成为其发出的业务消息的 owner 是一件比较自然的事情。

只有 owner 机制也不够,企业里所谓的业务 owner 所能提供给你的帮助,也就只限于对接的时候负责在工作 IM 上陪你聊天,告诉你这个 topic 里有哪些字段,你需要的字段要用什么样的 jpath 去找。再稍微自觉一点的团队会维护一个文档,介绍领域消息内包含什么内容,做过哪些需求。当文档不是 KPI 的时候,慢慢地也就不再更新了。

这种工作方式把业务信息的维护和上游消息的数据稳定性全部押注在了上游 RD 的良心上,显然是不靠谱的。更好的方式还是用技术手段解决这里的技术问题,可以有以下一些考量:

  1. 由特定团队提供专门的消息生产 SDK,对所有业务消息进行 schema 管理。消息生产环节的代码要求必须提供带特定格式的注释,如:@name 表示字段名,@type 表示数据类型,@enum 提供可能的枚举值。从结构体可以推断出最终序列化后的数据长什么样。并且在代码修改上线时,对代码进行扫描,提取所有相关的业务消息字段注释,自动生成相应文档。
  2. 如果团队技术实力实在不行,做不出自动生成文档的能力。也可以提供一个 schema 管理和异步数据校验的 validation 系统,在系统外部对数据 schema 进行管理,并不断消费上游的消息,以判断新来到的消息是否符合其 schema 定义。若有不符合期望的数据,则对上游值班人进行 on-call 报警,要求修复 schema 描述。

如果实现的是方案 2,理论上还可以开更大的脑洞。除了对 schema 管理外,还可以做一些复杂的逻辑校验,包括对数据的内容,逻辑,连续性,分布进行校验。并由所有下游业务方来配置其期望的校验规则。

后记

虽然本文现在才发,但两年前已经有了相关的想法。期间因为种种原因,这样的平台一直没有办法立项。中间某司断断续续也遇到了无数和上游系统重构导致的下游系统故障的问题,还是没有看到任何改进的迹象。

直到最近看到 Google 的工程论文:data-validation-for-machine-learning。其出发点是为了避免上游的错误数据影响到下游的模型训练结果。但本身 schema 管理,数据 validation 系统是可以泛用的,既然有很多系统依赖上游系统的 schema 和数据正确性,那就应该对这些 schema 和正确性进行管理。

这种成本并不算高的项目,不知道为什么 Google 可以做,可以立项,可以落地,可以发出论文来,而我们自己却对自己没有信心。

Xargin

Xargin

If you don't keep moving, you'll quickly fall behind
Beijing