【问题标题】:Unique Name must be specified for each listener when multiple communication listeners are used使用多个通信侦听器时,必须为每个侦听器指定唯一名称
【发布时间】:2018-10-16 05:56:39
【问题描述】:

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

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

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

我在 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 链接中: serviceappcode

【问题讨论】:

    标签: azure azure-service-fabric service-fabric-stateless


    【解决方案1】:

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

    姓名

    通信侦听器的名称。如果无状态服务只有一个通信侦听器,则此参数是可选的。如果未给出,则将 Name 设置为 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"); 
    

    【讨论】:

    • 感谢您的回复,现在我没有收到异常,但是当我使用“ServiceProxy”调用服务时,我无法调用此服务方法示例代码:var client = ServiceProxy .Create(new Uri("fabric:/AuthenticationServiceApp/AuthenticationServiceApi")); var 结果 = client.OnRouteMessageaAsync("topic");
    • 是的,很抱歉,忘记提及您也需要在客户端使用该名称,请参阅更新后的答案
    • 谢谢,但即使我无法调用该方法,它也不会引发任何异常,我尝试使用错误的服务 uri,它在服务结构集群中不存在,例如 fabric :/Auth/AuthenticationServiceApi即使它没有给出异常。
    • 好的,您能否使用使用ServiceProxy.Create&lt;ICommunication&gt; 调用服务的方法的完整代码更新您的问题?
    • 那么...如果您在异常处理程序中设置断点,没有?现在你只是在吞下任何异常。
    猜你喜欢
    • 2016-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-15
    相关资源
    最近更新 更多