事件流订阅事件流订阅的设计理念是将瞬间的过程化调用转变成可回放的指令,对指令的响应可以不用再预定义 。事件流订阅,在应用层表现为 Mediator 中介模式,在架构层表现为 Broker 消息模式 。
应用层 -Mediator 中介模式
A 直接调用 B,意味着 A 对 B 产生了强依赖 。当然我们可以通过面向接口编程,把这个依赖降低,降低到只依赖接口,不依赖实现 。简单说,我们只依赖对事情的处理结果,不依赖于如何实现这个处理结果 。
但是这还不够,因为我们还依赖了接口,接口意味着对处理语义的刻画 。现实中有些情况,连语义的描述都要发生变化,也就是接口都要发生变化,如何进一步解耦呢?如下图:
文章插图
A 不直接调用 B,而通过中介 Mediator,解耦两步:
- 先由 A 调用 Mediator: A 持有 Mediator 的引用,执行 Mediator 的方法,即 mediator.publish(e) 。
- 再由 Mediator 调用 B: 为了解耦 Mediator 对外界的依赖,我们用面向接口 EventHandler 来实现依赖反转 。让 B 来实现 EventHandler,当然如果 B 已经存在,或更有话语权,依然应该遵循依赖反转的原则,只不过 Mediator 模式的推进方可以再实现一个 Adaptor,来帮助既有的 B 适配到 EventHandler 。
- 订阅:通过 mediator.subscribe(b) 把未来的事件处理提前注册到 Mediator 。
- 发布:A 向 Mediator 发布自己的事件 。注意这个理念特别重要,A 仅仅发布发生了什么事情,A 并没有直接调用 B 声明对事情的处理 。也就是 A 连对 B 的接口都不再依赖了!举个例子,比如新员工入职,刚开始要为员工办理磁条卡,只是办理磁条卡的供应商可能是甲,也可能是乙 。这叫面向接口编程,但这还不够,因为随着公司的发展,现在新员工入职,有人脸识别了,不用再办磁条卡了,而是要登记人脸识别,另外员工福利更好了,对异地公干的新员工入职还会发放一笔安家费,这些都是之前的“接口”没有描述的 。
- 执行:当 mediator 收到 A 的事件后(A 调用了 mediator.publish(e)),mediator 会通过 EventHandler 来回调预先通过 mediator.subscribe(b) 注册的处理类 。
文章插图
可以看到上述架构通过 Map<Topic, List> resolver 来维护从 Topic 到 EventHandler 的一组处理 。为什么是 List,而不是 EventHandler 呢?为了更加灵活,比如上文提到的「现在新员工入职,有人脸识别了,不用再办磁条卡了,而是要登记人脸识别,另外员工福利更好了,对异地公干的新员工入职还会发放一笔安家费」 。
架构层 -Broker 消息模式
文章插图
上图的 Broker 模式,跟 Mediator 模式其实没有本质的不同,只不过 Broker 更加突出了借助消息中间件 MQ 实现异步 。客户端提交一个委托,Broker 持久化完成,并回复 ACK,表示委托已收到 。接着委托的消费处理,可以是离线的 。通常需要支持 Group 机制:Group 内部多个 Instance 是负载均衡的,它们共同瓜分委托消息的处理;而 Group 间是冗余复制的,它们各自消费各自的,相互之间隔离,有助于实现业务可拓展性 。
比如一个新员工入职,它产生一个“新人入职”事件,然后行政部门会为其准备工卡、财务部门会为其准备工资卡、HR 部门会为其缴纳社保 。当然,随着公司业务发展,可能还会增加,比如业务部门的业务培训,风控部门的合规性培训等 。
跟前面说的 Proxy 模式,相同点在于它们都是在架构层面实现可拓展性 。不同点是,Proxy 模式支持的是 PreHandler 和 PostHandler;而 Broker 模式支持的是 MidHandler 。
关于作者
作者李伟,研究微服务与大数据方向,擅长中台架构敏捷性课题 。就职于京东零售,担任资深架构师,加入京东前曾就职于搜狐和百度 。
【细数软件架构中的解耦】
推荐阅读
- 硬盘你真的选对了么?固态真的好用么?细数硬盘这些年出现的坑
- 如何去除360以及其他软件的捆绑广告
- 远程控制软件哪个好,试试Win10远程桌面,不会让你失望
- 如何绕过win7系统开机密码,进入系统安装特殊软件
- 聊聊几个程序员经常用的作图软件
- Linux主流架构运维工作简单剖析
- 一文看懂微服务架构之注册中心Consul、Nacos
- 程序员也需了解的主流云计算网络架构
- 软件开发人员应该了解的2021年技术趋势
- 数据中台到底包括什么内容?一文详解架构设计与组成