InfoQ如何基于 DDD 构建微服务?( 五 )
图 8:事件驱动架构
在上面的示例中 , 订单服务发布一个事件:订单已取消 。 订阅了该事件的其他服务处理各自的领域功能:支付服务退款 , 库存服务调整商品的库存 , 等等 。 为确保此集成的可靠性和弹性 , 需要注意以下几点:
生产者应确保至少发出了一次事件 。 如果过程中出现失败 , 则应确保存在回退机制以重新触发事件
消费者应该确保以幂等的方式消费事件 。 如果再次发生同一事件 , 不会对消费者产生任何副作用 。 事件也可能不是顺序到达的 。 消费者可以使用时间戳或版本号字段来保证事件的唯一性 。
由于某些用例的特性 , 不一定总是可以使用基于事件的集成 。 请看一下购物车服务和支付服务之间的集成 。 这是一个同步集成 , 因此我们需要注意一些事项 。 这是一个行为耦合的例子——购物车服务可能会从支付服务调用一个 REST API , 并指示它授权订单的支付 , 而时间耦合——支付服务需要对购物车服务可用 , 它才能接受订单 。 这种耦合降低了这些上下文的自治性 , 也可能会引入不必要的依赖 。 有几种方法可以避免这种耦合 , 但是如果使用了所有这些选项 , 我们将失去向客户提供即时反馈的能力 。
将 REST API 转换为基于事件的集成 。 但是 , 如果支付服务仅公开 REST API , 则此选项可能不可用
购物车服务立即接受订单 , 并且有一个批处理作业来接管订单并调用支付服务 API
购物车服务生成一个本地事件 , 然后调用支付服务 API
在出现失败和上游依赖项(支付服务)不可用的情况下 , 将上述方法与重试相结合 , 可以产生更具弹性的设计 。 例如 , 在发生故障的情况下 , 可以通过基于事件或批处理的重试来备份购物车和支付服务之间的同步集成 。 这种方法会对客户体验产生额外的影响:客户可能输入了不正确的支付详细信息 , 当我们离线处理支付时 , 无法强制他们在线 。 或者 , 收回失败的支付可能会增加企业的成本 。 但在所有可能的情况下 , 让购物车服务对支付服务的不可用性或故障具有弹性 , 利大于弊 。 例如 , 如果我们无法离线收款 , 我们可以通知客户 。 简而言之 , 在用户体验、弹性和运营成本之间存在着权衡 , 在设计系统时 , 明智的做法是充分考虑这些折衷 。
避免为满足特定数据需求而编排服务
存在于任何面向服务架构的一个反模式是:服务迎合调用者的特定访问模式 。 通常 , 当调用者团队与服务提供者团队紧密合作时 , 就会发生这种情况 。 如果团队正在开发一个单体应用程序 , 它们通常会创建一个跨越不同聚合边界的 API , 从而使这些聚合紧密耦合在一起 。 我们来看一个例子 。 比如说 Web 中的订单详情页面 , 移动应用程序需要在单个页面上显示订单详情和订单退款处理详情 。 在一个单体应用程序中 , 订单获取 API(Order-GET-API , 假设它是 REST API)需要同时查询订单和退款 , 合并两个聚合并向调用方发送一个复合响应 。 由于聚合属于同一流程边界 , 因此可以在没有太多开销的情况下实现这一点 。 调用者可以在一次会话中获得所需的所有数据 。
如果订单和退款是不同上下文的一部分 , 那么数据不再出现在单个微服务或聚合边界内 。 为调用者保留相同功能的一个选项是 , 让订单服务负责调用退款服务并创建一个复合响应 。 这种方法会引起以下几个问题:
订单服务现在与另一个服务集成 , 纯粹是为了支持那些需要退款数据和订单数据的调用者 。 现在订单服务的自治性降低了 , 因为退款聚合的任何更改都会导致订单聚合的更改 。
订单服务有另一个集成 , 因此需要考虑另一个故障点:如果退款服务出现故障 , 订单服务是否仍可以发送部分数据 , 并且调用者是否可以优雅地处理故障呢?
如果调用者需要变更 , 以从退款聚合中获取更多的数据 , 那么现在需要两个团队同时进行变更
- 作文|如何正确看待,张子枫的高考事件?很多人都是断章取义吗?
- 陈薇院士回应疫苗发热率高|陈薇院士回应疫苗发热率高 如何回应?有啥影响?
- 北斗|北斗卫星高密度发射 产品质量如何保证?专家回应
- 家装百科|如何用银色配饰搭出清凉感?3套40岁左右时尚达人的夏日穿搭示范
- 老人|瑞思拜!107岁老人每天坚持拉伸锻炼1小时 如何做到长寿?
- 防灾减灾如何用北斗?北斗办:毫米级定位可以预警泥石流
- 穿搭|卫衣和短裙如何搭配比较好看时尚?
- 海外资金|外资企业撤出,中国世界工厂地位被取代,传统外贸人该如何面对?
- 二锅头|?二锅头在北京是如何取代黄酒的?
- 央视网 产品质量如何保证?专家回应,北斗卫星高密度发射
