0

I've set up a basic Service Fabric solution with a stateless service and Web API and tested that everything works using the default service remoting listener. Happy days!

When I try to replace the default listener with a service bus relay (how I intend to communicate with the service) I'm getting errors at startup.

CreateServiceInstanceListeners()

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

            return wcfRelay;
        })
    };
}

Service config (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>

If I break in the listener creation I see it's creating two service endpoints:

enter image description here

And eventually I get this error showing up for each node in Service Fabric Explorer.

Unhealthy event: SourceId='System.RA', Property='ReplicaOpenStatus', HealthState='Warning', ConsiderWarningAsError=false. Replica had multiple failures in_Node_1 API call: IStatelessServiceInstance.Open(); Error = System.InvalidOperationException (-2146233079) The Service contains multiple ServiceEndpoints with different ContractDescriptions which each have Name='ICommercial' and Namespace='http://[schema_path]/20170713'. Either provide ContractDescriptions with unique Name and Namespaces, or ensure the ServiceEndpoints have the same ContractDescription instance. at System.ServiceModel.Dispatcher.UniqueContractNameValidationBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase) at System.ServiceModel.Description.DispatcherBuilder.ValidateDescription(ServiceDescription description, ServiceHostBase serviceHost) at System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription description, ServiceHostBase serviceHost) at System.ServiceModel.ServiceHostBase.InitializeRuntime() at System.ServiceModel.ServiceHostBase.OnBeginOpen(TimeSpan timeout, AsyncCallback callback, Object state) at System.ServiceModel.Channels.CommunicationObject.OpenAsyncResult.InvokeOpen() at System.ServiceModel.Channels.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 cancellationToken) at Microsoft.ServiceFabric.Services.Runtime.StatelessServiceInstanceAdapter.d__20.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.ServiceFabric.Services.Runtime.StatelessServiceInstanceAdapter.d__14.MoveNext()

I'm not exactly clear how to remedy this "Either provide ContractDescriptions with unique Name and Namespaces, or ensure the ServiceEndpoints have the same ContractDescription instance".

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
ConfusedMonkey
  • 3
  • 1
  • 1
  • 6

1 Answers1

0

The endpointResourceName should definitely point to the endpoint that you have specified within your ServiceManifest file. Anyway I'm not even sure that app.config will even work here... Have you seen any SF example with WCF listener that uses app.confing? Check out this nice example to configure the required settings in code - ServiceFabric.WcfCalc. Hopefully it will help.

Kiryl
  • 1,416
  • 9
  • 21
  • I can see from the created listeners that it is creating the one configured in app.config. The question I guess is why a second default net.tcp listener is created (see image in main post). This is why the error is being generated. – ConfusedMonkey Jul 24 '17 at 09:57
  • @ConfusedMonkey Having reproduced your issue on my machine, I'd say the reason you have two endpoints is this - the first endpoint gets created out of your app.config file, the second one is built by SF out of your manifest file, which is how your service will be resolved and known at SF Naming Service. So I'd still recommend to take a look at the article I've posted above and do all the required configuration in code when you create your wcf listener. – Kiryl Jul 26 '17 at 08:02
  • @ConfusedMonkey Seems like there is a post that shows exactly how to configure wcf relay listener in SF - [Setup a Azure Service Fabric Listener for Service Bus Relay Binding](https://stackoverflow.com/questions/43055785/setup-a-azure-service-fabric-listener-for-service-bus-relay-binding). – Kiryl Jul 26 '17 at 10:21