Service Fabric Web Api具有外部和内部端点

时间:2017-04-14 08:12:36

标签: c# azure asp.net-web-api azure-service-fabric

一些背景知识:

我们有一个Service Fabric应用程序,其中包含 2个WebApi服务(和其他)。一个是我们的实际前端API,第二个是某些特定客户的第一个代理。两个WebApis都在不同的端口上公开。对于通信,我们使用了服务模板附带的OwinCommunicationListener(我们只是调整它以允许使用https)。当客户端调用代理API时,我们当前正在使用HttpClient,它调用实际API的公共IP地址。

这显然没有意义,因为WebApis都托管在同一台机器上,因此我们希望通信不是通过互联网进行本地通信。对于从API 到我们在ServiceProxy(强类型RPC)中内置的其他微服务的通信。目前,我们的前端API有两个侦听器(http,https)。

为了实现我们的目标(API有2个公共http(s)端点和一个内部端点),我们提出了这样的想法:我们只需将RPC侦听器与http侦听器一起添加到侦听器列表中。因此,在这种情况下,API将为公共流量提供2个http侦听器,为内部流量提供1个RPC。在这种情况下,我们重构了主要的API来继承自

  

IService

,然后我们调整了CreateServiceInstanceListeners函数,看起来像这样:

enter image description here

现在当我运行aplicaiton时,主要的Web API(现在继承自IService的那个)永远不会起来 - 在诊断窗口中,我可以看到创建监听器的无限循环。这是否意味着不能同时使用http侦听器和内部强类型RPC,或者我错过了什么?

我已阅读有关使用命名服务进行服务解析的信息,但我无法找到适合我的情况的任何文档或示例。

我真正需要做的是获取其他服务的本地地址,以便我可以通过http在本地调用它 - 这是我通过查询命名服务可以实现的吗?或者我可以只使用本地主机地址?(无论如何,负载在前面都是平衡的,所以我想这时不需要它,所以我可以在同一个节点上调用该服务)

2 个答案:

答案 0 :(得分:1)

创建多个通信侦听器时,请确保命名,如下所示:

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
        {
            yield return new ServiceInstanceListener(p => new SubscriberCommunicationListener(this, p), "StatelessSubscriberCommunicationListener");
            yield return new ServiceInstanceListener(context => new FabricTransportServiceRemotingListener(context, this), "StatelessFabricTransportServiceRemotingListener");
        }

以下是使用名称

创建代理的代码
var subStateless = ServiceProxy.Create<ISubscribingStatelessService>(new    
    Uri("fabric:/MyServiceFabricApp/SubscribingStatelessService"),
    listenerName: "StatelessFabricTransportServiceRemotingListener");

Here's示例实现。

答案 1 :(得分:1)

命名服务可以通过REST API或通过FabricClient连接到群集来实现。这些API中的各种操作实际上使用命名服务。然而,它不是你可以(好吧,你不应该)连接的服务。相反,您可以使用FabricClient的QueryManager列出群集中服务的已注册端点。这将显示您的服务的注册端点。

var fabricClient = new FabricClient();
var applicationList = fabricClient.QueryManager.GetApplicationListAsync().GetAwaiter().GetResult();
foreach (var application in applicationList)
{
    var serviceList = fabricClient.QueryManager.GetServiceListAsync(application.ApplicationName).GetAwaiter().GetResult();
    foreach (var service in serviceList)
    {
        var partitionListAsync = fabricClient.QueryManager.GetPartitionListAsync(service.ServiceName).GetAwaiter().GetResult();
        foreach (var partition in partitionListAsync)
        {
            var replicas = fabricClient.QueryManager.GetReplicaListAsync(partition.PartitionInformation.Id).GetAwaiter().GetResult();
            foreach (var replica in replicas)
            {
                if (!string.IsNullOrWhiteSpace(replica.ReplicaAddress))
                {
                    var replicaAddress = JObject.Parse(replica.ReplicaAddress);
                    foreach (var endpoint in replicaAddress["Endpoints"])
                    {
                        var endpointAddress = endpoint.First().Value<string>();
                        Console.WriteLine($"{service.ServiceName} {endpointAddress} {endpointAddress}");
                    }
                }
            }
        }
    }
}