DarksideCookie

Come to the dark side...we have cookies!

Using the Windows Azure Service Bus - Message relaying

My last post was a bit light on the coding side I know. I also know that I promised to make up for that with a post with some actual code. And this is it! Actually, this is one of them. My plan is to walk through several of the features over the next few posts in the n00b kind of way.

That is, I am going to go through the basics for each of the features I deem interesting, making it easy to follow for people who are new to the Service Bus. And please don’t be offended by the “n00b” comment. We are all “n00bs” at some point in every thing we do.

Before we can build some cool service bus things, we need to make sure that we have everything we need on the machine, which basically means verifying that we have the Azure SDK installed. In this case, I am using the 1.5 release, that was released recently, but if they have released a new version, hopefully most of the code will port nicely.

If not, it is easy to do using the Web Platform Installer or by going here, which will launch the WPI automatically for you. It is possible to get just the SDK install by clicking here for 64-bit and here for the 32-bit.

Launching the WPI and searching for Azure will give you the following screen

image

At least at the time of writing.

Just select the Windows Azure AppFabric SDK V<whatever is the current>. As you can see, I am also installing the Azure tools for Visual Studio, but that shouldn’t not be required for this demo.

Now that we have the tools, we need to set up a Service bus namespace in Azure. This is not hard at all. Just browse to https://windows.azure.com/ and log in to your account.

If you don’t have an account, you will have to set one up. Currently I believe that there is a queue for trial accounts, but that might change. Otherwise, if you have an MSDN account, this will give you some Azure love as well. But yes, you do need to enter credit card details to cover any costs that you might incur. Generally this will not happen while just testing things. But make sure you stay in the defined limitations of your subscription type unless you have a few dollars to spend…

As you log in, you will see the Azure Management Portal (built in Silverlight of course). In the bottom left corner you will find a button for “Service Bus, Access Control & Caching”.

image

Click it! Then click the “New” button at the top, followed by the" “Service bus” link.

image

Fill out the window that pops up

image

And you are done. This should have given you a new Service bus namespace to play with.

I will return to the Azure Management Portal later, so keep the window open.

Next, we can start looking at getting some code up and going. In this case, I have created a solution with 3 projects, one for the server, one for the client and one for common stuff.

I prefer having my common things in a third project, instead of creating duplicates in the other projects. The client and server projects are Console projects, and the common project is a class library.

The first thing we need to do is to create a service contract, which is fairly easy. Just create a new interface in the common project that defines the features you need. In my case, that is a service that will tell me whether or not it is Friday, which would look something like this

public interface IIsItFridayService
{
bool IsItFriday();
}

However, we need to turn it into a WCF service contract by adding some attributes from the System.ServiceModel assembly. So let’s add a reference to that, and add the ServiceContractAttribute and OperationContractAttribute to the interface.

[ServiceContract(Name="IsItFridayService", Namespace="http://chris.59north.com/azure/relaydemo")]
public interface IIsItFridayService
{
[OperationContract]
bool IsItFriday();
}

Finally, we need to create a channel interface as well. This will be used later on. Luckily, it is a lot easier than it sounds. It is basically an interface that implements the service interface as well as the IChannel interface. Like this

public interface IIsItFridayServiceChannel : IIsItFridayService, IChannel { }

That’s it! Service contract finished!

Next we have to create the server, and the first thing we have to do is add a reference to the service bus assembly called Microsoft.ServiceBus. However, if you open the “Add Reference” dialog, you will probably realize that it isn’t there. That’s because the Console project for some reason is configured to use the “.NET Framework 4 Client Profile” instead of the full framework.

To solve this, just change the target framework to “.NET Framework 4”, and then you can add the reference. You will need to do the same thing to the client project as well.

image

Ok…with that out of the way, we can start looking at building the server.

When you create a WCF service, you will first of all need an address where the service is to be exposed. In the case of the service bus, this address is created using a static helper method on a class called ServiceBusEnvironment

This address can then be passed to a standard WCF ServiceHost together with the type of service to host.

Uri endpointAddress = ServiceBusEnvironment.CreateServiceUri("sb", GetNamespace(), "IsItFridayService");

var host = new ServiceHost(typeof(IsItFridayService), endpointAddress);

Note that the “sb” in there, is the scheme for the service bus…

The host however is just a regular Wcf service host and has no knowledge of the service bus. So to be able to work with the service bus, we need to add a service behavior called TransportClientEndpointBehavior. This behavior is responsible for authenticating towards the service bus using a token, which it gets from a TokenProvider. In this case, the TokenProvider will be one that uses the issuer name, and a secret to create the token. This provider is created by calling the TokenProvider.CreateSharedSecretTokenProvider method, passing in the issuer name and the secret.

There are a couple of other providers as well, but let’s ignore those for now!

The issuer name and secret is available through the Azure Management Portal. Just select the namespace you need it for in the list of service bus namespaces, and then click the little “View” button to the right

image

This will give you a window that shows you everything you need

image

As soon as we have the TOkenProvider and ServiceBehavior set up, we need to add it to the hosts endpoints.

var serviceBusEndpointBehavior = new TransportClientEndpointBehavior();
serviceBusEndpointBehavior.TokenProvider = TokenProvider.CreateSharedSecretTokenProvider(GetIssuerName(), GetSecret());
foreach (var endpoint in host.Description.Endpoints)
{
endpoint.Behaviors.Add(serviceBusEndpointBehavior);
}

That’s it, next we can call Open() on the host, and await connections!

host.Open();

Console.WriteLine("Service listening at: " + endpointAddress);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();

host.Close();

The client needs an address to connect to as well, and can use the same helper method as the server. It also needs a TransportClientEndpointBehavior to be able to communicate with the service, and once again, it can be created in the same way as on the server.

var serviceUri = ServiceBusEnvironment.CreateServiceUri("sb", GetNamespace(), "IsItFridayService");

var serviceBusEndpointBehavior = new TransportClientEndpointBehavior();
serviceBusEndpointBehavior.TokenProvider = TokenProvider.CreateSharedSecretTokenProvider(GetIssuerName(), GetSecret());

But that’s where the similarities end. The next step is to create a ChannelFactory<T> that is responsible for creating a “channel” to use when communicating with the service. This is where that extra “channel” interface comes into play. The factory will create an instance of a class that implements that interface.

This factory is also responsible for the behavior stuff, so we create it and add the TransportClientEndpointBehavior to the endpoint.

var channelFactory = new ChannelFactory<IIsItFridayServiceChannel>("RelayEndpoint", new EndpointAddress(serviceUri));
channelFactory.Endpoint.Behaviors.Add(serviceBusEndpointBehavior);

As soon as the factory is created, we can create a channel, open it, call the method we need to call, and finally close it.

var channel = channelFactory.CreateChannel();
channel.Open();

Console.WriteLine("It is" + (channel.IsItFriday() ? " " : "n't ") + "Friday");

channel.Close();

That’s it! More or less at least… If you have ever worked with Wcf, you have probably figured out that we are missing some configuration.

The configuration is however not very complicated. For the server, it looks like this

<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service name="DarksideCookie.Azure.ServiceBusDemo.RelayService.IsItFridayService">
<endpoint contract="DarksideCookie.Azure.ServiceBusDemo.RelayService.Common.IIsItFridayService" binding="netTcpRelayBinding" />
</service>
</services>
<extensions>
<bindingExtensions>
<add name="netTcpRelayBinding"
type="Microsoft.ServiceBus.Configuration.NetTcpRelayBindingCollectionElement, 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>

Nothing complicated there, except for that new binding type that requires us to register a binding extension.

That new binding is what is responsible for communicating with the service bus. This is what makes it possible for us to create a regular Wcf service, and have it communicate with the service bus.

The client config is very similar

<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<client>
<endpoint name="RelayEndpoint"
contract="DarksideCookie.Azure.ServiceBusDemo.RelayService.Common.IIsItFridayService"
binding="netTcpRelayBinding"/>
</client>
<extensions>
<bindingExtensions>
<add name="netTcpRelayBinding"
type="Microsoft.ServiceBus.Configuration.NetTcpRelayBindingCollectionElement, 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>

As you can see, it has the same binding stuff registered, as well as a single client endpoint.

Running the server and client will result in something like this

image

There is however one more thing I want to look at!

The service works fine, but it requires the client to know exactly where to find it, which might not be a problem. But it is possible for us to actually output some information about the available services.

This is done by “registering” the service in the so called “service registry” using a service behavior called ServiceRegistrySettings. This behavior will tell the service bus whether the service should be possible to find publicly, or not. By creating an instance, passing in DiscoveryType.Public to the constructor, and adding it to the hosts endpoints, we can enable this feature

var serviceRegistrySettings = new ServiceRegistrySettings(DiscoveryType.Public);
foreach (var endpoint in host.Description.Endpoints)
{
endpoint.Behaviors.Add(serviceRegistrySettings);
}

What does this mean? Well, it means that if we browse to the “Service Gateway” address (available in the Azure Management Portal), we get an Atom feed defining what services are available in the chosen namespace.

So in my case, browsing to http://darksidecookie.servicebus.windows.net, gives me a feed that looks like this

<feed xmlns="http://www.w3.org/2005/Atom">
<title type="text">Publicly Listed Services</title>
<subtitle type="text">This is the list of publicly-listed services currently available</subtitle>
<id>uuid:206607c9-4819-40ad-bfd6-cd730732cab0;id=31581</id>
<updated>2011-09-28T17:12:54Z</updated>
<generator>Microsoft® Windows Azure AppFabric - Service Bus</generator>
<entry>
<id>uuid:206607c9-4819-40ad-bfd6-cd730732cab0;id=31582</id>
<title type="text">isitfridayservice</title>
<updated>2011-09-28T17:12:54Z</updated>
<link rel="alternate" href="sb://darksidecookie.servicebus.windows.net/IsItFridayService/"/>
</entry>
</feed>

Without that extra behavior, this feed will not disclose any information about the services available in the namespace.

That’s all there is to it! At least if you are creating something as simple as this. But it is still kind of cool that it is this simple to create a service that can be hosted anywhere and be called from anywhere and having all messages relayed in the cloud for us automatically.

And the code is available as usual here: DarksideCookie.Azure.ServiceBusDemo

Posted: Sep 29 2011, 18:39 by ZeroKoll | Comments (0) |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: Azure | WCF
Manage post: :)

Pingbacks and trackbacks (1)+

Comments are closed