温馨小区里住着一位厨艺精湛的王阿姨。过去她想让大家吃上热乎饭,得翻开手机通讯录,挨个给 3 号楼王大爷、5 号楼小李、门卫老周打电话:“今天有红烧肉,来不来?”电话一打就是一下午。后来小区装了大喇叭“温馨FM”,王阿姨做好饭只需对着喇叭喊一句“开饭啦!”,想吃的住户自然会端着碗赶来——她再也不用知道谁家在听、谁家不想听。这套从“挨个呼叫”到“广播消息”的转变,就是今天的主角:事件驱动设计模式。 事件驱动并不神秘,它就在我们身边:电台广播、朋友圈点赞、外卖平台的“订单已出餐”通知……它的核心是让发消息的人和收消息的人互不认识,通过一个公共通道传递消息。对 AI 工程师来说,模型训练、数据流水线、监控告警这些环节天然充满“状态变化”,用事件驱动能写出更松耦合、更好扩展的系统。
学懂事件驱动,你就能在架构评审时自信地回答“这里该用事件总线还是直接调用”,把 AI 服务和模型管道从千丝万缕的电话线变成井然有序的社区广播——这是 AI 工程师进阶架构师的关键一步。
目录
可视化演示
展示观察者模式同步通知、发布订阅异步解耦、事件溯源状态重建,步进切换探索事件驱动核心设计模式。
本节配有交互动效(进入视口后自动加载,约 3KB)。
观察者模式:同步通知 Subject状态变化触发通知 O1/O2/O3同步接收事件 进程内一对多依赖关系 notify = subject.notifyAll() 观察者同步接收通知耦合度较高
核心概念剖析:一支喇叭让消息飞
温馨小区有位王阿姨,厨艺一绝。以前她要问各家吃什么,得挨个敲窗户喊话;后来小区物业给她装了一支“大喇叭”,她只需要对着喇叭喊“排骨汤出锅啦”,想喝汤的人自然会端着碗赶来。在这套社区广播系统里,王阿姨不关心谁在听,听众也不打扰王阿姨做饭——这就是事件驱动最核心的气质:发消息的人不认识收消息的人。
在软件系统里,“大喇叭”被叫做事件总线(Event Bus),王阿姨那句“排骨汤出锅啦”就是一条事件(Event),骑车赶来的邻居们是订阅者(Subscriber),王阿姨本人是发布者(Publisher)。事件驱动设计模式,英文缩写 EDA(Event-Driven Architecture),说的就是:组件之间不直接互相点名调用,而是把“发生了什么”变成消息丢到公共通道上,谁关心谁取用。
事件听起来抽象,其实它指一切“状态变化”:按钮被点击、订单被创建、模型训练的 loss 下降到了 0.001。只要把这些变化打包成事件,发布到总线,订阅者就能按需接收。与请求驱动不同,发布者不知道甚至不关心有哪些订阅者,订阅者也不需要知道发布者的存在,于是系统的连接从“蜘蛛网”变成“星形总线”,复杂度大幅下降。
王阿姨装上大喇叭之后,小区里搬来多少新住户都不会增加她的麻烦——她只负责对着喇叭喊话。这正是事件驱动的魅力:解耦,让系统的生长不再带来连线的爆炸。
- 直接连接数每两个组件之间都要建一条调用关系,从 n 个点里选 2 个点的组合数就是 n(n-1)/2。
- 总线连接数所有组件都只往事件总线上连一条线,共 n 条,中间多出一个转发角色。
- 对比结论当 n=10 时,直接调用要 45 条连系,事件驱动只需要 10 条,差距随 n 增大越拉越大。
请求驱动对比:打电话与听广播
王阿姨还记得老日子:傍晚 5 点,她翻开通讯录,给 3 号楼王大爷打“今天有红烧肉”,给 5 号楼小李打“有冬瓜汤”,再给门卫老周打“有馒头”……一通电话一通电话地打,累得嗓子冒烟。这就是请求驱动:调用方必须精确知道对方的电话号码(服务地址),而且必须托着电话线等对方回答“好嘞”(同步等待返回结果)。
请求驱动不是一无是处:它直接、确定、一件事说清马上有结果。但它的软肋也一目了然——强耦合。只要某位住户搬家(服务不可用),王阿姨的电话线就断了;只要新搬来一位住户,通讯录就得加长。对应到代码里,A 组件调用 B 组件时,B 的接口、地址、返回格式全是 A 的“知识负担”,一改动就牵一发动全身。
事件驱动把“呼叫-应答”改成了“广播-收听”的异步模式。王阿姨不需要拨号,只需要朝喇叭喊;住户们各自决定接不接收;王阿姨也不需要等待任何人回复。代价是“没有即时的确认”——广播里没人回应时,王阿姨不知道汤是受欢迎还是被浪费了。这正是异步的本质:不阻塞发布者,但也不保证反馈。
王阿姨放下电话看着大喇叭感叹:“打电话一找一个准,但一条线只能连一个人;广播虽然不知道谁在听,一嗓子却能让全小区知道。”架构师的选择从来不是哪个好哪个坏,而是看你要“确定送达”还是“广而告之”。
- 生产事件发布者把“状态变化”打包成事件对象,记录类型、载荷等信息。
- 总线传输事件在消息代理中排队、路由、复制给所有订阅者。
- 消费处理每个订阅者并行处理自己的事件,整体耗时取最大者。
观察者模式:王阿姨的熟客花名册
大喇叭虽好,但王阿姨有几位 VIP 熟客,比如 3 号楼王大爷只爱红烧肉。若每道菜都全小区广播,王大爷耳朵会起茧。于是王阿姨掏出一个“熟客花名册”:谁登记想吃哪道菜,她就记一笔,做好菜之后按着花名册挨个通知。这就是观察者模式的生活版。
观察者模式里有两类角色:主题(Subject)与观察者(Observer)。主题就是王阿姨/被观察对象,它维护一个观察者列表“花名册”,并提供增减入口:王大爷说“以后我常来”就登记,说“我搬家了”就划掉。状态一变(菜出锅),主题遍历花名册,逐个调用观察者的“响应方法”——在代码里通常叫 update()。
观察者模式的一大特点是同步且直接:主题亲自遍历观察者,调用关系在同一个进程内完成,不需要中间件。它适合组件数量少、彼此就在本地进程里的场景。Android 里的按钮点击监听、GUI 里的事件源与监听器,都是观察者模式的身影。
花名册好用,但王阿姨心里清楚:它适合“几十个熟客”的小饭桌,若小区扩到几千户,光翻花名册就得翻半天。观察者模式能解耦“主题与观察者”的双向依赖,但当观察者数量变大,就需要把“亲自挨个通知”升级为“交给广播站转发”——也就是下一节的发布订阅模式。
- 维护观察者集合主题持有一组观察者对象的集合,相当于一份动态更新的日名单。
- 串行回调累加状态变化时主题逐个调用 update(),总耗时为单次回调耗时之和。
- 同步阻塞风险若某个观察者卡顿,后续观察者全部被拖慢,整体延迟趋近无穷。
发布订阅模式:广播站的公开频道
小区人口暴涨后,王阿姨的花名册变成了一本厚电话簿,光是更新“谁搬走、谁入住”就让她头大。物业干脆建了个“社区广播站”,任何人想发消息都到广播站登记,并按话题分类——美食频道、健身频道、宠物频道。住户按需选择订阅哪个频道。这就是发布订阅模式,常写作 Pub/Sub。
和观察者模式最大的区别是:发布者与订阅者之间多了一个消息代理(Broker)作为中间人。王阿姨把“红烧肉出锅”投递到“美食频道”,广播站负责把消息推送给所有订阅了美食频道的人。发布者根本不接触订阅者,订阅者也看不见发布者——唯一的交点是那个“频道”(Topic)。这带来两个宝贵特性:空间解耦(互相不知道对方存在)与时间解耦(发布者发完就走,订阅者有空再处理)。
技术落地时,消息代理就是 Kafka、RabbitMQ、Redis Pub/Sub 这类中间件。生产者往 Topic 写入事件,Broker 根据订阅关系做复制与投递。新增订阅者只需向 Broker 登记,无需修改任何业务代码。这种“多对多、异步、带缓冲”的组合拳,让 Pub/Sub 成为大规模分布式系统的默认选择,但它的投递量也随之放大。
王阿姨把菜谱交给广播站后,生活轻松了许多:她不必记住任何住户,住户也能在美食频道之外订阅健身、宠物消息。发布订阅模式把“熟人社会”升级成了“陌生人社区”——消息不再认人,只认频道,这是大规模系统解耦的关键一步。
- 事件数一定时间内发布者产生的全部事件条数,等于事件到达率对时间的积分。
- 订阅人数当前订阅该 Topic 的消费者数量,来自订阅关系表。
- 复制放大广播让投递次数按订阅数线性放大,Broker 的带宽压力因此增加。
AI工程应用:智慧小区的联动网络
温馨小区在数字化转型中变成了“智慧小区”:门口的人脸识别摄像头、楼栋的环境传感器、云端的大模型推理服务器都成了新住户。它们之间如果靠“互相打电话”,光电话号码簿就有城墙厚。于是工程师给小区拉了一套“数据广播网”,让各种 AI 组件通过事件总线协作。
第一个典型的应用是训练流水线。数据生成器生产一批新样本后,朝“数据就绪”频道发一条事件;数据处理服务订阅这个频道,清洗完数据再向“特征就绪”频道发事件;模型训练服务订阅“特征就绪”开始一轮训练——每个环节只盯着自己的频道,整条流水线像接力赛一样自动推进。第二类典型应用是模型监控与告警:推理服务每完成一批预测,就发出“推理完成”事件;监控服务收到后对比 accuracy 和 latency,一旦指标突降就向“告警频道”发布消息,值班机器人收到后拉响告警。
事件驱动特别适合 AI 工程里的异步长流程:数据增强、分布式训练、模型评估、灰度发布,每个阶段耗时从秒级到小时级。若用同步调用,调用方要死死攥着电话等很久;用事件驱动,上游发完事件就去干别的活,下游准备好了再来消费。它天然地把“先做什么、后做什么”编成一张解耦的事件网,而不是一环扣一环的阻塞链。
智慧小区里再也听不见此起彼伏的电话铃声,数据广播网的频道里流淌着一条条“样本已就绪”“训练已收敛”“模型已上线”。事件驱动让 AI 工程从人拉肩扛变成了全自动流水线,王阿姨的厨房也接入了一个新频道:AI 营养师根据订餐数据自动推送明天的菜谱。
- 单指标正常概率指标 i 不超阈值的概率是 (1-p_i)。
- 全部正常概率假设 k 个指标相互独立,所有指标都正常的概率是连乘积。
- 至少一个异常告警发生 = 至少一个异常 = 1 减去“全部正常”。
反模式陷阱:当广播变成噪音
智慧小区的广播大了之后,麻烦也来了。有人每天往美食频道发 100 条优惠券广告,住户们打开收音机全是“领券领券”,真正重要的“火灾预警”被淹没在信息洪流里。这种“事件发得太多太乱”的现象,在技术圈有个著名的名字——事件风暴。
事件风暴的本质是:因为发事件太容易了,开发者的手一抖,各种细碎状态全都变成了事件。一个用户点击按钮,竟然连锁触发 50 条事件:埋点、缓存刷新、推荐重算、邮件推送、报表更新、同步到大数据平台……系统被事件洪流冲垮,CPU 和网络被打满,消息队列开始积压。此时事件驱动不但没有解耦,反而制造了新的瓶颈——广播站的喇叭都喊冒烟了。
另一个常见陷阱是消息顺序。请求驱动里 A 调用 B 永远是先到先做;事件驱动经过总线/队列后,两个事件的先后顺序可能被并发消费打乱。比如“先改密码、再退出登录”两个事件若乱序执行,就变成了“先退出、后改密码”的安全漏洞。此外,事件丢失也是隐患:没有确认机制时,消息发完就没了,数据不一致只能在事后对账。调试时,事件在多个服务间流转,一条请求的完整链路要跨十几个日志文件才能拼出来。
王阿姨看着被广告刷屏的“美食频道”,叹了口气:“喇叭是好喇叭,但也不能什么都往上吼。”事件驱动不是越多越好,而是越准越好——克制地发布有意义的事件,给每类事件配好消费能力,广播站才不会变成噪音站。
- 到达率单位时间进入事件总线/队列的事件数量。
- 停留时间每个事件从进队到被消费掉的平均耗时,包含排队等待和服务时间。
- 积压量两者相乘得到队列中堆积的事件数,λ 一大,积压立刻上升。
架构权衡决策:王阿姨的选型心法
王阿姨现在有三种做法:给 VIP 单独送餐就打电话(请求驱动),小范围试新菜用花名册(观察者模式),全小区食堂开饭就广播(发布订阅模式)。她根据做菜的性质来决定,不在厨房里一刀切。架构选型也是同一个逻辑——没有银弹,只有匹配。
什么时候选事件驱动?判据可以概括为三点:一,模块之间是否真的需要解耦——如果只有两三个服务且生命周期一致,强行引入事件总线只会徒增复杂度;二,是否天然存在“状态变化”的异步信号——比如订单状态变更、模型训练里程碑;三,是否能容忍最终一致性与延迟——事件驱动通常做不到强一致,适合“晚一点没关系”的场景。反之,银行转账、库存扣减这类强一致场景,请求驱动加上事务仍然更稳妥。
如果真的决定采用事件驱动,可靠性设计是绕不开的功课:给每条事件加唯一 ID 以便幂等消费;对重要事件开启确认与重试机制;必要时引入事件溯源(Event Sourcing),把事件流存成“记账本”,任何时刻都能回放重建状态。有了这套“广播站管理制度”约束发布与消费,事件驱动才能既解耦又可靠。
王阿姨最终在厨房里挂了一张小卡片:“打电话给 VIP,翻花名册给熟客,广播给全小区。”架构师的心法也不过如此:看清场景,算清收益,再决定要不要上喇叭。
- 解耦收益系统新增或修改组件的平均成本下降幅度,用 0 到 1 归一化。
- 代价成本事件中间件运维、消息丢失修复、调试追溯等额外开销的总和。
- 加权决定α、β 两个系数按业务场景人工设定,得分大于 0 才值得转向事件驱动。
AI 应用场景
场景一:AI 训练平台的事件管道
阶段:数据工程 / 训练管理
解决的问题:以往每新增一个下游任务,都要修改上游数据服务的代码来“打新电话”;用事件驱动后,上游只管发布“新数据已上线”事件,下游自行订阅,彼此不再互相绑架。
具体案例:某电商公司的推荐模型团队把“用户行为日志落盘”设置为发布到 user.behavior.logged 主题,特征工程服务、离线报表服务、模型再训练服务各自订阅;后来新增一个“实时反欺诈分析”服务时,只写一行 subscribe 注册进频道,完全不需要改动任何旧服务代码,上线时间从两周缩短到两天。
场景二:模型监控告警系统
阶段:模型部署 / 运维监控
解决的问题:模型上线后的准确率下降、延迟升高、特征分布漂移都需要自动感知,靠人工轮询查指标既慢又费人力。
具体案例:推理服务每完成一批预测就向 inference.finished 频道发布事件,监控服务订阅后计算窗口内的 accuracy 与 p99 latency,若指标跌破阈值,就向 alert.triggered 发布事件,钉钉机器人随即收到告警,并将异常样本自动转发到数据回流管道,形成“发现-告警-反馈-再训练”的闭环。
场景三:AI 工作流编排
阶段:任务编排 / 工作流管理
解决的问题:训练、评估、部署之间的多步骤依赖如果用 if-else 硬编码,流程会僵化难维护;事件驱动让每一步只关注“自己该等的事件”,上下游完全解耦。
具体案例:数据标注完成后发出 annotation.completed 事件,触发训练任务;训练达到指标阈值后发出 training.succeeded 事件,触发模型评估;评估通过后发出 model.promoted 事件,触发灰度发布。整条流水线不需要一个中心调度器轮询状态,而是被事件链自然推着走。
Python 演示
"""Event-driven AI training monitor demo."""import time class EventBroker: """Publish-Subscribe broker.""" def __init__(self): self.subscribers_map = {} def subscribe(self, event_type, handler): if event_type not in self.subscribers_map: self.subscribers_map[event_type] = [] self.subscribers_map[event_type].append(handler) def publish(self, event): event_type = event.get("type") for handler in self.subscribers_map.get(event_type, []): handler(event) class Trainer: """Simulate an AI trainer that publishes events.""" def __init__(self, broker): self.broker = broker self.step_count = 0 def run(self, epochs): for epoch in range(1, epochs + 1): loss = max(0.5, 1.0 - epoch * 0.02) self.step_count += 1 event = { "type": "training_step", "epoch": epoch, "loss": loss, } self.broker.publish(event) time.sleep(0.05) def log_handler(event): print(f"[LOG] epoch {event['epoch']} loss {event['loss']:.4f}") def alert_handler(event): if event["loss"] > 0.95: print(f"[ALERT] Loss too high: {event['loss']:.4f}") def checkpoint_handler(event): if event["epoch"] % 5 == 0: print(f"[SAVE] checkpoint at epoch {event['epoch']}") def main(): broker = EventBroker() broker.subscribe("training_step", log_handler) broker.subscribe("training_step", alert_handler) broker.subscribe("training_step", checkpoint_handler) trainer = Trainer(broker) trainer.run(epochs=10) if __name__ == "__main__": main()
training_step 事件,日志、告警、模型保存三个处理器互不相识,却都能通过 Broker 收到通知。self.subscribers_map = {}用一个字典记录每种事件类型对应的回调函数列表,相当于广播站的“订阅花名册”。if event_type not in self.subscribers_map:首次订阅某类事件时先创建空列表,避免后续 append 报错。self.subscribers_map[event_type].append(handler)把新订阅者登记进列表,发布者完全无需感知这个动作。self.broker.publish(event)Trainer 只负责把事件交给 Broker,后续的转发和它无关。for handler in self.subscribers_map.get(event_type, [])Broker 按事件类型找出所有订阅者,逐一调用回调函数。broker.subscribe("training_step", log_handler)相当于对广播站说“训练频道一有消息就叫我”,注册即生效。if event["epoch"] % 5 == 0检查点处理器只关心每 5 轮的保存时机,与其他处理器零接触。
常见误区
误区网上文章都说事件驱动又解耦又异步,所有新系统我都应该用事件驱动,Kafka 一上,架构立刻现代化。
正解事件驱动只是众多工具之一。两三个服务的单体场景强行引入事件总线,等于为了买瓶酱油去开一辆大卡车——额外增加中间件运维、消息丢失风险和调试成本。王阿姨给 VIP 单独送菜时,直接打电话(同步请求)反而最简单可靠;只有面对大量互相独立的消费者时,广播才划算。
为何常见:因为“解耦”“异步”听起来高端,加上技术文章大多只讲优点而忽略适用边界,初学者很容易把一种模式当成万能的银弹。
误区观察者模式和发布订阅模式画出来都是“一个中心连多个外围”,名字也经常混着用,所以它们完全一样。
正解核心区别在中间层。观察者模式里主题直接保存观察者列表并逐个调用,属于进程内、同步、直接依赖;发布订阅模式有消息代理(Broker),发布者和订阅者互相不知道对方存在,支持跨进程、异步、多对多。王阿姨的花名册(观察者)和社区广播站(发布订阅)是两种不同的协作方式,不能混为一谈。
为何常见:两种模式的 UML 类图画出来很像,都是中心节点连多个叶子节点,再加上文章总是把它们并列放在“解耦”话题里一起讲,初学者自然觉得它们是一个东西。
误区消息发到了 Kafka 或 RabbitMQ 这种专业中间件里,应该很安全,事件一定不会丢。
正解消息代理虽然提供持久化,但“至少一次”“最多一次”“恰好一次”的投递语义各不相同。如果没有开启 ack 确认、事务和重试机制,消费者宕机、消费失败重放等问题仍会导致事件丢失或重复。广播站的大喇叭只是把声音放出去,没人保证你回家路上没听漏;重要事件必须自己设计幂等与对账机制。
为何常见:Kafka 等组件在宣传上强调“持久化、高可靠”,让初学者误以为消息进入中间件就等于进了保险箱,忽视了分布式系统里确认、重试、幂等这些基本功。
误区用了事件总线后,各服务各自处理自己的事件,不用再担心数据一致性了,最终数据会自动同步好。
正解事件驱动把同步事务换成异步协调,本质上是选择了最终一致性,而不是消灭了一致性问题。订单状态、余额扣减这类需要强一致的场景,若强行事件驱动,反而要引入 SAGA、事件溯源等更复杂的补偿机制。广播里说“饭好了”,不能保证每个住户都真的吃上了;你只是把问题从“接口调用层”转移到了“数据一致性治理层”。
为何常见:“解耦”听起来像把复杂问题变简单了,人们容易把“模块解耦”误解为“一致性问题消失”——实际上异步化之后,跨服务的数据对齐反而更难追踪。
面试题
Q1. 在事件驱动架构中,事件发布者知道哪些订阅者正在监听?
- A.清楚地知道每一个
- B.通常完全不知道← 正确答案
- C.知道一部分订阅者
- D.靠配置文件得知
答案:B。事件驱动的核心是发布者与订阅者解耦。王阿姨对着大喇叭喊“开饭啦”,她并不知道谁在听、有多少人在听。订阅者自行决定是否接收,发布者不需要维护订阅者名单,这正是“空间解耦”的含义。
Q2. 下面哪个是事件驱动最直观的生活比喻?
- A.拨打长途电话
- B.收听广播电台← 正确答案
- C.开部门协调会
- D.医院挂号问诊
答案:B。广播电台的主持人向电波覆盖范围发送节目,不知道谁在收听,听众按需调台——这正是发布订阅模式的生活版。打电话是请求驱动,协调会和挂号问诊都是点对点的交互,不是广播。
Q3. 观察者模式中“主题”的核心职责是什么?
- A.直接执行具体业务
- B.维护观察者并通知← 正确答案
- C.把数据写入数据库
- D.控制消息的发送顺序
答案:B。观察者模式里的主题(Subject)相当于王阿姨的“熟客花名册”:它负责登记/注销观察者,并在状态变化时逐个调用观察者的 update()。至于业务逻辑、持久化和消息排序,都不是主题的核心职责。
Q4. 事件驱动架构想要解决的核心痛点是什么?
- A.提升单次请求的响应速度
- B.降低组件之间的耦合度← 正确答案
- C.压缩系统的代码体积
- D.保证数据库强一致性
答案:B。事件驱动把“点对点直接调用”变成“发布-订阅广播”,主要解决了组件之间的强耦合问题。它不一定让单次请求更快,反而可能增加中间件延迟;代码体积和数据库一致性也不是它的主要目标,甚至可能因为异步而引入一致性难题。
Q5. 发布订阅模式比观察者模式多了一层什么?
- A.主题业务接口
- B.消息代理中间件← 正确答案
- C.数据库存储层
- D.异步回调函数
答案:B。发布订阅模式引入了 Broker(消息代理)作为中间人,发布者和订阅者之间不直接接触。观察者模式是主题直接保存观察者列表并逐个回调,没有中间转发角色。回调函数两种模式都有,异步也并非观察者模式的必备特征。
Q6. AI 训练流水线中,哪个环节最适合用事件驱动?
- A.一次性批量导入历史数据
- B.训练日志写入本地文件
- C.指标变化触发自动评估← 正确答案
- D.每日凌晨定时备份数据库
答案:C。训练指标变化属于典型的“状态变化”,适合发布事件触发下游评估、告警或可视化。批量导入和定时备份是一次性/周期性的批处理任务,用调度器更合适;日志写本地文件是简单 IO,不需要事件总线。
Q7. 以下哪些是事件驱动架构的优点?
- A.模块解耦且扩展灵活← 正确答案
- B.支持异步与多播通信← 正确答案
- C.天然保证事件有序处理
- D.新增订阅者无需改发布方← 正确答案
答案:ABD。发布者和订阅者互不知晓,新增订阅者只要向 Broker 登记即可,因此解耦和扩展性好;事件驱动天然支持异步,一条事件可被多个订阅者消费(多播)。但它并不保证顺序——多个消费者并发处理时,消息顺序可能被打乱,这是它的短板而非优点。
Q8. 下列哪些现象属于事件驱动的陷阱?
- A.事件风暴导致洪流积压← 正确答案
- B.消息乱序破坏业务逻辑← 正确答案
- C.事件丢失导致数据不一致← 正确答案
- D.中间件自动保证强一致
答案:ABC。事件风暴(一次操作触发大量连锁事件)、消息乱序和事件丢失,都是事件驱动架构的典型陷阱,分别对应反模式章节里的吞吐瓶颈、顺序难保证和可靠性问题。事件中间件并不自动保证强一致,D 项本身就是错误认知。
Q9. 事件驱动架构可能带来哪些额外代价?
- A.调试链路变长变复杂← 正确答案
- B.系统吞吐量必然下降
- C.消息乱序难以处理← 正确答案
- D.组件数量一定增多
答案:AC。事件在多个服务间流转后,一次业务操作的完整链路分散在各处日志里,调试更困难;经过队列和并发消费,消息顺序也难以保证。吞吐量在有良好设计时可能反而提升,组件数量也不一定增多,B 和 D 都不是必然代价。
Q10. 某系统有 n 个组件,从请求驱动改为总线式事件驱动后,连接数约变为多少?
- A.约为 n 条连接← 正确答案
- B.约为 n/2 条连接
- C.约为 n² 条连接
- D.约为 log n 条连接
答案:A。请求驱动下两两连接需要 n(n-1)/2 条;引入事件总线后,每个组件只与总线相连,共 n 条连接。n=10 时从 45 条降到 10 条,这也是事件驱动解耦价值的定量体现。n/2、n²、log n 都不符合“每个组件连一次总线”的拓扑结构。