共计 5102 个字符,预计需要花费 13 分钟才能阅读完成。
简介:NBF 是阿里巴巴供应链中台的根底技术团队打造的一个技术 PaaS 平台,她提供了微服务 FaaS 框架,低代码平台和中台基础设施等一系列的 PaaS 产品,旨在帮忙业务搭档疾速复用和扩大中台能力,晋升研发效力和对外的商业化输入。事件核心就是 NBF 系列技术产品中的一员。本文首先介绍事件驱动架构的概念及实用场景,而后会介绍事件核心产品的设计和实现。
作者 | 林晖
起源 | 阿里技术公众号
一 业务背景
电商平台供应链的业务场景非常复杂,技术中台须要反对非常复杂且一直变动的业务需要,构建了数量繁多且严密耦合的业务链路,为技术架构的保护带来了压力。
1 问题形容
上图是一个典型的业务架构,A 域是上游域,B 域和 C 域是上游域。A 域在收到内部调用申请时,首先同步调用 B 域的服务接口实现同步业务逻辑,而后发送音讯告诉到 MQ。C 域异步生产音讯后,反向调用 A 域的接口查问详细信息,实现异步业务逻辑。
这种架构的问题包含:
- A 域强依赖 B 域的接口,B 域接口变动会导致 A 域调用失败,而 A 域无奈管控 B 域的接口变动;
- C 域收到音讯后须要反查 A 域的接口,对 A 域造成了双重依赖,A 域接口和音讯格局的任何变动及不稳定性都会影响 C 域;
- A 域的音讯和接口都是刹时数据,两者因为时间差可能不统一,减少了 C 域解决的复杂度(例如:C 域收到的音讯是单据已创立,调用接口时查到该单据已完结);
- A 域须要保障同步调用和音讯告诉的一致性,包含 MQ 不可用等状况产生时的容灾解决
面对这些问题,咱们心愿利用事件驱动架构的个性来解耦子域,升高业务链路复杂度,构建稳固并向前兼容的事件契约,从而晋升全域的稳定性。
2 事件驱动架构的利用过程
- 从新梳理全链路业务流和业务流动,建设对立的规范语言;
- 定义规范的事件格局和通用根底字段;
- 各域定义蕴含残缺业务语义、自闭包、多租户的畛域事件;
- 开发并接入一套适应供应链业务特点的事件零碎(NBF 事件核心);
3 对于 NBF
NBF[1] 是阿里巴巴供应链中台的根底技术团队打造的一个技术 PaaS 平台,全称是 New-Retail Business Factory,她提供了微服务 FaaS 框架,低代码平台和中台基础设施等一系列的 PaaS 产品,旨在帮忙业务搭档疾速复用和扩大中台能力,晋升研发效力和对外的商业化输入。事件核心就是 NBF 系列技术产品中的一员。
本文首先介绍事件驱动架构的概念及实用场景,而后会介绍事件核心产品的设计和实现。
二 什么是事件驱动架构(EDA)
1 畛域事件
很多同学会将事件和音讯混同。在业务零碎中,事件指的是畛域事件,而音讯能够是任意数据或数据片段。畛域事件的特点包含:
- 与服务接口一样有残缺的 schema,并保障 schema 向前兼容;
- 是业务流程的一部分,由业务动作触发,蕴含了残缺(或局部但有独立语义)的业务状态变动;
- 事件消费者接管到事件后,相应批改本身的业务状态,并按需收回新的事件;消费者须要保障所有事件最终生产胜利,否则会导致业务流程不残缺;
- 事件须要长久化保留并长期归档,不便业务同学查问、复原中断的业务流程、从新发动业务流程等,也不便风控及财务剖析同学做离线剖析。
2 事件驱动架构的概念
和很多架构名词相似,事件驱动架构并没有一个明确的定义和能力范畴。Martin Fowler 在 2017 年的文章[2] 中形容了与事件驱动架构相干的一些次要模式。在本文中,事件驱动架构的概念具象为由畛域事件驱动的业务流技术架构。每一个畛域事件都对应一个业务流中的具体流动(如洽购单建单),而事件就是流动产生导致的后果(如洽购单建单实现事件),事件内容就是流动导致的残缺状态变动(如洽购单 + 子单列表)。
3 事件驱动架构的长处
在 Fundamentals of Software Architecture[3] 以及 Microservices Patterns[4]等书中形容了事件驱动架构的一些显著特点,咱们总结为以下几项:
- 高度解耦
- 播送能力
- 纯异步调用(Fire and Forget)
- 灵便扩大
- 高解决性能
4 事件驱动架构能解决什么理论问题
上面咱们举几个例子来形容事件驱动架构的解耦和播送能力如何帮忙解决事实工作中的问题:
解耦能力
在基于申请 / 响应形式的服务化架构中,上游服务依照约定的 RPC 接口调用上游服务,这样有一个比较严重的问题:上游服务作为数据(例如业务单据)的生产者,强依赖了作为数据生产方的上游服务所定义的接口,导致上游服务本身无奈积淀接口和数据规范。
一种更正当的计划是依赖倒置:由上游服务定义 SPI,上游服务实现 SPI,这样,上游服务终于有机会积淀出本身的接口和数据规范,不再须要适配各个上游服务的接口,而是由上游服务的开发者依照接口文档来做实现。但这种设计依然无奈解决运行时上游服务依然依赖上游服务的问题,上游服务的可用性、一致性、幂等性能力会间接影响上游服务的相干指标及实现形式,须要上下游服务开发者一起对齐计划,在出问题时一起解决。
应用事件驱动设计能够实现契约定义和运行时的全面解耦:上游服务能够积淀本人的事件契约,在运行时无论是上游服务还是上游服务都只依赖事件 Broker,上游服务的可用性和一致性等问题由事件 Broker 来保障。
播送能力
在供应链中台这样简单的微服务架构中,要害的上游服务往往有多个上游服务,上游服务个别须要程序或并发调用所有的上游服务来实现一次残缺的调用。
上游服务的开发者会面临多个难题:
- 服务的可用性会被上游服务影响;
- 服务的 RT 本人无法控制;
- 上游服务之间的一致性如何保障;
- 如何实现一套牢靠的重试机制;
而上游服务的开发者也有本人的问题:
- 每接入一个上游服务都须要跟服务开发者排期:谁来答疑,什么时候联调,什么时候上线;
- 上游流量如何做过滤,顶峰流量是否能抗得住;
- 如何满足上游服务的可用性及 RT 要求;
应用事件驱动架构人造能够防止上述问题:
- 上下游齐全解耦,上游服务只有保障将事件胜利发送到 Broker,无论有几个上游消费者,都不会影响本身的 RT,也不须要思考上游服务之间的一致性;
- 上游服务在接入新的事件时,只须要在事件治理服务中走完订阅审批流,不须要期待事件发布者排期和联调;
- 通过事件 Broker 提供的事件过滤能力,上游服务只须要生产与本身相干的事件流量(例如:天猫超市的计费服务只须要生产 tenantId 为天猫超市的洽购单创立事件,而不须要生产银泰租户的洽购单创立事件);
- 通过事件 Broker 提供的事件存储能力和重投能力,即便上游服务发送的事件流量超过了上游服务的解决能力,也只会影响上游服务的生产提早,不会导致大量申请失败的状况。
5 事件驱动架构不适宜什么场景
- 强依赖 Response 的场景,例如单据查问、商品查问;
- 对全局解决提早敏感的场景,例如游戏、搜寻;
- 要求服务之间放弃强一致性的场景;
三 事件核心的功能设计
作为面向中台的事件中间件,事件核心集成了消息中间件 MetaQ(RocketMQ),初始应用体感也与 MQ 很像,但事件核心有很多不同的功能设计:
- 欠缺的权限管制;
- 反对事件契约定义以及运行时合法性校验;
- 反对大事件发送和生产(10MB 或更高);
- 反对长期的事件历史查问、事件索引查问(如单据编号、sku)、事件重投;
- 反对生产周期很长的事件(如须要几个月能力完结的入库单);
- 所有事件及生产记录的残缺归档;
- 以 OpenAPI 的模式凋谢了事件查问、事件重投等运维态的性能,不便被其余系统集成。
四 事件核心的运行时架构
事件核心运行态次要由以下局部组成:
1、事件核心服务 /SDK
a) SDK:蕴含事件收发的次要逻辑,反对事务发送和一般发送,反对事件校验、压缩、本地备份;
b) Tunnel Service:一层很薄的数据库代理服务,反对按利用、事件、场景、IO 维度的限流,反对数据库疾速灵便扩容;
c) Index Service:事件索引服务,通过精卫(DataX)获取 Binlog,解析为索引后写入索引表(Lindorm)。
2、阿里中间件
a) Diamond(Nacos):蕴含利用相干的全副配置信息,如发送、订阅关系、事件定义、中间件配置等;
b) SchedulerX:调度 SDK 执行事件从新发送、从新生产、事务异样状态问询;
c) MetaQ:次要的事件收发管道;
d) TDDL(RDS):事件内容及生产记录存储;
e) 精卫:用于生成索引、计算提早等异步解决逻辑;
f) Lindrom(serverless):用于寄存事件内部索引,serverless 模式反对按量付费和弹性扩容,性能比较稳定。
下图为简化的运行时架构图,图中蓝色线条示意事件的失常收发链路(事务发送),红色线条示意事件的异样解决链路。
1 事件发送与生产流程
事件构造
运行时的一条事件实例由三局部组成:
1、事件 ID:全局惟一,格局为“逻辑库编号_月内发送日期_uuid”,例如 01_11_f75ec4fb347c49c4bc3e93xxxxxxxx,其中逻辑库编号用于逻辑库路由,日期用于事件清理;
2、事件 Head:蕴含事件元信息,如 trace 信息、发送者信息、事件大小、MetaQ 信息等,参考示例:
3、事件 Body:JSON 格局,蕴含由用户已定义的事件内容,事件内容要合乎事件定义契约,否则会被回绝发送。
运行时的事件可能有多个生产方,每个生产方会产生一条生产记录,生产记录蕴含:
- 事件 ID
- 生产信息:生产状态、生产次数、下次生产工夫等
事件发送流程
事件核心反对事务发送和非事务发送两种模式,应用状态机驱动,API 设计与 MetaQ 的 API 基本一致。以下以事务发送为例介绍发送流程,因为非事务发送的流程更简略,所以不再具体介绍。
1)事务发送状态机
2)事务发送时序图
3)异样状态事务问询
事件生产流程
事件生产流程也应用状态机驱动,API 相比 MetaQ 有一些不同:
- 不须要再调用 subscribe topic;
- 新增生产过滤器 EventFilter,反对依照租户、业务流、事件维度做过滤;
- 反对不同的事件应用不同的 Listener 生产;
1)事件生产状态机
2)重试周期
事件进入生产失败状态后,事件核心会周期调用用户 Listener 从新生产,生产周期以 5s 起始指数减少,最多重试 15 次,最大为 5 * 214 = 81920 秒(约 22 小时)。
3)事件生产时序图
2 事件存储
数据表
事件核心应用了 32 分库的 TDDL,依照 HASH(事件 ID)做分库,每个库上有以下几张表:
- 事件主表,蕴含发送者信息、事件信息以及一般事件的事件体;
- 事件生产记录主表,蕴含消费者信息、生产状态以及从新生产信息,与事件主表通过事件 ID 关联;
- 大事件主表,蕴含大事件体,与事件主表通过事件 ID 关联;
- 事件天表,表构造与事件主表雷同,寄存生产结束的事件;
- 生产记录天表;
- 大事件天表;
事件生命周期
- 新写入的事件和生产记录会进入主表;
- 当事件写入超过 1 天,且事件的所有生产方都生产胜利后,事件及所有生产记录会从主表挪动到天表中;
- 当事件某个生产方须要从新生产之前生产胜利的事件时,事件及所有生产记录会从天表移回到主表中;
- 每天的某个工夫,事件清理服务会将 7 天前的那张天表清空,例如明天是 2 月 11 号,那么就会清空 2 月 4 号的所有天表。
3 内部索引
事件发送历史列表、事件索引查问和事件重投是事件核心运维平台的次要性能。其中索引查问性能的查问速度快、查问后果精确,用户反馈始终比拟好。
索引配置
用户在批改事件定义时,能够为其中任意根底类型字段配置为“查问字段”,事件核心会在运行时解析该字段的值,并创立索引;一个事件中的每个查问字段都会对应一条索引;即便没有配置查问字段,也会生成一条蕴含工夫戳的索引,用于已发送事件的排序和分页。
索引构造
事件核心的索引为 KV 构造,应用 Lindorm 的宽表存储,按应用场景分为两种类型:
- 不蕴含查问字段的索引;
- Key 格局为 HASH(租户 id_事件 code)_env_发送工夫差值_事件 ID;
- Value 为事件 ID、事件头;
- 蕴含查问字段的索引;
- Key 格局为 HASH(租户 id_事件 Code_字段门路_索引值)_env_发送工夫差值_事件 ID;
- Value 为事件 ID、事件头;
其中
- 发送工夫差值 = Long.MAX_VALUE – 发送工夫毫秒数,用于按发送工夫倒序展现;
- 字段门路是 json path 格局,例如 $.bizNo;
查问性能
通过目前事件核心运维平台 99% 的查问都能够在毫秒级别返回后果,Lindorm 索引行数在十亿级别。
五 总结
本文介绍了事件驱动架构在供应链执行链路的利用背景和实际过程,并介绍了 NBF 事件核心产品的设计和局部实现。目前事件核心每日事件发送量峰值在千万级别,安稳度过了双 11、双 12、年货节等流量顶峰。
[
原文链接](http://click.aliyun.com/m/100…)
本文为阿里云原创内容,未经容许不得转载。