一些背景知识:
我们有一个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函数,看起来像这样:
现在当我运行aplicaiton时,主要的Web API(现在继承自IService的那个)永远不会起来 - 在诊断窗口中,我可以看到创建监听器的无限循环。这是否意味着不能同时使用http侦听器和内部强类型RPC,或者我错过了什么?
我已阅读有关使用命名服务进行服务解析的信息,但我无法找到适合我的情况的任何文档或示例。
我真正需要做的是获取其他服务的本地地址,以便我可以通过http在本地调用它 - 这是我通过查询命名服务可以实现的吗?或者我可以只使用本地主机地址?(无论如何,负载在前面都是平衡的,所以我想这时不需要它,所以我可以在同一个节点上调用该服务)
答案 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}");
}
}
}
}
}
}