通过 Service Fabric 中的 http 公开 WCF restful 服务

Publicly exposing a WCF restful service via http from Service Fabric

我正在尝试通过 http 公开基于 WCF 的 restful 服务,但目前为止未成功。我首先在我的本地机器上尝试证明它有效。我发现了一个建议 here,我删除了我的本地集群,然后以管理员身份从 SF SDK 文件夹中手动 运行 这个 powershell 命令,以使用机器名称绑定重新创建它:.\DevClusterSetup.ps1 -UseMachineName

集群创建成功。我可以使用 SF Explorer 并在集群清单中看到 NodeList 中的条目显示机器名称而不是本地主机。这个好像不错。

但我注意到的第一个问题是,如果我通过 SF Explorer 扩展我的方式到我的应用程序正在 运行 的节点,我看到一个端点条目,但 URL 不是什么我希望。我看到了这个:http://surfacelap/d5be9425-3247-4290-b77f-1a90f728fb8d/39cda0f7-cef4-4c7f-8af2-d05786a834b0-131111019607641260

即使我设置了端点,这也是我应该看到的吗?我没想到路径中的guid和其他数字。这让我怀疑 SF 没有将我的服务视为可公开访问,而是可能只设置为在应用程序内进行内部访问?如果我深入研究我的服务清单,我会按预期看到:

<Resources>
    <Endpoints>
      <Endpoint Name="ResolverEndpoint" Protocol="http" Type="Input" Port="80" />
    </Endpoints>
</Resources>

但是我怎么知道服务本身是否映射到它?当我使用上面的 crazy long url 并尝试我的服务的一个简单方法时,我得到了一个 http 202 响应,但没有预期的响应数据。如果我随后将方法名称更改为不存在的方法名称,我会得到同样的结果,而不是预期的 http 404。我尝试同时使用我的机器名称和本地主机。同样的结果。

很明显我做错了什么。下面是我的 CreateServiceInstanceListeners 覆盖。在其中您可以看到我使用 "ResolverEndpoint" 作为我的端点资源名称,它与服务清单相匹配:

    protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
    {
        return new[] { new ServiceInstanceListener((context) =>
            new WcfCommunicationListener<IResolverV2>(
                serviceContext: context,
                wcfServiceObject: new ResolverServiceV2(),
                listenerBinding: new WebHttpBinding(WebHttpSecurityMode.None),
                endpointResourceName: "ResolverEndpoint"
            )
        )};
    }

我做错了什么?

服务清单中指定的端点资源由进程中使用相同端点资源名称的所有副本侦听器共享。因此,如果您的服务有多个分区,那么来自不同分区的多个副本可能会在同一进程中结束。为了区分发往不同分区的消息,侦听器将分区 ID 和附加实例 GUID 添加到路径中。

如果您要使用单例分区服务并且知道在同一进程中不会有多个副本,您可以直接提供您希望侦听器打开的 EndpointAddress。使用 CodePackageActivationContext API 从 NodeContext 的端点资源名称、节点名称或 IP 地址获取端口,然后提供您希望侦听器打开的路径。

这里是WcfCommunicationListener中构造Listen Address的代码。

  private static Uri GetListenAddress(
        ServiceContext serviceContext,
        string scheme,
        int port)
    {
        return new Uri(
            string.Format(
                CultureInfo.InvariantCulture,
                "{0}://{1}:{2}/{5}/{3}-{4}",
                scheme,
                serviceContext.NodeContext.IPAddressOrFQDN,
                port,
                serviceContext.PartitionId,
                serviceContext.ReplicaOrInstanceId,
                Guid.NewGuid()));
    }

请注意,您现在在一个节点上只能有一个应用程序、一个服务和一个分区,当您在本地测试时,将该服务的实例数保持为 1。在实际集群中部署时,您可以使用-1 个实例计数。

这里有一个让它工作的方法:https://github.com/loekd/ServiceFabric.WcfCalc

对代码的重要更改是使用集群的 public 名称作为端点 URL 以及该端点上的额外 WebHttpBehavior 行为。