当使用多个通信侦听器时,必须为每个侦听器指定唯一名称

Unique Name must be specified for each listener when multiple communication listeners are used

我创建了一个 .NET Core 无状态 Service Fabric 应用程序 (v 3.0.467)。我需要为此服务同时使用 KestrelCommunicationListener 和 ServiceProxy 远程调用。

当我将应用程序部署到本地集群时,它抛出异常:

Unique Name must be specified for each listener when multiple communication listeners are used

我在servicemanifest.xml文件中配置如下

<Resources>
    <Endpoints>
      <!-- This endpoint is used by the communication listener to obtain the port on which to 
           listen. Please note that if your service is partitioned, this port is shared with 
           replicas of different partitions that are placed in your code. -->
      <Endpoint Name="ServiceEndpointV2" />
      <Endpoint Protocol="http" Name="httpServiceEndpoint" Type="Input" Port="9098" />
    </Endpoints>
  </Resources>

和代码示例:

  protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
        {
            return new[]
            {
                 new ServiceInstanceListener((context) =>
                {

                    // return new FabricTransportServiceRemotingListener(context, this);

                      return new FabricTransportServiceRemotingListener(context, this,new Microsoft.ServiceFabric.Services.Remoting.FabricTransport.Runtime.FabricTransportRemotingListenerSettings(){EndpointResourceName = "ServiceEndpointV2" });

                }),
                new ServiceInstanceListener(serviceContext =>
                    new KestrelCommunicationListener(serviceContext, "httpServiceEndpoint", (url, listener) =>
                    {
                        ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");

                        return new WebHostBuilder()
                                    .UseKestrel()
                                    .ConfigureServices(
                                        services => services
                                            .AddSingleton<StatelessServiceContext>(serviceContext))
                                    .UseContentRoot(Directory.GetCurrentDirectory())
                                    .UseStartup<Startup>()
                                    .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                                    .UseUrls(url)
                                    .Build();
                    }))
         };
        }

这个配置有没有错误?

更新:

以下代码是从客户端调用的服务示例方法:

 public Task<string> OnRouteMessageaAsync(string tenant)
   {
            return Task.FromResult(tenant);
   }

客户代码:

 private async Task<string> RemoteServiceCall()
        {
            try
            {
                var client = ServiceProxy.Create<ICommunication>(new Uri("fabric:/AuthenticationServiceApp/AuthenticationServiceApi"), listenerName: "RemotingListener");
                var response = client.OnRouteMessageaAsync("tenant");
                return response.Result;
            }
            catch (Exception ex)
            {

            }
            return null;
        }

示例代码如下GitHub link: serviceappcode

您定义了多个 ServiceInstanceListener。为了让 Service Fabric 区分它们,您需要使用 ServiceInstanceListener 的构造函数的可选 name 参数来命名它们。见 the docs:

Name

Name of the communication listener. This parameter is optional if the Stateless Service has only one communication listener. If it is not given, the Name is set to DefaultName.

    protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
    {
        return new[]
        {
            new ServiceInstanceListener((context) =>
            {

                // return new FabricTransportServiceRemotingListener(context, this);

                return new FabricTransportServiceRemotingListener(context, this,new Microsoft.ServiceFabric.Services.Remoting.FabricTransport.Runtime.FabricTransportRemotingListenerSettings(){EndpointResourceName = "ServiceEndpointV2" });

            }, name: "RemotingListener"),
            new ServiceInstanceListener(serviceContext =>
                new KestrelCommunicationListener(serviceContext, "httpServiceEndpoint", (url, listener) =>
                {
                    ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");

                    return new WebHostBuilder()
                        .UseKestrel()
                        .ConfigureServices(
                            services => services
                                .AddSingleton<StatelessServiceContext>(serviceContext))
                        .UseContentRoot(Directory.GetCurrentDirectory())
                        .UseStartup<Startup>()
                        .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                        .UseUrls(url)
                        .Build();
                }), name: "KestrelCommunicationListener")
        };
    }

现在,您在使用远程调用服务时也必须使用此名称:

var client = ServiceProxy.Create<ICommunication>(
    new Uri("fabric:/AuthenticationServiceApp/AuthenticationServiceApi"), 
    listenerName: "RemotingListener"); 
var result = client.OnRouteMessageaAsync("topic");