3
votes

I haven't deployed behind a load balancer before. My customer has a WCF service built and tested on servers using a service model configuration that is relatively straightforward. It provides a service to return an image of a map for another application. To get the map, it calls other services.

The service was built in Visual Studio 2010 targeting the 3.5 framework. The customer is using IIS 7.5 and an F5 load balancer. When moving to the production server, the Web.config was changed to add the load balancer behavior and specify the endpoint to show the physical and logical address of the service:

        <services>
      <service behaviorConfiguration="Service.Service1Behavior" name="StaticMapImageService.Data.MapImageService">
        <endpoint 
                address="https://gis.customer.com/StaticMapImage/Service/StaticMapImageService.svc" 
                binding="basicHttpBinding" 
                bindingNamespace="http://customer.com"
                contract="StaticMapImageService.Data.IMapImageService"
                listenUri="http://hq-gis01.customer.net/StaticMapImage/Service/StaticMapImageService.svc"
                behaviorConfiguration="SSLLoadBalancerBehavior">
        </endpoint>
        <endpoint 
                address="mex" 
                binding="mexHttpBinding" 
                bindingNamespace="http://werner.com"
                contract="IMetadataExchange"/>
      </service>
    </services>

There is no entry for this service in the system.servicemodel/bindings section. The other services are configured in the bindings and client sections:

        <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_IAddressVerificationService"
            closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00"
            sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false"
            hostNameComparisonMode="StrongWildcard" maxBufferSize="999999999"
            maxBufferPoolSize="524288" maxReceivedMessageSize="999999999"
            messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
            useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="999999999" maxArrayLength="16384"
              maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="None">
            <transport clientCredentialType="None" proxyCredentialType="None"
                realm="" />
            <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
        </binding>
        <binding name="BasicHttpBinding_IGeocoderService" closeTimeout="00:01:00"
            openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
            allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
            maxBufferSize="999999999" maxBufferPoolSize="524288" maxReceivedMessageSize="999999999"
            messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
            useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="999999999" maxArrayLength="16384"
              maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="None">
            <transport clientCredentialType="None" proxyCredentialType="None"
                realm="" />
            <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
        </binding>
        <binding name="PCMilerSoap" closeTimeout="00:01:00" openTimeout="00:01:00"
            receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
            bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
            maxBufferSize="999999999" maxBufferPoolSize="524288" maxReceivedMessageSize="999999999"
            messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
            useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="999999999" maxArrayLength="16384"
              maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="None">
            <transport clientCredentialType="None" proxyCredentialType="None"
                realm="" />
            <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
        </binding>
      </basicHttpBinding>
      <wsHttpBinding>
        <binding name="WSHttpBinding_IGeocoderService" closeTimeout="00:01:00"
            openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
            bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
            maxBufferPoolSize="524288" maxReceivedMessageSize="999999999"
            messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
            allowCookies="false">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
              maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <reliableSession ordered="true" inactivityTimeout="00:10:00"
              enabled="false" />
          <security mode="Message">
            <transport clientCredentialType="Windows" proxyCredentialType="None"
                realm="" />
            <message clientCredentialType="Windows" negotiateServiceCredential="true"
                algorithmSuite="Default" establishSecurityContext="true" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <client>
      <endpoint address="https://gis.customer.com/AddressVerification/Service/AddressVerificationService.svc"
          binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IAddressVerificationService"
          contract="AddressVerificationService.IAddressVerificationService"
          name="BasicHttpBinding_IAddressVerificationService" />
      <endpoint address="https://gis.customer.com/Geocoder/Service/GeocoderService.svc/ws"
          binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IGeocoderService"
          contract="GeocoderService.IGeocoderService" name="WSHttpBinding_IGeocoderService">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>
      <endpoint address="https://gis.customer.com/Geocoder/Service/GeocoderService.svc/soap"
          binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IGeocoderService"
          contract="GeocoderService.IGeocoderService" name="BasicHttpBinding_IGeocoderService" />
      <endpoint address="http://hq-miler02.customer.net/MultiMiler/ALKWS/PCMiler.asmx"
          binding="basicHttpBinding" bindingConfiguration="PCMilerSoap"
          contract="PCMiler.PCMilerSoap" name="PCMilerSoap" />
    </client>

There was a problem when the service was deployed to a server behind the load balancer. When I try to call the service from WCFStorm or WebServiceStudio I get the message "The provided URI scheme 'https' is invalid; expected 'http'.

The endpoints for the service itself look right to me. However in the development and testing versions of the config, the client section uses http instead of http, while on the production servers it uses the load balancer's https address.

This seems like it should be obvious, but we're missing it. Can anybody give us a clue?

2
Anyone? Is this question that stupid? Was my question too long or unclear? TMI?Tim Rourke
No the question is good. But experience with this scenario is rare. Try to also ask on MSDN WCF forum: social.msdn.microsoft.com/Forums/en-US/wcf/threadsLadislav Mrnka
Thanks, Ladislav. I did that, though it didn't help in this case. It turned out our network security was changed and didn't let anything through even with the proper configuration. If you want to make your comment an answer, I'll mark it accepted.Tim Rourke

2 Answers

0
votes

We have wcf services set up behind Windows Network Load Balancing without any issue (well there was one, but it wasn't to do with NLB).

I think it's to do with the address. The web server is usually unaware that it's behind a load balancer. all it sees are requests coming from one source, the load balancer. Your binding has it listening for https, but unless the load balancer talks to the web server over https, which is rare, the requests are coming over http, hence the error.

You need to either change the address to http, or set the load balancer to talk to the web server via http.

0
votes

So I'm late to the party, but i ran into the same issue with calling a service behind F5. Change your client binding security to Transport instead of None.