maandag 10 juni 2013

Onderzoek naar Windows Azure Service Bus (deel 2)

Windows Azure Service Bus is een dienst in Windows Azure die het mogelijk maakt om on-premise services samen te laten werken met services in de cloud en applicaties buiten de cloud. Hierbij kun je denken aan klanten die jouw services willen integreren in hun applicatie, maar ook mobiele toepassingen. Windows Azure Service Bus geeft de mogelijk om toegang aan te bieden zonder dat de beveiliging van de on-premise omgeving noemenswaardig wordt aangetast.
Windows Azure Service Bus bestaat uit drie onderdelen:

  1. Service Bus Relay
  2. Queues
  3. Topics en Subscriptions
In de vorige blog hebben we stilgestaan bij de Service Bus Relay. In dit deel kijken we naar de Service Bus Queue.
Een queue is een wachtrij waarin je berichten plaatst. Wie het eerst in de wachtrij komt, wordt ook het eerst geholpen. Dit principe noemen we First In First Out (FIFO). Aan de ene kant heb je applicaties die berichten in de queue plaatsen. Dit kunnen desktop applicaties zijn of mobiele toepassingen, maar ook services. Aan de andere kant heb je één of meerdere applicaties draaien die de queue uitlezen (afbeelding 1). Het mooie van de queue is dat de berichten, als ze eenmaal in de queue staan, niet zomaar zullen verdwijnen (reliability). Dat is mooi want als de applicatie, die de queue uitleest, offline gaat, is het wel zo fijn dat de berichten bij terugkomst nog beschikbaar zijn (in het ergste geval kunnen de berichten in de "dead letter queue" belanden wanneer ze niet op tijd gelezen worden).


Afbeelding 1. Het principe van een queue. Diverse toepassingen schieten berichten in de queue (Message Senders) en aan de andere kant worden de berichten weer uitgelezen (Message Receiver). Bron: Windows Azure
Een queue zul je gaan gebruiken als er heel veel berichten op jouw server worden afgevuurd die de server niet meer kan verwerken (druk druk druk). In zulke situaties wordt de queue gebruikt om er berichten in op te slaan, zodat ze later alsnog kunnen worden verwerkt (load leveling), of de queue wordt door meerdere servers uitgelezen (load balancing).
Er was al een queue in Windows Azure aanwezig (bij Azure Storage), maar de Service Bus Queue biedt meer mogelijkheden. Op de Windows Azure site zijn de verschillen mooi in kaart gebracht.

We gaan nu bekijken hoe je de sevice Bus Queue opzet. Hierbij willen we dat de "Message Sender" berichten in de queue kan schieten, maar deze niet kan uitlezen. Daarnaast zal de "Message Receiver" de queue kunnen uitlezen, maar er geen berichten in kunnen zetten.
Allereerst zet je een namespace op in de Service Bus Queue (vanuit de Windows Azure Portal) en daarna kun je een queue aanmaken (zie afbeelding 2) waarbij je de naam van de queue opgeeft, de regio waarin hij komt te draaien en tenslotte de eerder aangemaakte service bus namespace.


Afbeelding 2. Het aanmaken van de queue
Vervolgens moeten we de rechten afregelen van de "Message Sender" en de "Message Receiver". Dit doe je via de ACS management portal. Om op de ACS management portal te komen, selecteer je eerst de zojuist aangemaakte queue en klik je op "ACCESS KEY" onderin beeld (afbeelding 3). Dit geeft het dialoogje in afbeelding 4 van waaruit je naar de ACS Management Portal gaat (afbeelding 5).


Afbeelding 3. Het verborgen knopje onderin beeld waarmee je  de key informatie te zijn krijgt, maar ook toegang krijgt tot de ACS Management Protal

Afbeelding 4. De toegang tot de ACS Management Portal. Listig verborgen.

Afbeelding 5. De ACS Management Portal.
Op de ACS Management Portal ga je naar de "Service Identities". Daarin zie je één identity staan; de owner. Dit is de administrator identity die alles mag op de queue. Natuurlijk kun je die gebruiken, maar dat is niet aan te bevelen. We gaan twee identities toevoegen via de "Add" knop in afbeelding 5. Het brengt ons naar het scherm in afbeelding 6 waarin we bij Name "reader" opgeven. Zorg er ook voor dat er een symmetrische key gegenereerd wordt. Die zul je nodig hebben om berichten uit de queue te lezen.


Afbeelding 6. Het aanmaken van een nieuwe service identity.
Maak op dezelfde manier ook een service identity aan voor "writer". Vervolgens ga je naar de "Rule groups" en selecteer je "Default Rule Group for ServiceBus" (afbeelding 7). Dit leidt je naar het scherm in afbeelding 8 waarin je een lijstje van de bestaande rules voor de service identity "owner" ziet staan. 

Afbeelding 7. De Rule Groups
Afbeelding 8. De bestaande Rule groups voor "owner". Van hieruit kun je nieuwe rules aanmaken.
Wanneer je op "Add" klikt, kun je nieuwe rules aanmaken voor de service identities die je zo-even hebt toegevoegd. In afbeelding 9 zie je hoe je de Rule definieert voor de service identity "reader".


Afbeelding 9. Het aanmaken ven een nieuwe rule.
Bij "Input claim issuer" selecteer je "Access Control Service". Bij "Input claim type" neem je de standaard waarde "name identifier" over en bij "Input claim value" geef je de service identity "reader" op. Bij "Output claim type" selecteer je "Enter type" en geef je de waarde "net.windows.servicebus.action" op. Bij "Output claim value" selecteer je "Enter value" met als waarde "Listen" (een gereserveerde actie van de Service Bus Queue die je het recht geef om berichten uit de queue te lezen. Je hebt ook nog "Send" om berichten in de queue te plaatsen en "Manage" die alles mag). Nadat je de rule hebt opgeslagen, doe je hetzelfde voor de "writer" met als veschil dat je bij "Input claim value" de waarde "writer" opgeeft en bij "Output claim value" de waarde "Send".

Nu we de rules gedefinieerd hebben, kunnen we aan het coderen gaan. Eerst zullen we een applicatie maken die berichten in de queue schiet. Dit wordt een gewone console applicatie die we verrijkt hebben met het "Windows Azure Service Bus" package vanuit NuGet (weer ervan uitgaand dat de Azure SDK al geïnstalleerd is). De code voor de "Message Sender" staat hieronder weergegeven.


class Program
{
    static void Main(string[] args)
    {
        TokenProvider tokenProvider = TokenProvider.CreateSharedSecretTokenProvider("writer""YpmQzUYtNdyQrAf0AdOrnlI");
        Uri svcUri = ServiceBusEnvironment.CreateServiceUri("sb""nspasit"string.Empty);
        MessagingFactory mFactory = MessagingFactory.Create(svcUri, tokenProvider);
        QueueClient client = mFactory.CreateQueueClient("test");

        Data data = new Data { FirstName = "Patrick", LastName = "Schmidt" };
        BrokeredMessage msg = new BrokeredMessage(data);
        msg.TimeToLive = TimeSpan.FromSeconds(30);
        client.Send(msg);

        Console.WriteLine("Message sent");
        Console.ReadLine();
    }
}

[DataContract]
public class Data
{
    [DataMember]
    public string FirstName { getset; }
    [DataMember]
    public string LastName { getset; }
}

Bij TokenProvider.CreateSharedSecretToken() geef je de service identity "writer" op en de bijbehorende key die je eerder hebt gegenereerd (afbeelding 6). de volgende stap is het aanmaken van de ServiceUri die de url naar de service bus construeert. Met de tokenProvider en de svcUri kun je een MessageFactory initialiseren van waaruit je de QueueClient genereert. Vervolgens maak je een BrokeredMessage object aan waarin je de te verzenden data stopt en tenslotte roep je op de QueueClient de Send() methode aan die het bericht op de queue plaatst. Wanneer alles goed verloopt, kun je het bericht zien in de queue op de Azure Portal (afbeelding 10)


Afbeelding 10. Het bericht is in de queue aangekomen.
Een bericht uit de Queue lezen gaat bijna op dezelfde manier. Hiervoor maken we weer een Console applicatie aan die we verrijken met de "Windows Azure Service Bus" package. Het uitlezen gaat dan zoals in de listing hieronder.

class Program
{
    static void Main(string[] args)
    {
        TokenProvider tokenProvider = TokenProvider.CreateSharedSecretTokenProvider("reader""b/cSFuJUyv7dftlA/3I");
        Uri svcUri = ServiceBusEnvironment.CreateServiceUri("sb""nspasit"string.Empty);
        MessagingFactory mFactory = MessagingFactory.Create(svcUri, tokenProvider);
        QueueClient client = mFactory.CreateQueueClient("test"ReceiveMode.PeekLock);

        BrokeredMessage msg = client.Receive();
        if (msg != null)
        {
            Data data = msg.GetBody<Data>();
            Console.WriteLine("{0} {1}", data.FirstName, data.LastName);
            msg.Complete();
        }

        Console.ReadLine();
    }
}

Bij de CreateSharedSecretToken() specificeer je nu de service identity "reader" en de bijbehorende key en vervolgens maak je weer de QueueClient aan. Let op dat ik als extra argument ReceiveMode.PeekLock opgeef. Deze optie is niet standaard (ReceiveAndDelete) en laat het bericht op de queue staan totdat ik zeg dat hij eraf kan via msg.Complete(). Op de QueueClient kun je nu via Receive() het bericht opvragen en, als die een geldige waarde heeft, via GetBody<Type>() het object terug halen.

Het werken met Windows Azure service Bus Queue is dus bijzonder eenvoudig. Met de nieuwste toevoeging AMQP (Advanced Message Queuing Protocol) kun je nu ook message-based applicaties bouwen die onafhankelijk zijn OS-platforms, leveranciers en talen.
Er kleven ook een paar nadelen aan Windows Azure Service Bus Queues. Zo worden transacties wel op queue-nivo ondersteund, maar niet gedistribueerd. Dwz dat een queue en bijvoorbeeld een database samen geen transactionele eenheid kunnen vormen.
Daarnaast moet je ook de kosten in de gaten houden. De kosten zijn per hoeveelheid berichten per maand. Op dit moment €75,- per 100.000.000 berichten per maand. Daarbij moet je ook opletten dat de berichten niet groter dan 64kb zijn, anders krijg je extra berichtkosten voor iedere 64kb die je overschrijdt. 

Geen opmerkingen:

Een reactie posten