微服务组合方法

时间:2015-07-22 20:55:23

标签: web-services architecture microservices

我对微服务社区有疑问。我将从教育领域给出一个例子,但它适用于每个微服务架构。

假设我有学生服务许可服务,其业务要求是学生数量受许可限制。因此,每次创建学生时都必须进行许可检查。有多种类型的许可证,因此许可证的类型必须包含在操作中。

我的问题是你发现哪种方法在实践中更好:

  1. 构建一个调用2个服务的组合服务
  2. 将学生服务与许可服务相结合,以便在调用createStudent时,学生服务会调用许可服务,并且只有在完成后才会创建学生
  3. 使用基于事件的架构
  4. 人们谈论微服务体系结构更像是图形而不是层次结构,而选项1 有点将其转变为层次结构,在这种层次结构中,复合材料越来越粗糙。其他缺点是它会对服务客户端应该实际使用的内容产生混淆,并且会出现一些重复,因为复合API必须包含调用下游服务所需的所有参数。 它确实有很大的好处,因为它为您提供了处理故障,编排和处理一致性的自然场所。

    选项2 似乎也有缺点:

    • 许可API必须泄漏到学生API中,以便您可以指定许可限制。

    • 它给学生服务带来了很大的负担,因为它必须处理所有相关服务的一致性

    • 随着更多服务需要在创建学生时做出反应我可以看到依赖图快速失控,除了管理学生的逻辑之外,服务还必须处理这种复杂性。

    选项3 虽然正在脱离天堂,但我认为这不会起作用,因为这一切都是从用户界面触发的,人们并不习惯“在这个新学生之前做其他事情”显示“方法。

    谢谢

5 个答案:

答案 0 :(得分:2)

应用许可和创建学生是正交的,因此选项2没有意义。

选项1更明智,但我会尽量不建立另一项服务。相反,我会尝试通过许可中间件“过滤”对学生服务的调用。

通过这种方式,您可以将此中间件用于其他服务调用(例如,类服务),并且许可和学生的API的更改可以独立完成,因为这些内容实际上是独立的。事实上,许可证正在使用许多学生,但这很容易改变。

我不确定选项3,基于事件的方法如何在这里提供帮助。它可以解决其他问题。

答案 1 :(得分:2)

恕我直言,我会选择选项2.需要考虑的几件事情。如果您购买完整的SOA以及微服务,那么每次服务需要联系其他服务时,您都无法退缩。对此感到满意....记住这一点。关于选项2我真正喜欢的是在许可证服务请求成功之前不会发送成功的学生服务响应。将许可证服务视为任何其他外部服务,您可以将许可证服务包装在可由许可证服务JAR发布的客户端对象中。

  • 许可API必须泄漏到学生API中,以便您可以指定许可限制。

是的,将使用许可证服务API。您可以将其称为泄漏(有人必须使用它)或封装,以便请求学生服务的客户端不必担心许可。

  • 它给学生服务带来了很大的负担,因为它必须处理所有相关服务的一致性

有些服务必须承担这个负担。但我会有机地管理它。我们正在谈论需要另一个服务的1项服务。如果这种情况增长并变得具体麻烦,那么就可以进行重构。如果学生服务所需的服务数量增长,我认为它可以优雅地重构,并且学生服务可能成为组合服务,并且如果需要,可以将独立使用的服务组合并到新服务中。但是,如果学生服务使用的依赖服务列表仅供学生服务使用,那么我不知道是否值得将它们分组到自己的服务中。我认为不是负担和泄漏,你可以将其视为封装和所有权......学生服务是该负担的所有者,因此不需要泄露给其他客户/服务。

  • 随着更多服务需要在创建学生时做出反应我可以看到依赖图快速失控,除了管理学生的逻辑之外,服务还必须处理这种复杂性。

替代方案是各种复合服务。就像我对前一个要点的回答一样,如果它表面上是一个真正的问题,那么就可以优雅地解决这个问题。

如果强迫您的每个选项都可以变成可行的解决方案。我正在为备选方案2提出一个自以为是的案例。

答案 2 :(得分:1)

选项1和2创建紧密耦合,应尽可能避免,因为您希望让您的服务独立。所以问题就变成了:

我们如何使用基于事件的架构来实现这一目标?

  1. 使用事件来跟踪学生服务中许可证服务的许可信息,实际上是数据重复。这里的缺点是:您只有最终的一致性,因为数据重复是异步的。

  2. 使用异步事件触发最终触发学生创建的事件链。从您的问题来看,看起来您已经有了这个想法,但是在处理UI方面存在问题。这里有两个可能的选项:等待学生创建(或失败)事件,少量超时,或(事件更好),让你的系统完全被动(使用UI的服务器 - 客户端推送机制)。

答案 3 :(得分:0)

我知道这个问题已经被问过了,但我想我有话要说,这可能是有价值的。
首先,您的方法将取决于最终产品的总体规模。我倾向于遵循经验法则:如果我在各个微服务之间存在太多依赖关系,我倾向于使用一些可以简化并可能删除这些依赖关系的东西。我不希望最终得到蜘蛛网服务!这里有一个好处是消息队列,例如RabbitMQ 但是,如果我只有几个相互通信的服务,我会让它们直接相互调用,作为任何替代解决方案,同时简化架构,增加一些计算和基础设施开销。

无论您决定采用哪种方法,都要考虑Hexagonal architecture设计您的服务!当您决定从一个解决方案迁移到另一个解决方案时,这将为您省去麻烦。我倾向于将我的DAO设计为"适配器",因此调用服务A的DAO将直接或通过消息队列调用它,独立于业务逻辑。当我需要更改它时,我可以将此DAO更改为另一个DAO,而无需触及任何业务逻辑(最终业务逻辑并不关心它是如何获取数据的)。六边形架构非常适合微服务,TDD和黑盒测试。

答案 4 :(得分:0)

我建议选择3。您必须在可用性和一致性之间进行选择-在微服务体系结构中,最经常需要可用性。

您的“学生”汇总应具有“ LicenseStatus”属性。创建学生后,其许可证状态将设置为“未验证”,并发布事件“ StudentCreated”。然后,LicenseService应对此事件做出反应,并尝试为该学生保留许可证。然后,它将相应地发布“保留”或“拒绝”事件。学生服务将通过订阅这些事件来更新学生的身份。

当UI调用您的API网关创建学生时,网关将简单地调用Student服务进行创建并返回202 Accepted或200 OK响应,而不必等待学生获得适当的许可。当学生通过异步通信(例如通过长轮询或Web套接字)获得许可时,UI可以通知用户。

如果许可服务出现故障或速度缓慢,则仅会影响许可。学生服务将仍然可用,并将继续成功处理请求。一旦许可证服务再次正常运行,服务总线就会从队列中推送所有未决的“ StudentCreated”事件(最终一致性)。

此方法还鼓励扩展。将来添加的新微服务可以订阅这些事件,而无需对学生或许可微服务进行任何更改(去耦)。

使用选项1或选项2,您将无法获得任何这些好处,并且由于一种不健康的微服务,许多微服务将停止工作。