Testing Out the New AppFabric Service Bus Relay Load Balancing

The Windows Azure team made a change in the back end to support multiple listeners on a single relay endpoint.  This solves a known challenge with the Service Bus.  Up until now, we had to be creative when building highly available Service Bus solutions since only a single listener could be live at one time.  For more on this change, see Sam Vanhoutte’s descriptive blog post.  In this post, I’m going to walk through an example that tests out the new capability.

First off, I made sure that I had the v1.5 of the Azure AppFabric SDK. Then, in a VS2010 Console project, I built a very simple RESTful WCF service contract.

namespace Seroter.ServiceBusLoadBalanceDemo
{
    [ServiceContract]
    interface IHelloService
    {
        [WebGet(UriTemplate="/{name}")]
        [OperationContract]
        string SayHello(string name);
    }
}

My service implementation is nothing exciting.

public class HelloService : IHelloService
    {
        public string SayHello(string name)
        {
            Console.WriteLine("Service called for name: " + name);
            return "Hi there, " + name;
        }
    }

My application configuration for this service looks like this (note that I have all the Service Bus bindings here instead of machine.config):

<?xml version="1.0"?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="CloudBehavior">
          <webHttp />
          <serviceRegistrySettings discoveryMode="Public" displayName="HelloService" />
          <transportClientEndpointBehavior>
            <clientCredentials>
              <sharedSecret issuerName="ISSUER" issuerSecret="SECRET" />
            </clientCredentials>
            <!--<tokenProvider>
              <sharedSecret issuerName="" issuerSecret="" />
            </tokenProvider>-->
          </transportClientEndpointBehavior>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <bindings>
      <webHttpRelayBinding>
        <binding name="WebRelayBinding">
          <security relayClientAuthenticationType="None" />
        </binding>
      </webHttpRelayBinding>
    </bindings>
    <services>
      <service name="Seroter.ServiceBusLoadBalanceDemo.HelloService">
        <endpoint address="https://<namespace>.servicebus.windows.net/HelloService"
          behaviorConfiguration="CloudBehavior" binding="webHttpRelayBinding"
          bindingConfiguration="WebRelayBinding" name="SBEndpoint" contract="Seroter.ServiceBusLoadBalanceDemo.IHelloService" />
      </service>
    </services>
    <extensions>
      <!-- Adding all known service bus extensions. You can remove the ones you don't need. -->
      <behaviorExtensions>
        <add name="connectionStatusBehavior" type="Microsoft.ServiceBus.Configuration.ConnectionStatusElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
        <add name="transportClientEndpointBehavior" type="Microsoft.ServiceBus.Configuration.TransportClientEndpointBehaviorElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
        <add name="serviceRegistrySettings" type="Microsoft.ServiceBus.Configuration.ServiceRegistrySettingsElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      </behaviorExtensions>
      <bindingElementExtensions>
        <add name="netMessagingTransport" type="Microsoft.ServiceBus.Messaging.Configuration.NetMessagingTransportExtensionElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
        <add name="tcpRelayTransport" type="Microsoft.ServiceBus.Configuration.TcpRelayTransportElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
        <add name="httpRelayTransport" type="Microsoft.ServiceBus.Configuration.HttpRelayTransportElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
        <add name="httpsRelayTransport" type="Microsoft.ServiceBus.Configuration.HttpsRelayTransportElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
        <add name="onewayRelayTransport" type="Microsoft.ServiceBus.Configuration.RelayedOnewayTransportElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      </bindingElementExtensions>
      <bindingExtensions>
        <add name="basicHttpRelayBinding" type="Microsoft.ServiceBus.Configuration.BasicHttpRelayBindingCollectionElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
        <add name="webHttpRelayBinding" type="Microsoft.ServiceBus.Configuration.WebHttpRelayBindingCollectionElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
        <add name="ws2007HttpRelayBinding" type="Microsoft.ServiceBus.Configuration.WS2007HttpRelayBindingCollectionElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
        <add name="netTcpRelayBinding" type="Microsoft.ServiceBus.Configuration.NetTcpRelayBindingCollectionElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
        <add name="netOnewayRelayBinding" type="Microsoft.ServiceBus.Configuration.NetOnewayRelayBindingCollectionElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
        <add name="netEventRelayBinding" type="Microsoft.ServiceBus.Configuration.NetEventRelayBindingCollectionElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
        <add name="netMessagingBinding" type="Microsoft.ServiceBus.Messaging.Configuration.NetMessagingBindingCollectionElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      </bindingExtensions>
    </extensions>
  </system.serviceModel>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>

A few things to note there.  I’m using the legacy access control strategy for the TransportClientEndpointBehavior.  But the biggest thing to notice is that there is nothing in this configuration that deals with load balancing.  Solutions built with the 1.5 SDK should automatically get this capability.

I went and started up a single instance and called my RESTful service from a browser instance.

2011.10.27sb01

I then started up ANOTHER instance of the same service, and it appears connected as well.

2011.10.27sb02

When I invoke my service, ONE of the available listeners will get it (not both).

2011.10.27sb03

Very cool. Automatic load balancing. You do pay per connection, so you don’t want to set up a ton of these.  But, this goes a long way to make the AppFabric Service Bus a truly reliable, internet-scale messaging tool.  Note that this capability hasn’t been rolled out everywhere yet (as of 10/27/2011 9AM), so you may not yet have this working for your service.

Author: Richard Seroter

Richard Seroter is Director of Developer Relations and Outbound Product Management at Google Cloud. He’s also an instructor at Pluralsight, a frequent public speaker, the author of multiple books on software design and development, and a former InfoQ.com editor plus former 12-time Microsoft MVP for cloud. As Director of Developer Relations and Outbound Product Management, Richard leads an organization of Google Cloud developer advocates, engineers, platform builders, and outbound product managers that help customers find success in their cloud journey. Richard maintains a regularly updated blog on topics of architecture and solution design and can be found on Twitter as @rseroter.

7 thoughts

  1. The world of Azure technology (ie you) spins fast when you have to put in a disclamer in a blog post stating that it might not have been rolled out just yet.
    As of this morning we have it in Europe as well.

    It is a nice feature and you demonstrate it really well and simple. Thanks.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.