代码之家  ›  专栏  ›  技术社区  ›  Jiew Meng

使用AWS API Gateway+Lambda/ECS开发的微服务应该如何对话?

  •  9
  • Jiew Meng  · 技术社区  · 7 年前

    我正在开发一个“微服务”应用程序,使用带有Lambda或ECS for compute的AWS API网关。现在的问题是服务之间的通信是通过API网关通过API调用实现的。这让人感觉效率低下,安全性也不如从前。有没有办法让我的微服务以一种更高效、更安全的方式相互交流?比如直接在私人网络里交谈?

    我想到的一个方法是多层次的API网关。

    • 1个公共API网关
    • 每个微服务1个专用API网关。每个微服务都可以在专用网络中“直接”调用另一个微服务

    但这样的话,我需要在两个层次的API中“复制”我的路由。。。这似乎不太理想。我在想也许用 {proxy+} . 什么都可以 /payment/{proxy+} 转到支付API网关等-仍然有两个级别的API网关。。。但这似乎是我能做的最好的了?

    也许有更好的办法?

    5 回复  |  直到 7 年前
        1
  •  7
  •   KiteCoder    7 年前

    将有很多方法来构建微服务。首先,我要熟悉AWS发布的白皮书: Microservices on AWS , Whitepaper - PDF version .

    在你的问题中你说: “现在的问题是服务之间的通信是通过API网关通过API调用实现的。这让人感觉效率低下,安全性也不如从前。有没有办法让我的微服务以一种更高效、更安全的方式相互交流?”

    是的-事实上,AWS白皮书,以及 API Gateway FAQ 将API网关作为应用程序的“前门”。API网关的目的是用于与AWS服务通信的外部服务。。不是AWS服务相互通信。

    AWS资源可以通过多种方式相互通信来调用微服务。白皮书中概述了一些,这是我使用的另一个资源: Better Together: Amazon ECS and AWS Lambda . 您使用的服务将基于您的需求。

    通过将单片应用程序分解为小型微服务,通信开销增加了,因为微服务必须相互通信。在许多实现中,REST over HTTP用作通信协议。这是一个轻量级的协议,但高容量可能会导致问题。在某些情况下,考虑合并来回发送大量消息的服务可能是有意义的。如果你发现你的情况下,你整合越来越多的服务只是为了减少聊天,你应该检讨你的问题域和你的域模型。

    据我所知,问题的根源是将请求路由到微服务。保持 Characteristics of Microservices “您应该选择一个单一的解决方案来管理路由。

    API网关

    您提到了使用API网关作为路由解决方案。API网关可用于路由。。。但是,如果选择使用API网关进行路由,则应在一个级别显式定义路由。为什么?

    1. 使用{proxy+}会增加攻击面,因为它需要在另一个微服务中正确处理路由。
    2. 在API网关中定义路由的优点之一是API是自文档的。如果您有多个API网关,它将成为合谋的。

    这样做的缺点是需要时间,并且可能需要更改已经定义的现有API。但是,您可能已经对现有代码库进行了更改,以遵循微服务最佳实践。

    Lambda或其他计算资源

    尽管上面列出了使用API网关进行路由的原因,但如果配置正确,另一个资源可以正确处理路由。可以将API网关代理设置为Lambda函数,该函数定义了所有微服务路由,或者 another resource within your VPC 已定义路由。

    结果

    你做什么取决于你的要求和时间。如果您已经在某个地方定义了一个API,并且只想使用API网关来限制、监视、保护和记录请求,那么您将使用API网关作为代理。如果您想从API网关中充分受益,请显式地定义其中的每个路由。这两种方法都可以遵循微服务的最佳实践,但是 意见 在API网关中定义每个公共API是与微服务体系结构保持一致的最佳方式。其他答案也很好地解释了每种方法的利弊。

        2
  •  6
  •   Dudemullet    7 年前

    我要去 假设解是Lambdas 但它们也可以是ECS实例或ELB实例。

    当前问题 original problem

    在进入解决方案之前,了解lambdas的一个重要概念是 应用程序代码 还有一个 event_source .

    事件源是调用 应用程序代码 . 您提到了API网关,它只是调用lambda(HTTP请求)的一种方法。其他有趣的 event sources 与您的解决方案相关的是:

    • Api网关(如前所述,对服务间通信无效)
    • Direct invocation (通过AWS Sdk,可以同步或异步)
    • SNS (发布/订阅,事件总线)
    • 有超过20种不同的方法调用lambda。 documentation

    用例#1同步

    因此,如果HTTP_响应依赖于一个lambda调用另一个lambda并依赖于第二个lambda结果。直达的 invoke 可能是一个很好的解决方案,这样你就可以 invoke 以同步方式的lambda。这也意味着,lambda应该作为事件源订阅到API网关,并有代码来规范这两种不同类型的事件。(这就是为什么lambda文档通常有 event 作为参数之一)

    Sync use case

    用例2异步

    如果您的HTTP响应不依赖于其他微服务(lambdas)的执行。我强烈建议在这个用例中使用SNS,因为原来的lambda发布单个事件,并且可以有多个lambda订阅该事件并并行执行。

    Async/parallel execution

    更复杂的用例

    对于更复杂的用例:

        3
  •  1
  •   nbari    7 年前

    除了绑定到当前的设置和基础设施之外,还有多种方法和方法,而不排除实现/修改现有代码库的灵活性。

    当试图在API网关后面的服务之间进行通信时,需要小心实现以避免循环、暴露数据甚至最坏情况、阻塞自己时,请参见“通用”图像以获得更好的理解: enter image description here

    使用时 超文本传输协议 对于服务之间的通信,经常会看到流量从当前基础设施流出,然后通过同一个API网关返回,这是可以通过直接将另一个服务转移到位来避免的。

    例如,在上一个图像中,当 service B 需要与 service A 建议通过内部(ELB)终结点执行此操作,而不是通过API网关外出或返回。

    另一种方法是使用“only” 超文本传输协议 在API网关中,并使用其他协议在您的服务中进行通信,例如, gRPC . (在某些情况下不是最好的选择,因为依赖于您的体系结构和灵活性来修改/适应现有代码)

    在某些情况下,您的基础结构更为复杂,您可能无法在容器中按需通信,或者无法访问端点,在这种情况下,您可以尝试实现 event-driven architecture (SQS和AWS Lambda)

    我喜欢去 异步的 在可能的情况下,通过使用事件/队列,从我的角度来看,可以更好地“扩展”服务,而且服务必须成为消费者/工作者,而且不需要监听传入的请求(不需要HTTP),下面是一篇文章,解释如何使用 rabbitmq for this purpose communicating microservices within docker

    这些只是一些想法,希望能帮助你找到自己的“最佳”方式,因为是一些变化太大,每一个场景都是独特的。

        4
  •  1
  •   Arnold Galovics    7 年前

    我不认为您的问题与AWS有严格的关系,但更像是服务之间的一般通信方式。

    API网关用作边缘服务,是位于后端边界的服务,可由外部方访问。对于API网关后面的通信,在您的微服务之间,您不必再次通过API网关。

    有两种沟通方式,我想为你的案子提一下:

    • 超文本传输协议
    • 消息传递

    HTTP是最简单的通信方式,因为它自然更容易理解,并且有大量的库使其易于使用。

    尽管有好处,但还是有几件事要注意。

    • 故障处理
    • 服务无法响应时的电路中断
    • 一致性
    • 重试次数
    • 在调用另一个服务时,使用服务发现(例如EURKA)使系统更灵活

    在消息传递方面,您必须处理异步处理、基础结构问题(如设置和维护消息代理),它不像纯HTTP那么容易使用,但是您可以通过最终保持一致来解决一致性问题。

    总的来说,有很多事情你必须考虑,一切都是关于取舍。如果您只是从微服务开始,我认为最好从使用HTTP进行通信开始,然后慢慢转到消息传递选项。

    例如,在Java+Spring云Netflix世界中,您可以使用Eureka和Feign,这样就很容易使用逻辑地址到由Eureka转换为实际IP和端口的服务。另外,如果您想在restapi中使用Swagger,甚至可以 generate Feign client stubs 从它。

        5
  •  0
  •   xpa1492    7 年前

    我已经有一段时间在想同样的问题,但仍然找不到一个好的通用解决方案。。。为了它的价值。。。

    如果交流是单向的,而“调用者”不需要等待结果,我发现动觉流非常强大——只要在流上发布一个“任务”,让流触发一个lambda来处理它。但很明显,这在非常有限的情况下有效。。。

    对于响应-应答世界,我像最终用户一样调用API网关端点(在HTTP世界中封送和解组数据以“适应”所增加的开销,以及不必要的多重身份验证)。

    在极少数情况下,我可能有一个后端lambda函数,它由网关API lambda和其他微服务直接调用。这为“最终用户”添加了额外的“跃点”(而不是[UI->网关API->网关API lambda],现在我有了[UI->网关API->网关API lambda->后端lambda]),但使微服务发起的调用更快(因为调用和所有相关数据不再需要通过HTTP请求“隧道化”)。另外,这使得体系结构更加复杂(我不再有一个正式的API,而是有一个“back channel”直接依赖项)。