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.
I then started up ANOTHER instance of the same service, and it appears connected as well.
When I invoke my service, ONE of the available listeners will get it (not both).
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.
Excellent post, Richard.
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.
I’ve updated my post, the update seems to be available on South Us and Europe West Region/Country.
Thanks for you help