当前位置: 首页 > 科技观察

NBF赛事中心架构设计与实现

时间:2023-03-14 21:29:25 科技观察

作者|林辉1.业务背景电商平台供应链的业务场景非常复杂,技术中台需要支持非常复杂多变的业务需求,构建了大量紧耦合的业务链接,给技术架构的维护带来压力。一、问题描述上图是一个典型的业务架构,A域为上游域,B、C域为下游域。当域A收到外部调用请求时,首先同步调用域B的服务接口完成同步业务逻辑,然后发送消息通知MQ。域C异步消费消息后,反向调用域A的接口查询详细信息,完成异步业务逻辑。该架构存在的问题包括:(1)域A强依赖域B的接口,域B的接口变化会导致域A的调用失败,而域A无法控制域B的接口变化;(2).域C收到消息后,需要回查域A的接口,这就形成了对域A的双重依赖。域A的接口和消息格式的任何变化和不稳定都会影响到域C;(3)A域的消息和接口是瞬时数据,两者或由于时间差可能不一致,增加了C域处理的复杂度(例如:C域收到的消息是文档有已创建,调用接口时文档已完成);(4)域需要保证同步调用和消息通知的一致性,包括MQ不可用时的容灾。面对这些问题,我们希望利用事件驱动架构的特性,对子域进行解耦,降低业务环节的复杂度,构建一个稳定的、前向兼容的事件合约,从而提高整个域的稳定性。2.事件驱动架构的应用流程(1)重组全链路业务流程和业务活动,建立统一的标准语言;(2)定义标准事件格式和公共基础字段;(3)每个域定义包含完整的业务语义、自闭合、多租户域事件;(4)开发并接入一套适应供应链业务特点的事件系统(NBFEventCenter);3.关于NBFNBF[1]是阿里巴巴供应链中台,由基础技术团队打造的一个技术PaaS平台,全称新零售商业工厂,她提供微服务FaaS等一系列PaaS产品框架、低代码平台和中台基础设施,旨在帮助业务合作伙伴快速复用和扩展中台能力,提升研发效率和对外商业输出。活动中心是NBF系列技术产品中的一员。本文首先介绍了事件驱动架构的概念和适用场景,然后介绍了事件中心产品的设计与实现。二、什么是事件驱动架构(EDA)1、现场事件很多同学会把事件和消息混为一谈。在业务系统中,事件是指领域事件,消息可以是任意数据或数据片段。领域事件的特点包括:(1)像服务接口一样具有完整的模式,并保证模式向前兼容;(2)是业务流程的一部分,由业务动作触发,包括完整的(或部分但独立的语义)(3)事件消费者收到事件后,相应地修改自己的业务状态,并根据需要发出新的事件;消费者需要保证所有事件消费成功,否则业务流程不完整;(4)事件需要持久化存储,长期归档,方便商科学生查询,恢复中断的业务流程,重新启动业务流程等,也便于离线分析进行风控和财务分析学生。2.事件驱动架构的概念类似于很多架构术语。事件驱动架构没有明确的能力定义和范围。MartinFowler2017年的文章[2]描述了一些与事件驱动架构相关的主要模式。在本文中,事件驱动架构的概念体现为领域事件驱动的业务流技术架构。每个领域事件对应一个业务流中的一个特定活动(如采购订单创建),事件是该活动的结果(如采购订单完成事件),事件内容是其引起的完整状态变化活动(例如采购订单+子订单列表)。3.事件驱动架构的优势在FundamentalsofSoftwareArchitecture[3]和MicroservicesPatterns[4]中,事件驱动架构的一些明显特征在FundamentalsofSoftwareArchitecture[3]和Microservices等书籍中都有描述模式[4]。FireandForget)灵活扩展高处理性能4.事件驱动架构可以解决哪些实际问题?下面举几个例子来说明事件驱动架构的解耦和广播能力如何帮助解决现实世界的问题:解耦能力是基于请求/响应的面向服务的架构中,上游服务调用下游服务根据约定的RPC接口。这有一个严重的问题:作为数据(如业务文档)的生产者,上游服务强烈依赖于数据消费者。下游服务定义的接口使得上游服务自身无法沉淀接口和数据标准。更合理的解决方案是依赖倒置:SPI由上游服务定义,SPI由下游服务实现。这样上游服务终于有机会沉淀自己的接口和数据标准,不再需要适配各个下游服务的接口,而是由下游服务的开发者根据接口文档来实现。但是,这种设计仍然无法解决上游服务在运行时仍然依赖下游服务的问题。下游服务的可用性、一致性、幂等能力将直接影响上游服务的相关指标和实现方式,上下游服务开发者需要联合解决方案,共同解决问题。使用事件驱动设计可以实现契约定义和运行时的全面解耦:上游服务可以存放自己的事件契约,上下游服务在运行时都只依赖事件代理,下游服务的可用性和一致性等由EventBroker保证的问题。广播能力在供应链中台等复杂的微服务架构中,关键的上游服务往往有多个下游服务,而上游服务一般需要依次或并发调用所有下游服务才能完成一次完整的调用。上游服务的开发者会面临多重问题:服务的可用性会受到下游服务的影响;服务的RT不能自己控制;如何保证下游服务之间的一致性;如何实现可靠的重试机制;而下游服务开发者也有自己的问题:每次访问上游服务都需要和服务开发者进行调度:谁来答题,什么时候联调,什么时候上线;上行流量如何过滤,峰值流量能否承受;如何满足上游服务的可用性和RT要求;使用事件驱动架构自然可以避免以上问题:上下游完全解耦,只要上游服务保证事件成功发送给broker,不管下游有多少消费者,它都会不影响自身RT,无需考虑下游服务间的一致性;下游服务接入新事件时,只需在事件管理服务中完成订阅审批流程,无需等待事件发布者调度联调;通过EventBroker提供的事件过滤能力,下游服务只需要消费与自身相关的事件流量(例如天猫超市的计费服务只需要消费tenantId为天猫超市的采购订单创建事件,不需要需要消费银泰租户采购订单创建事件);通过事件代理提供的事件存储和重投能力,即使上游服务发送的事件流超过下游服务的处理能力,也只会影响下游服务的消费延迟,不会造成大量请求失败的情况。5、事件驱动架构不适合强烈依赖Response的场景,比如文档查询、商品查询;对全局处理延迟敏感的场景,例如游戏和搜索;需要服务间强一致性的场景;3、事件中心中台事件中间件的功能设计,事件中心集成了消息中间件MetaQ(RocketMQ),初始使用体验和MQ非常相似,但是事件中心有很多不同的功能设计:(1)完善的权限控制;(2)支持事件合约定义和运行时合法性验证;(3)支持大事件发送消费(10MB以上);(4)支持长期事件历史查询、事件索引查询(如单号、sku)、事件重新提交;(5)支持消费周期较长的事件(比如需要几个月才能完成的入库订单);(6)完成所有事件和消费记录的归档;(7)以OpenAPI的形式开放事件查询、事件复投等运维状态功能,方便其他系统集成。4.事件中心运行时架构事件中心运行状态主要由以下部分组成:事件中心服务/SDKa)SDK:包含事件发送和接收的主要逻辑,支持事务发送和普通发送,以及支持事件校验、压缩、本地备份;b)TunnelService:超薄层的数据库代理服务,支持按应用、事件、场景、IO维度限流,支持数据库快速灵活扩容;c)IndexService:事件索引服务,通过经纬(DataX)Binlog获取,解析成索引写入索引表(Lindorm)。阿里中间件a)Diamond(Nacos):包含所有与应用相关的配置信息,如发送、订阅关系、事件定义、中间件配置等;b)SchedulerX:调度SDK执行事件重发、重消费、交易异常状态问题c)MetaQ:主要的事件收发管道;d)TDDL(RDS):存储事件内容和消费记录;e)经纬:用于索引生成、计算延时等异步处理逻辑;f)Lindrom(serverless):用于存储事件的外部索引。Serverless模式支持按量付费和弹性扩展,性能比较稳定。下图是一个简化的运行时架构图。图中蓝线表示正常的事件收发链路(交易发送),红线表示事件的异常处理链路。1、事件发送消费流程的事件结构运行时的一个事件实例由三部分组成:(1)事件ID:全局唯一,格式为“逻辑库号_月内发送日期_uuid”,例如01_11_f75ec4fb347c49c4bc3e93xxxxxxxx,其中逻辑库编号用于逻辑库路由,日期用于事件清理;(2)EventHead:包含事件元信息,如trace信息、发送者信息、事件大小、MetaQ信息等。参考示例:(3)EventBody:JSON格式,包含用户定义的事件内容。事件内容必须符合事件定义契约,否则将被拒绝。事件在运行时可能有多个消费者,每个消费者都会产生一条消费记录。消费记录包括:事件ID消费信息:消费状态、消费次数、下次消费时间等事件发送流程事件中心支持事务发送和非事务发送两种模式,由状态机驱动,API设计与MetaQ基本相同。下面以事务发送为例介绍发送过程。由于非事务性发送的过程比较简单,这里不再赘述。1)交易发送状态机2)交易发送时序图3)异常状态交易查询事件消费流程事件消费流程也是由状态机驱动,API与MetaQ相比有一些区别:(1)无需调用订阅主题;(2)新增消费过滤器EventFilter,支持按租户、业务流、事件维度进行过滤;(3)支持使用不同的Listener消费不同的事件;1)事件消费状态机2)重试循环事件进入消费失败状态后,事件中心会周期性调用用户Listener重新消费。消费周期从5s开始,呈指数增长,最多重试15次。最大值为5*214=81920秒(约22小时)。3)事件消费时序图2事件存储数据表事件中心使用32个分库的TDDL,根据HASH(事件ID)做分库,每个数据库有如下表:(1)事件主表,包括发送(2)事件消费记录主表,包括消费信息、消费状态和再次消费信息,事件主表与事件ID相关联;(3)重大事件主表,包含大事件主体,通过事件ID与事件主表相关联;(4)事件日表,表结构与事件主表相同,存储已经消费过的事件;(五)消费记录日表;(6)大事件日表;事件生命周期(1)新写入的事件和消费记录都会进入主表;(2)当事件写入时间超过1天,且该事件的所有消费者都消费成功时,会将事件和所有消费记录从主表移动到天空表;(3)当某个事件的消费者需要重新消费之前消费成功的事件时,会将事件和所有消费记录从天表移动到主表;(4)每天的某个时间,活动清理服务会清理7天前的skywatch。例如,如果今天是2月11日,则2月4日的所有天文表将被清除。3、外部索引事件发送历史列表、事件索引查询和事件重提交是事件中心运维平台的主要功能。其中,索引查询功能查询速度快,查询结果准确,用户反馈一直比较好。索引配置在修改事件定义时,用户可以将任意一个基本类型字段配置为“查询字段”,事件中心会在运行时解析该字段的值并创建索引;事件中的每个查询字段将对应一个索引;即使没有配置查询字段,也会生成一个包含时间戳的索引,用于对发送的事件进行排序和分页。索引结构事件中心的索引是KV结构,使用了Lindorm的宽表存储,根据使用场景分为两种:(1)不包含查询字段的索引;(2)Key格式为HASH(租户id_事件码)_env_发送时间差_事件ID;(3)Value为事件ID和事件头;(4)包含查询字段的索引;(5)Key格式为HASH(租户id_事件代码_字段路径_索引值)_环境_发送时间差_事件ID;(6)Value为事件ID和事件头;其中(1)发送时间差=Long.MAX_VALUE-发送时间,单位毫秒,用于按发送时间倒序显示;(2)字段路径为json路径格式,如$.bizNo;查询性能通过目前的事件中心运维平台,99%的查询都能在毫秒级返回结果,Lindorm索引行数在亿级。五、总结本文介绍了事件驱动架构在供应链执行环节的应用背景和实践过程,并介绍了NBF事件中心产品的设计和部分实现。目前,事件中心每天发送事件的峰值量在千万级别,顺利度过了双11、双12、元旦等流量高峰期。参考链接:[1]https://www.infoq.cn/video/xXxlmqhTH5owSDRSx52p[2]https://martinfowler.com/articles/201701-event-driven.html[3]https://book.douban。com/subject/34464806/[4]https://book.douban.com/subject/26989027/