使用 Azure Service Fabric 部署的微服务的 API 网关/代理模式
Posted
技术标签:
【中文标题】使用 Azure Service Fabric 部署的微服务的 API 网关/代理模式【英文标题】:API gateway/proxy pattern for microservices deployed using Azure Service Fabric 【发布时间】:2015-07-11 20:27:56 【问题描述】:在观看了 Azure Service Fabric 的 BUILD 会议视频后,我开始想象这可能非常适合我们当前基于微服务的架构。但是,我不完全确定如何解决一件事 - API 网关/代理。
考虑一个不那么简单的微服务体系结构,其中有 N 个服务在 Azure Service Fabric 中运行,暴露 REST 端点。在许多情况下,您希望将这些零散的 API 端点打包成一个单入口 API 供消费者使用,以避免让它们直接连接到服务结构实例。 Azure Service Fabric 解决方案似乎在各个方面都如此完整,以至于当我在 BUILD 会谈中提到的功能中看不到可以轻松解决此问题的方法时,我有点想知道我是否遗漏了一些明显的东西。
Vulcan 等服务旨在通过让服务在etcd 中注册它们想要路由到它们的路径来解决这个问题。我猜想解决这个问题的一种方法可能是创建一个单独的有状态 Web 服务,其他服务可以注册自己,提供服务名称和它们需要路由到它们的路径。然后,有状态 Web 服务可以根据其状态将流量路由到正确的实例。但是,这似乎并不完全理想,例如在删除应用程序时删除路由以及通常使状态与部署在集群中的服务保持同步。有没有人考虑过这个问题,或者知道如何在 Azure Service Fabric 中解决这个问题?
【问题讨论】:
【参考方案1】:您需要执行此操作的服务注册/可发现性实际上已经存在。有一个称为命名服务的有状态系统服务,它基本上是服务实例和它们正在侦听的端点的注册器。因此,当您启动服务(无论是无状态的还是有状态的)并在其上打开一些侦听器时,该地址就会在命名服务中注册。
现在您需要填写的部分是用户与之交互的“网关”。这不必是有状态的,因为命名服务管理有状态的部分。但是你必须想出一个适合你的寻址方案,然后它将请求转发到正确的位置。基本上是这样的:
-
接收请求。
使用 NS 查找可以接受请求的服务。
将请求转发给它,并将响应返回给用户。
如果服务不再存在,404。
一般来说,我们不喜欢规定任何关于您的服务如何相互通信的内容,但我们正在考虑解决这个问题的方法,将 HTTP 作为一个完整的内置解决方案。
【讨论】:
这是一个有趣的方法。我似乎找不到关于命名服务的任何特定文档,但是,您是否碰巧有更多关于它的信息?我看到它注册为fabric:/System/NamingService
,但我找不到任何接口或类似的东西我可以用来例如使用ServiceProxy.Create<TServiceInterface>
与它通信。我假设ServiceProxy
内部正在与它通信,所以我猜有一种方法:)
实际上,我在FabricClient
中找到了一些有助于枚举集群中的节点/应用程序/部署的东西。我应该能够使用它来确定哪些服务希望将流量路由到它们(通过服务命名方案或其他方式)并实现一些简单的逻辑来测试它。谢谢指点!
你明白了,FabricClient 是你与系统通信的网关。使用 ServiceManager 属性进行服务解析。 ServiceProxy 是一种用于在服务之间轻松通信的内置机制(基本上为您提供服务之间的强类型 RPC)。是的,它在内部使用 FabricClient 进行服务解析!
如果有一些使用 FabricClient 的具体例子来达到这个目的会很好。它包含很多功能,在这里应用的使用模式一点也不明显。
@VaclavTurecek 有没有您描述的方法示例?【参考方案2】:
我们也为此目的实施了 HTTP 网关服务。为了确保我们可以为任何内部协议提供一个 HTTP 网关,我们使用 ASP.NET 5 中间件为基于 HTTP 的内部服务(如 ASP.NET WebAPI)实现了网关。它使用ServicePartitionClient
和来自CommunicationClientFactoryBase
的一些重试逻辑将请求从例如/service 路由到内部Service Fabric 地址,例如fabric:/myapp/myservice。
我们开源了这个中间件,你可以在这里找到它: https://github.com/c3-ls/ServiceFabric-HttpServiceGateway
项目的 wiki 中还有更多文档。
【讨论】:
在 https 上设置这个有很多麻烦。你们有没有尝试在 https 上运行它?【参考方案3】:从 Service Fabric 5.0 版开始,此功能内置于 http 端点。文档位于https://azure.microsoft.com/en-us/documentation/articles/service-fabric-reverseproxy/
【讨论】:
在大多数情况下,只要您了解使用它的后果,通过反向代理进行通信就足够了。集群中任何暴露 HTTP 端点的服务都可以从外部客户端寻址。您的 DevOps 团队很可能会认为这是不可接受的。【参考方案4】:我们使用了一个名为Traefik 的开源项目并取得了惊人的成功。它周围有一个 Azure Service Fabric 包装器 - 它本质上是一个 GoLang exe,作为托管可执行文件部署到集群上。
它支持断路器、加权循环 LB、路径和标头版本路由(这对于托管多个 API 版本来说非常棒),不胜枚举。它有一个方便的门户来查看配置和健康统计数据。
它的真正威力在于您如何配置它。它是通过ServiceManifest.xml
中的服务本身完成的。这允许您部署新服务并立即将它们路由到 - 无需更新路由表等。
例子
<StatelessServiceType ServiceTypeName="WebServiceType">
<Extensions>
<Extension Name="Traefik">
<Labels xmlns="http://schemas.microsoft.com/2015/03/fabact-no-schema">
<Label Key="traefik.frontend.rule.example">PathPrefixStrip: /a/path/to/service</Label>
<Label Key="traefik.enable">true</Label>
<Label Key="traefik.frontend.passHostHeader">true</Label>
</Labels>
</Extension>
</Extensions>
</StatelessServiceType>
强烈推荐!
【讨论】:
我也将 Traefik 与 Service Fabric 结合使用。非常无缝!【参考方案5】:Azure Service Fabric 可以轻松实现此场景的标准架构:网关服务作为客户端连接的前端,所有 N 个后端服务与前端网关进行通信。作为 Service Fabric 的一部分,有一些通信 API 堆栈可用于轻松地从客户端到服务以及在服务内部进行通信。 Service Fabric 提供的通信 API 堆栈隐藏了发现、连接和重试连接的详细信息,以便您可以专注于实际的信息交换。使用 Service Fabric 通信 API 时,服务不必实现将其名称和终结点注册到特定路由服务的机制,除非是创建服务本身的常规步骤。通信 API 接收服务 URI 和分区键,并自动解析并连接到正确的服务实例。 This article 提供了一个很好的起点,可帮助您决定哪些通信 API 最适合您的特定情况,具体取决于您使用的是 Reliable Actors 还是 Reliable Services,还是 HTTP 或 WCF 等协议,或者选择编写服务所用的编程语言。在文章末尾,您将找到指向不同通信 API 的更详细文章和教程的链接。有关 Web API 服务中通信的教程,请参阅this。
【讨论】:
我了解 Service Fabric 服务的通信侦听器概念,以便与服务进行实际通信;我想象的是“Service1”想要服务/foo/*
,“Service2”想要服务/bar/*
;然后在api.mydomain.com
上设置一个共享 API 代理,将适当的 URI 代理到后端的适当服务中。编排这种类型的路由似乎需要一些工作,而我的问题更多的是“这是 Service Fabric 将提供的东西,还是我需要自己动手?”。
另外,为了进一步明确;我希望从这种 API 代理中发现哪些服务在运行时需要哪些路径(通过以某种方式枚举 Service Fabric 集群中的服务,提取每个服务的元数据 - 或者让服务自己告诉代理他们想要路由到自己的路径)。当可能有数百个服务时,必须维护一些硬编码的路由似乎很麻烦。【参考方案6】:
我们使用带有网关模式的 SF 和网关后面的大约 13 个服务。我们使用 SF 提供的内置 DNS 服务,请参阅:https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-dnsservice,这允许内部服务使用已知(SF 内部)DNS 名称服务调用,包括内部服务的网关服务。有一些众所周知的 asp.net 核心网关(Ocelot、ProxyKit)可供使用,但我们推出了自己的。我们有一个外部负载均衡器来路由到 SF 中的多个网关实例。
【讨论】:
【参考方案7】:当服务启动时,它会将其端点注册到结构命名服务。然后,您可以使用 Fabric 客户端 API 向 Fabric 请求注册的端点,并与注册的服务名称相关联。
所以是的,就像您描述的情况一样,您将拥有一个网关,该网关将接受传入的 URI 进行连接,然后使用该路径信息作为服务名称查找,然后在传入请求和实际的内部端点位置。
看起来团队发布了一个演示如何执行此操作的示例:https://github.com/Azure/servicefabric-samples/tree/master/samples/Services/VS2015/WordCount
【讨论】:
【参考方案8】:我想知道,与其在 N+ 服务上公开 Rest,不如在服务结构内的任何地方使用默认的 comm 堆栈(或尽可能在内部保持简单)。仅在结构的边缘入口点公开 REST。使用 std stateless web 2.x api 包装您的服务和参与者的结构代理,和/或使用结构服务以相同的方式公开休息。根据需要在面向前的 Rest 服务中聚合您的 api。不确定我是否需要额外的聚合器开销来命名重定向(也许我错过了这个想法)。那么它似乎只是用所需的命名空间(即外观模式)组织(和保护)休息端点的练习。
【讨论】:
以上是关于使用 Azure Service Fabric 部署的微服务的 API 网关/代理模式的主要内容,如果未能解决你的问题,请参考以下文章
Azure App Service 与 Azure Service Fabric [关闭]