Service Fabric 具有不同 ContractDescriptions 的多个 ServiceEndpoint

Posted

技术标签:

【中文标题】Service Fabric 具有不同 ContractDescriptions 的多个 ServiceEndpoint【英文标题】:Service Fabric multiple ServiceEndpoints with different ContractDescriptions 【发布时间】:2017-12-19 05:36:20 【问题描述】:

我已经使用无状态服务和 Web API 设置了一个基本的 Service Fabric 解决方案,并使用默认服务远程侦听器测试了一切正常。快乐的日子!

当我尝试用服务总线中继(我打算如何与服务通信)替换默认侦听器时,我在启动时遇到错误。

CreateServiceInstanceListeners()

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()

    return new[]  
        new ServiceInstanceListener(context => 
            var wcfRelay = new WcfCommunicationListener<ICommercial>(
                wcfServiceObject: this,
                serviceContext: context,
                endpointResourceName: "serviceRelay");

            return wcfRelay;
        )
    ;

服务配置(app.config)

  <system.serviceModel>
    <extensions>…</extensions>
    <services>
      <service name="Commercial.Service.CommercialService">
        <endpoint address="http://[namespace].servicebus.windows.net/CommercialService" 
                  name="serviceRelay" 
                  binding="basicHttpRelayBinding" 
                  contract="Commercial.Interface.ICommercial" 
                  behaviorConfiguration="relayToken" />
      </service>
    </services>
    <bindings>
      <basicHttpRelayBinding>
        <binding closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" maxBufferSize="5886800" maxBufferPoolSize="524288" maxReceivedMessageSize="5886800" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="5886800" maxArrayLength="5886800" maxBytesPerRead="5886800" maxNameTableCharCount="16384" />
        </binding>
      </basicHttpRelayBinding>
    </bindings>
    <behaviors>
      <endpointBehaviors>
        <behavior name="relayToken">
          <transportClientEndpointBehavior>
            <tokenProvider>
              <sharedAccessSignature keyName="RootManageSharedAccessKey" key="[key]" />
            </tokenProvider>
          </transportClientEndpointBehavior>
        </behavior>
      </endpointBehaviors>
    </behaviors>
  </system.serviceModel>

如果我中断侦听器的创建,我会看到它正在创建两个服务端点:

enter image description here

最终,Service Fabric Explorer 中的每个节点都会出现此错误。

不健康事件:SourceId='System.RA'、Property='ReplicaOpenStatus'、HealthState='Warning'、ConsideWarningAsError=false。副本在_Node_1 API 调用中有多个失败:IStatelessServiceInstance.Open();错误 = System.InvalidOperationException (-2146233079) 服务包含多个具有不同 ContractDescriptions 的 ServiceEndpoint,每个都有 Name='ICommercial' 和 Namespace='http://[schema_path]/20170713'。要么为 ContractDescriptions 提供唯一的名称和命名空间,要么确保 ServiceEndpoints 具有相同的 ContractDescription 实例。在 System.ServiceModel.Dispatcher.UniqueContractNameValidationBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase) 在 System.ServiceModel.Description.DispatcherBuilder.ValidateDescription(ServiceDescription description, ServiceHostBase serviceHost) 在 System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription description, ServiceHostBase serviceHost) ) 在 System.ServiceModel.Channels.CommunicationObject.OpenAsyncResult.InvokeOpen() 在 System.ServiceModel.Channels 的 System.ServiceModel.ServiceHostBase.OnBeginOpen(TimeSpan 超时,AsyncCallback 回调,对象状态)的 System.ServiceModel.ServiceHostBase.InitializeRuntime()。 CommunicationObject.OpenAsyncResult..ctor(CommunicationObject communicationObject, TimeSpan timeout, AsyncCallback callback, Object state) at System.ServiceModel.Channels.CommunicationObject.BeginOpen(TimeSpan timeout, AsyncCallback callback, Object state) at Microsoft.ServiceFabric.Services.Communication .Wcf.Runtime.WcfCommunicationListener`1.Microsoft.ServiceFabric.Services.Communication.Runtime.ICommunicationListener.OpenAsync(CancellationToken cancelToken) at Microsoft.ServiceFabric.Services.Runtime.StatelessServiceInstanceAdapter.d__20.MoveNext() --- 堆栈跟踪结束以前引发异常的位置 --- 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 在 Microsoft.ServiceFabric.Services.Runtime.StatelessServiceInstanceAdapter.d__14.MoveNext( )

我不太清楚如何解决这个“要么为 ContractDescriptions 提供唯一的名称和命名空间,要么确保 ServiceEndpoints 具有相同的 ContractDescription 实例”。

【问题讨论】:

【参考方案1】:

endpointResourceName 应该明确指向您在 ServiceManifest 文件中指定的端点。无论如何,我什至不确定 app.config 甚至可以在这里工作......你见过任何使用 app.confing 的 WCF 监听器的 SF 示例吗?查看这个很好的示例以在代码中配置所需的设置 - ServiceFabric.WcfCalc。希望它会有所帮助。

【讨论】:

我可以从创建的监听器中看到它正在创建 app.config 中配置的监听器。我猜的问题是为什么要创建第二个默认 net.tcp 侦听器(参见主帖中的图片)。这就是产生错误的原因。 @ConfusedMonkey 在我的机器上重现了你的问题,我想说你有两个端点的原因是 - 第一个端点是从你的 app.config 文件中创建的,第二个端点是由SF 从您的清单文件中取出,这就是您的服务将在 SF Naming Service 中解析和知晓的方式。因此,我仍然建议您查看我在上面发布的文章,并在创建 wcf 侦听器时在代码中进行所有必需的配置。 @ConfusedMonkey 好像有一篇文章准确地展示了如何在 SF 中配置 wcf 中继侦听器 - Setup a Azure Service Fabric Listener for Service Bus Relay Binding。

以上是关于Service Fabric 具有不同 ContractDescriptions 的多个 ServiceEndpoint的主要内容,如果未能解决你的问题,请参考以下文章

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

Service Fabric:具有分区负载平衡的可靠服务管道

Service Fabric 服务参考具有黄色三角形

具有 5 个节点的 Service Fabric 本地开发集群运行的实例和分区少于预期

Azure Service Fabric - 针对不同环境的不同发布设置

Service Fabric:将枚举类移动到不同的项目