【问题标题】:Differentiate microservice logic by config or a new service通过配置或新服务区分微服务逻辑
【发布时间】:2019-08-04 00:12:21
【问题描述】:

我们有一个数据处理管道,我们可以在其中接收来自不同来源的数据。整个管道是通过使用事件驱动架构和微服务来实现的。其中一项服务具有三个独立的任务。其中两个在不同的数据源中是完全通用的,但是第三个任务范围可能会根据我们的数据源而略有变化。例如,对于一个源,唯一签名可以根据filed1 和filed2 计算,而对于另一个源,它可以根据field2 和field3 计算。实现此服务以符合微服务粒度原则的最佳方式是什么?

我想到了三种方法:

1) 创建一个服务并为每个源使用不同的实现(如工厂设计模式)。根据来源,将在运行时使用其中一种实现。

优点:服务数量较少。更简单的复杂性

缺点:由于该服务将在所有数据源之间共享,因此通过添加任何新数据源应重新部署该服务,这会在该服务与负责从某个源收集数据的任何服务之间创建隐式依赖关系

2) 将此服务拆分为两个服务,对所有源使用一个,并为每个数据源重新实现提取的服务。

优点:收集器和这两个服务之间没有依赖关系。通过添加新源,需要实施新服务,并且不需要重新部署与其他源相关的服务。

缺点:服务更多,而且由于服务太小,我们将来可能最终会面临纳米服务问题。

3) 不要改变服务的粒度,而是在运行时创建不同的服务实例。每个都有不同的配置来指定要用于每个源的字段集。在这种情况下,代码是共享的,但运行时实例会根据其所属的源而有所不同。

优点:服务数量较少,并且没有操作依赖性

缺点:将逻辑的复杂性转移到运行时,这可能会使部署和操作更具挑战性

【问题讨论】:

  • 您是否考虑过可扩展性、每项服务的关键性、新服务的更改频率等?通常,这些 NFR 有助于定义您是需要创建服务还是重用现有服务(配置/功能标志)
  • @AminAbu-Taleb 是的。从技术上讲,更改频率是这里的主要区别点,因为通过添加新源,我们需要修改受解决方案 1 影响的服务。
  • 是否有可能构建动态规则处理程序?我在建立优惠券系统时遇到了类似的问题。顺便说一句,我认为第二个在企业架构中是不合理的。
  • @wl.GIG 动态规则处理程序是什么意思?
  • @Alin 就像所有数据源的通用处理程序,输入参数如 [columns: {as, bb,...}, crypto: xxxxx ]

标签: architecture microservices event-driven


【解决方案1】:

我同意阿德里安的观点,这取决于你的情况。

我认为最重要的是系统复杂性——它在系统的测试、支持和演进中起着至关重要的作用。 (亲吻)

所以我认为最好的选择是 2。

当然,您应该记住其他设计原则——创建库以供重用等,但无论如何,您的源代码设计将是树而不是带有非托管依赖项的网络。

【讨论】:

    【解决方案2】:

    这取决于。仅供参考,我知道 Kafka,但没有这方面的经验。

    对于选项 3:您管理具有不同配置的解决方案的各种实例的能力有多成熟?会有多少实例?您如何能够观察所有实例的运行状况、行为和性能?

    此选项意味着开发不那么复杂,但操作方面更复杂:您只有一个代码库要测试,但要测试许多不同的配置排列。

    对于选项 1:在开发方面会更复杂,并且在操作方面仍然会有一些复杂性。其原因取决于解决方案如何设置为识别在运行时使用哪个实现。 IOC 方法可行,但它仍然是需要管理的配置。

    对于这两种方法,您都可以使用正确的配置设置实例并对其进行测试,这很好。

    关于系统变更:理想情况下,微服务应该易于替换。确保服务之间的划分清晰,以便您可以理想地替换解决方案的一部分而不会破坏另一部分。在将此类更改部署到生产中之前,它还应该易于测试——既可以单独测试服务/模块,也可以与解决方案的其余部分以及相关配置进行集成测试。如果您觉得一种方法比另一种更适合此方法,那么这就是我可能会采用的方法。

    更新 - 选项 2

    这意味着有多个服务来处理一些请求(但不是其他请求),所以现在您必须管理服务之间的流程(在运行时),以及它们之间的相互依赖关系(在开发、部署时);更难测试。

    微服务部分是关于拥有独立的服务 - 选项二并没有真正符合这种精神 - 没关系,只是意识到它不是严格意义上的微服务,这取决于你对这些事情的特殊程度。

    【讨论】:

    • 您对选项 2 有何看法?
    【解决方案3】:

    我认为我最关心的是服务产生的结果类型。 如果(对于所有 3 个选项)过程的结果将是完全相同的类型(或域对象),我肯定会支持 选项 1

    这符合“松散耦合,内聚行为”原则,Sam Newman 在他的 book 中写道。

    松散耦合,因为消费者不必关心从哪个服务调用/接收事件,因此无需知道来源。

    内聚行为,因为单个服务将业务逻辑应用于事件,因此产生具有一致类型/语义的可靠内聚事件。

    对于不同的来源,我想说让它们被单个服务使用是可以的。在服务实现内部以可维护的方式设计它有很多可能性。源应该选择什么任务是一个应该对消费者隐藏的实现细节。

    缺点:由于该服务将在所有数据源之间共享,因此通过添加任何新数据源应重新部署该服务,这会在该服务与负责从某个源收集数据的任何服务之间创建隐式依赖关系

    该服务确实依赖于生产者,因为它需要它作为来源。没有办法规避这一点。在某种程度上,所有其他选项也是如此。但是依赖是消费者依赖生产者,而不是相反!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-22
      • 2018-07-27
      • 1970-01-01
      • 2010-12-24
      • 1970-01-01
      • 2015-02-09
      • 2011-01-20
      • 2018-11-26
      相关资源
      最近更新 更多