Cet article a fait l'objet d'une traduction automatique.
Au cœur de Windows Azure
Bus des services Windows Azure : modèles de messagerie utilisant des sessions
Bruno Terkaly
Ricardo Villalobos
Télécharger l'exemple de code
Dans l'un de nos articles précédents, nous avons discuté de l'importance de l'utilisation de modèles de messagerie dans le nuage afin de découpler les solutions et promouvoir des architectures logicielles à l'échelle.(Voir « Comparant Windows Azure files d'attente et Service Bus Queues » à msdn.microsoft.com/magazine/jj159884.) Queuing est l'un de ces modèles de messagerie, et la plateforme Windows Azure offre deux options principales pour mettre en œuvre cette approche : Services de stockage des files d'attente et les files d'attente Bus de Service, qui couvrent des scénarios où plusieurs consommateurs en compétition pour recevoir et traiter chacun des messages dans une file d'attente.C'est le modèle canonique pour soutenir des charges de travail variables dans le nuage, où récepteurs peuvent être dynamiquement ajoutés ou supprimés selon la taille de la file d'attente, en offrant un mécanisme de basculement et d'équilibrage de charge pour le back-end (voir Figure 1).
Figure 1 modèle files d'attente de messagerie : Chaque Message est consommé par un seul récepteur
Même si le modèle de messagerie de files d'attente est une excellente solution pour le découplage simple, il y a des situations où chaque récepteur nécessite sa propre copie du message, avec l'option de rejeter certains messages basés sur des règles spécifiques.Un bon exemple de ce type de scénario est indiqué dans Figure 2, qui illustre un défi commun que détail entreprises visage lors de l'envoi des informations à plusieurs branches, par exemple le dernier catalogue de produits ou une liste de prix mis à jour.
Éditeur/abonné figure 2 modèle de messagerie : Chaque Message peut être consommé plus d'une fois
Dans ce cas, le modèle de l'éditeur/abonné est un meilleur ajustement, où les récepteurs expriment simplement un intérêt dans une ou plusieurs catégories de messages, se connectant à un abonnement indépendant qui contient une copie du flux de message.Le Bus de Service Windows Azure implémente le modèle de messagerie éditeur/abonné par le biais de thèmes et d'abonnements, qui améliore grandement la capacité de contrôler la façon dont les messages sont distribués, basée sur les filtres et règles indépendantes.Dans cet article, nous allons vous expliquer comment appliquer ces capacités de Bus de Service Windows Azure à l'aide d'un scénario simple de la vie réelle, en supposant que les conditions suivantes :
- Produits doivent être reçues dans l'ordre basé sur la page du catalogue.
- Certains des magasins ne portent pas de catégories particulières de catalogue et produits dans ces catégories doivent être filtrées pour chaque magasin.
- Nouvelle information de catalogue ne doit pas être appliquée au système magasin jusqu'à ce que tous les messages sont arrivés.
Tous les exemples de code pour cet article ont été créés avec Visual Studio 2012, à l'aide de c# comme langage de programmation.Vous devez également Windows Azure SDK version 1.8 pour les développeurs .NET et l'accès à un abonnement Windows Azure.
Mise en place du plan de messagerie pour le projet
Avant d'écrire de code, vous devez définir les différentes entités (les sujets et les abonnements) qui feront partie du flux de travail messagerie.Cela est possible en consultant le portail Windows Azure à manage.windowsazure.com.Connectez-vous avec vos informations d'identification et procédez comme suit :
- Cliquez sur l'icône créer nouveau en bas à gauche du portail de gestion.
- Cliquez sur l'icône de l'application SERVICES, puis sur la rubrique BUS SERVICE et enfin sur créer personnalisé (voir Figure 3).
- Sur le premier écran de la boîte de dialogue, entrez le nom de la rubrique, puis sélectionnez l'approprié région et Windows Azure ID d'abonnement.Si il s'agit de votre premier espace de noms dans la zone sélectionnée, l'assistant proposera une file d'attente de l'espace de noms : [nom de votre entité]-ns.Vous pouvez modifier cette valeur.
- Cliquez sur la marque suivante (flèche vers la droite) pour insérer les propriétés restantes.Vous pouvez conserver les valeurs par défaut.Cliquez sur la coche en regard de créer le sujet.
- Cliquez sur l'icône Service Bus sur la barre de navigation de gauche pour obtenir une liste des espaces de noms.Notez que vous ne pourriez pas voir l'espace de noms énuméré immédiatement.Quelques secondes suffisent pour créer l'espace de noms et de mettre à jour l'interface du portail.
- Sélectionnez le sujet auquel vous venez de créer dans la liste et cliquez sur la touche d'accès rapide, qui se trouve au bas de l'écran.Enregistrer la chaîne de connexion complète pour une utilisation ultérieure.
- En haut de l'écran du portail Windows Azure, cliquez sur abonnements, puis sur créer un nouvel abonnement.Dans la boîte de dialogue du menu contextuel, entrez un nom (dans notre exemple, nous avons utilisé la « Store1Sub ») et ensuite cliquez sur la flèche pour continuer.
- Dans l'écran suivant, conservez les valeurs par défaut, mais assurez-vous de vérifier l'option d'activation sessions.Cliquez sur la coche en regard de créer l'abonnement.Séances serviront par les abonnés pour récupérer des messages dans un ordre séquentiel.
- Répétez les étapes 7 et 8 pour chacun des trois magasins.
Figure 3 création d'un nouveau sujet de Bus de Service à l'aide de la Windows Azure Portal
Une fois les sujets et les abonnements ont été créés, vous pouvez également accéder directement dans Visual Studio.Pour ce faire, ouvrez l'Explorateur de serveurs (vue | Explorateur de serveurs) et développez le nœud de Bus de Service Windows Azure (voir Figure 4).Faites un clic droit sur le nœud de Bus de Service Windows Azure et sélectionnez Ajouter une nouvelle connexion.Entrez le nom du Namespace, nom de l'émetteur (généralement "propriétaire") et clé d'accès de l'émetteur que vous avez enregistrées lors de la création de l'espace de noms Windows Azure dans le portail.
Figure 4 création d'une rubrique de Bus de Service et les abonnements à l'aide de Visual Studio Tools
N'oubliez pas qu'il est possible de créer et de gérer ces entités à l'aide de classes dans l'espace de noms Microsoft.ServiceBus.Messaging, TopicClient et SubscriptionClient, qui sont utilisés ultérieurement dans cet article par programme.
Une fois que la structure de base pour le flux de messagerie a été créée, nous allons simuler le trafic à l'aide de deux applications console créées dans Visual Studio, comme indiqué dans Figure 5.La première application de console, MSDNSender, enverra le catalogue de produits.Le second, MSDNrécepteur, recevront l'information dans chacun des magasins.Nous allons analyser le code dans les sections suivantes.Dans le modèle de publication/abonnement, le MSDNSender est l'éditeur et le MSDNReceiver est l'abonné.
Figure 5 Visual Studio Solution pour simuler le scénario de catalogue de produits
Envoyer le catalogue de produits de l'administration centrale
Comme vous pouvez le voir dans Figure 2, siège social (l'éditeur) envoie des messages à un sujet.Cette logique est représentée par le code dans le fichier principal, Program.cs, une partie du projet MSDNSender.Program.cs encapsule la logique et le code pour envoyer une liste de produits sous forme de messages individuels au sujet.Regardons les différentes sections, en commençant par la méthode Main.Notez que tout d'abord, nous créons un client pour le sujet, comme suit :
// Create a topicClient using the
// Service Bus credentials
TopicClient topicClient =
TopicClient.CreateFromConnectionString(
serviceBusConnectionString, topicName);
Lorsqu'un topicClient est créé, l'éditeur peut envoyer des messages à l'aide de ce. La liste des produits doit être envoyé est stockée dans un fichier XML appelé ProductsCatalog.xml, qui contient une liste de 10 entités du produit qui sera transformé en un tableau d'objets. Les produits seront ensuite sont mappées aux classes catalogue et produits stockés dans le fichier Product.cs :
// Deserialize XML file with Products, and store them in an object array
Catalog catalog = null;
string path = "ProductsCatalog.xml";
XmlSerializer serializer = new XmlSerializer(typeof(Catalog));
StreamReader reader = new StreamReader(path);
catalog = (Catalog) serializer.Deserialize(reader);
reader.Close();
Tous les produits de la gamme catalogue présente la structure illustrée dans Figure 6.
Figure 6 représentation de classe pour les produits du catalogue
public class Product
{
[System.Xml.Serialization.XmlElement("ProductId")]
public string ProductId { get; set; }
[System.Xml.Serialization.XmlElement("ProductName")]
public string ProductName { get; set; }
[System.Xml.Serialization.XmlElement("Category")]
public string Category { get; set; }
[System.Xml.Serialization.XmlElement("CatalogPage")]
public int CatalogPage { get; set; }
[System.Xml.Serialization.XmlElement("MSRP")]
public double MSRP { get; set; }
[System.Xml.Serialization.XmlElement("Store")]
public string Store { get; set; }
}
À l'intérieur de la boucle de tableau, un appel à la méthode CreateMessage extraits des différentes propriétés des objets produit et les affecte au message à envoyer. Deux propriétés requièrent une attention particulière :
if (isLastProductInArray)
message.Properties.Add("IsLastMessageInSession", "true");
message.SessionId = catalogName;
Séances sont extrêmement importants car ils permettent au récepteur de déterminer si tous les messages qui appartiennent à un groupe spécifique et logique sont arrivés. Dans ce cas, en définissant la propriété de message de SessionId, nous spécifions que le récepteur ne doit pas utiliser les informations de catalogue jusqu'après que tous les messages ayant la même valeur de nom de catalogue sont arrivés. En outre, pour le dernier produit dans le tableau, nous allons ajouter une nouvelle propriété : IsLastMessageInSession, ce qui permettra des récepteurs déterminer si le dernier message de la session est arrivé, et le catalogue peuvent être entièrement traités. Figure 7 montre MSDNSender en cours d'exécution.
Figure 7 l'exécution du projet MSDNSender
Recevoir le catalogue de produits à l'aide d'abonnements dans les magasins
Maintenant que le catalogue et les produits ont été envoyés pour le sujet et copiés sur les différents abonnements, portons notre attention sur le projet de MSDNReceiver, où les messages sont reçus et traités. Notez que dans la méthode Main de Program.cs, le code crée un client pour l'abonnement basé sur les informations fournies par l'utilisateur via un Console.Readligne de commande. Les utilisateurs doivent entrer leur numéro de magasin, qui reflète les messages qu'ils souhaitent recevoir. En bref, chaque magasin de branche ne porte que sur les messages qui s'appliquent à ce magasin :
Console.WriteLine("Enter Store Number");
string storeNumber = Console.ReadLine();
Console.WriteLine("Selecting Subscription for Store...");
// Create a Subscription Client to the Topic
SubscriptionClient subscriptionClient =
SubscriptionClient.CreateFromConnectionString(
serviceBusConnectionString, topicName,
"Store" + storeNumber.Trim() + "Sub",
ReceiveMode.PeekLock);
Parce que nous recevons des messages depuis les abonnements basés sur des sessions (comme expliqué dans la section précédente), il faut demander à celle qui suit à l'aide de la ligne de code suivante :
MessageSession sessionReceiver =
subscriptionClient.AcceptMessageSession(TimeSpan.FromSeconds(5));
Fondamentalement, cela signifie que le client vérifie tous les messages à être traitées dans l'abonnement — ceux dont la propriété SessionId n'est pas nulle, et si aucun de ces messages ne sont rencontrées dans un délai de cinq secondes, la demande sera temps out, mettant fin à l'application du récepteur. En revanche, si une session est trouvée, la méthode ReceivingSessionMessages sera appelée. Avant de nous lancer dans ce morceau de code, nous allons discuter de la notion d'état de session, ce qui permet au développeur de stocker des informations qui peuvent être utilisées alors que les messages qui appartiennent à la même transaction sont reçus. Dans ce cas, nous utilisons de l'état de session à « se souvenir » à la dernière page du catalogue qui a été reçue, ainsi que les messages — produits — qui sont arrivés dans le désordre.
Sur cette base, Voici le flux de travail dans le code :
- Le message en cours est reçu dans la ReceiveSessionMessages de méthode (voir Figure 8), qui s'appuie sur la méthode ProcessMessage (Figure 9) pour le traiter.
- À l'intérieur de la méthode ProcessMessage, si le message est hors séquence, il est automatiquement reporté et son ID stockées dans l'état de session. Dans le cas contraire, il a marqué comme « complet » et supprimé de l'abonnement. La prochaine devrait également, séquence — Page catalogue — sont stockées dans la session.
- Après le traitement du message reçu actuel, le code suivant dans ReceiveSessionMessages vérifie différée message ID lors de la session et tente de les traiter à nouveau fondé sur la dernière page du catalogue.
- Une fois que tous les messages ont été reçus pour la session, le récepteur est fermé.
Figure 8 la méthode ReceivedSessionMessages dans le Code
static void ReceiveSessionMessages(MessageSession receiver)
{
// Read messages from subscription until subscription is empty
Console.WriteLine("Reading messages from subscription {0}",
receiver.Path);
Console.WriteLine("Receiver Type:" + receiver.GetType().Name);
Console.WriteLine("Receiver.SessionId = " + receiver.SessionId);
SequenceState sessionState = GetState(receiver);
BrokeredMessage receivedMessage;
while ((receivedMessage = receiver.Receive()) != null)
{
string sessionId = receiver.SessionId;
ProcessMessage(receivedMessage, ref sessionState, receiver);
while (sessionState.GetNextOutOfSequenceMessage() != -1)
{
// Call back deferred messages
Console.WriteLine("Calling back for deferred message: Category {0},
Message sequence {1}", receiver.SessionId,
sessionState.GetNextSequenceId());
receivedMessage = receiver.Receive(
sessionState.GetNextOutOfSequenceMessage());
ProcessMessage(receivedMessage, ref sessionState, receiver);
}
if (receivedMessage.Properties.ContainsKey(
"IsLastMessageInSession"))
break;
}
SetState(receiver, null);
receiver.Close();
}
Figure 9 la méthode ProcessMessage dans le Code
static void ProcessMessage(BrokeredMessage message, ref SequenceState sessionState,
MessageSession session = null)
{
if (session != null)
{
int messageId = Convert.ToInt32(message.Properties["CatalogPage"]);
if (sessionState.GetNextSequenceId() == messageId)
{
OutputMessageInfo("RECV: ", message, "State: " + "RECEIVED");
sessionState.SetNextSequenceId(messageId + 1);
message.Complete();
SetState(session, sessionState);
}
else
{
Console.WriteLine("Deferring message: Category {0}, Catalog Page {1}",
session.SessionId, messageId);
sessionState.AddOutOfSequenceMessage(messageId,
message.SequenceNumber);
message.Defer();
SetState(session, sessionState);
}
}
Thread.Sleep(receiverDelay);
}
N'oubliez pas que pour ce projet, les ID de message différé sont stockés dans l'état de session et de potentiellement perdre. Dans un environnement de production, nous recommandons d'utiliser un type de stockage persistant (Windows Azure Tables est une option) à cet effet. Notez que si le message contient la propriété IsLastMessageSessionInSession (la valeur au cours du processus d'envoi), la boucle de la session est terminée. La console de sortie pour le projet MSDNReceiver se retrouvent dans Figure 10.
Figure 10 l'exécution du projet MSDNReceiver
Abonnements de Bus de Service Windows Azure vous donnent la possibilité de créer des règles spécifiques qui filtrent les messages avant qu'ils sont consommés. Dans ce cas, il serait relativement facile de créer une règle qui isole les produits par catégorie ou par nombre de magasin (dont nous avons ignorés dans ce projet). Règles peuvent être créées par programme, directement dans le portail Windows Azure ou grâce à des outils de Visual Studio.
Synthèse
Le Bus de Service Windows Azure offre une implémentation étonnamment robuste et flexible de la modèle de publication/abonnement. Différents scénarios peuvent être adressées par l'utilisation de thèmes et d'abonnements. La capacité de prendre en charge plusieurs expéditeurs, diffuser des messages à plusieurs récepteurs, ainsis que la capacité à logiquement grouper et trier les messages, ouvre un monde de possibilités pour le développeur modern. En outre, être en mesure de tirer parti d'une session permanente pour suivre l'état simplifie logiquement regrouper les messages et contrôler leur séquence. Dans un monde où les environnements distribués sont la norme, comprendre comment utiliser les modèles de messagerie et les outils qui les entoure est crucial pour les architectes de logiciels aujourd'hui dans le nuage.
Bruno Terkaly est développeur pour Microsoft. Ses connaissances approfondies sont issues d'années d'expérience dans le domaine, au cours desquelles il a écrit du code à l'aide d'une multitude de plateformes, de langages, d'infrastructures, de SDK, de bibliothèques et d'API. Il se consacre à l'écriture de code, à l'écriture sur un blog et à des présentations sur la création d'applications sur le cloud, plus particulièrement à l'aide de la plateforme Windows Azure.
Ricardo Villalobos est un architecte logiciel aguerri qui bénéficie de plus de 15 ans d'expérience dans la conception et la création d'applications pour des entreprises exerçant dans le secteur de gestion de la chaîne d'approvisionnement. Titulaire de différentes certifications techniques, ainsi que d'une maîtrise d'administration des entreprises délivrée par l'Université de Dallas, il travaille comme architecte de cloud dans le groupe incubation Windows Azure CSV pour Microsoft.
Merci à l'expert technique suivant d'avoir relu cet article : Abhishek Lal