maandag 17 juni 2013

Onderzoek naar Windows Azure Service Bus (deel 3)

Windows Azure Service Bus is een mooie dienst waarmee services, die zich in besloten on-premise omgevingen bevinden, kunnen worden ontsloten zonder daarbij de firewall noemenswaardig te ondermijnen. Het idee is dat de buitenwereld de service bus aanspreekt en dat die op zijn beurt weer de on-premise dienst benadert. Er zijn op dit moment drie scenario's mogelijk (een vierde, de Notification Hub, is momenteel nog in de preview fase)
  1. Service Bus Relay
  2. Service Bus Queue
  3. Service Bus Topic/Subscriptions
De Service Bus Relay kun je gebruiken om de communicatie naar on-premise services mogelijk te maken zonder al te veel gedoe met de firewall. Deze techniek is en een eerdere blog al beschreven.
De Service Bus Queue is ideaal om diensten, die veel te verwerken krijgen, te ontlasten. Denk hierbij aan Load Leveling of Load Balancing. Dit scenario is in het tweede deel van deze blogreeks beschreven.
In dit deel gaan we kijken naar de Service Bus Topic/Subscriptions.

De Service Bus Topic/Subscriptions lijkt in veel opzichten op de Service Bus Queue. Clients, zoals mobiele applicaties, services en andere toepassingen, schieten berichten in een speciale queue; de Topic. Het grote verschil zit hem in het feit dat op de Topic niet direct wordt gelezen, zoals dat bij de queue wel het geval is, maar dat de berichten in zogenaamde virtuele queues, de Subscriptions, geplaatst worden. Iedere subscription ontvangt een kopie van het originele bericht.  Welk bericht in welke subscription wordt geplaatst, is weer afhankelijk van het filter dat is ingesteld op de subscription.
Kort samengevat, alle berichten verschijnen in een Topic en worden op basis van een filter naar de subscriptions gekopieerd die dan weer kunnen worden bekeken door applicaties die geïnteresseerd zijn in een subscription (afbeelding 1)


Afbeelding 1. Het principe van Topic/Subscriptions. Diverse applicaties sturen hun berichten naar de Topic die op zijn beurt kopieën, op basis van een filterdefinitie, naar de subscription stuurt. De betreffende subscriptions kunnen dan worden uitgelezen door belangstellende applicaties. Bron: Windows Azure
Hoewel je zo'n topic met bijbehorende subscriptions vanuit de Azure Portal kunt opzetten, is het in dit geval handiger om dat vanuit code te doen omdat je dan meteen filters kunt definiëren op de subscriptions. Iets dat vanuit de portal niet kan. Om de topics en subscriptions op te zetten, hebben we de access key van de owner nodig. Die heeft tenslotte manager rechten.
De code om de topic en subscriptions op te zetten ziet er als volgt uit:

private static void CreateTopicAndSubscriptions()
{
    string topicName = "input";
    TokenProvider tokenProvider = TokenProvider.CreateSharedSecretTokenProvider("owner""f4lCnMAkco8Yoc=");
    Uri svcUri = ServiceBusEnvironment.CreateServiceUri("sb""nspasit"string.Empty);
    NamespaceManager manager = new NamespaceManager(svcUri, tokenProvider);
    if (!manager.TopicExists(topicName))
    {
        manager.CreateTopic(topicName);
        SqlFilter f1 = new SqlFilter("EXISTS(complaint) OR EXISTS(sold)");
        manager.CreateSubscription(topicName, "sales", f1);
        SqlFilter f2 = new SqlFilter("EXISTS(sold)");
        manager.CreateSubscription(topicName, "warehouse", f2);
        SqlFilter f3 = new SqlFilter("EXISTS(complaint)");
        manager.CreateSubscription(topicName, "support", f3);
    }
}

Eerst wordt de NamespaceManager opgezet op basis van de tokenProvider en de url van de service bus. Vervlogens wordt een topic in elkaar gezet en drie subscriptions. Iedere subscription krijgt een filter mee die bepaalt welke berichten hij wil ontvangen en welke niet. In alle gevallen test ik op de aanwezigheid van een bepaalde eigenschap op het bericht ("sold" en "complaint"). Het resultaat van de uitvoering van deze code is in afbeelding 2 te zien.


Afbeelding 2. De topic "input" met de drie subscriptions "sales", "support" en "warehouse"
Vervolgens kunnen we berichten in de topic schieten. Dit gaat bijna hetzelfde als bij de queue.

static void Main(string[] args)
{
    TokenProvider tokenProvider = TokenProvider.CreateSharedSecretTokenProvider("writer""YpmQzUYtkTfszs=");
    Uri svcUri = ServiceBusEnvironment.CreateServiceUri("sb""nspasit"string.Empty);
    MessagingFactory mFactory = MessagingFactory.Create(svcUri, tokenProvider);
    TopicClient client = mFactory.CreateTopicClient("input");

    ProductData data = new ProductData { Brand = "ACME", Product = "Explosive Device", Price = 299.99M };
    BrokeredMessage message = new BrokeredMessage(data);
    message.Properties["complaint"] = "Exploded too early";
    client.Send(message);

    data = new ProductData { Brand = "Philips", Product = "Tooth Brush", Price = 99.99M };
    message = new BrokeredMessage(data);
    message.Properties["sold"] = 2;
    client.Send(message);

    Console.ReadLine();
}

Merk op dat er nu een TopicClient wordt aangemaakt. Daarnaast wordt aan ieder bericht een aantal eigenschappen (properties) toegekend die overeenkomen met één van de waarden uit de filterdefinities ("compaint" en "sold"). Wanneer we deze code uitvoeren zien we het resultaat terug in afbeelding 3.


Afbeelding 3. De twee berichten zijn in de subscription aangekomen. Merk op dat de sales subscription twee berichten bevat omdat die filterdefinitie beide eigenschappen in zich heeft.
Het uitlezen van de subscription gaat bijna hetzelfde als bij de queue. Alleen wordt er nu gebruik gemaakt van een SubscriptionClient.


class Program
{
    static void Main(string[] args)
    {
        TokenProvider tokenProvider = TokenProvider.CreateSharedSecretTokenProvider("reader""b/cSFuJUyv7dftB0=");
        Uri svcUri = ServiceBusEnvironment.CreateServiceUri("sb""nspasit"string.Empty);
        MessagingFactory mFactory = MessagingFactory.Create(svcUri, tokenProvider);
        SubscriptionClient client = mFactory.CreateSubscriptionClient("input""sales"ReceiveMode.PeekLock);
        BrokeredMessage msg = client.Receive();
        if (msg != null)
        {
            ProductData data = msg.GetBody<ProductData>();
            Console.WriteLine("{0} {1} {2}", data.Brand, data.Product, data.Price);
            msg.Complete();
        }

        Console.ReadLine();
    }
}

In dit codevoorbeeld wordt de "sales" subscription uitgelezen hetgeen na twee keer uitvoeren tot het resultaat in afbeelding 4 leidt.


Afbeelding 4. Wanneer de "sales" subscription twee keer is uitgelezen, staat de berichtenteller weer op 0.
In dit voorbeeld zie je dat Service Bus Topic/Subscriptions veel op de Service Bus Queue lijkt. Het grote verschil is, waar de Service Bus Queue 1 op 1 werkt, werkt de Service Bus Topic/Subscriptions 1 op n. Bij Service Bus Topic/Subscriptions heb je dezelfde voordelen als bij Service Bus Queue, zoals load leveling en load balancing. Bij Service Bus Queue zul je in het algemeen met één soort applicatie de queue uitlezen. Welke applicatie het bericht van de queue haalt is minder van belang omdat ze toch hetzelfde doen. Als je dit probeert met verschillende soorten applicaties, zal iedere applicatie zelf moeten bepalen of het bericht van de queue kan. Dit impliceert dan weer kennis van andere applicaties hetgeen niet wenselijk is. Hierin schuilt het grote voordeel van de Service Bus Topic/Subscriptions, ieder soort applicatie gebruikt zijn eigen queue met berichten die voor hem interessant zijn.

Geen opmerkingen:

Een reactie posten