El service Bus de Azure: Los temas

Muy buenas a todos,

Hace unos días, escribí un post en el que os contaba los primeros pasos para usar la funcionalidad más básica del Service Bus de Azure, las cosas FIFO.

Primeros pasos con el Service Bus de Azure: las colas

Hoy quiero profundizar más en el Service Bus y las opciones que nos permite, concretamente, quiero hablaros sobre una funcionalidad que me ha resultado interesantísima, los temas. Vamos a ver el esquema de esta funcionalidad antes de entrar en el detalle de la misma.

sb-topics-01

Esta funcionalidad, como podemos ver en la imagen, nos va a permitir crear un tema y asociado a éste distintas subscripciones. Los mensajes se enviarán al tema y las aplicaciones consumidoras leerán dichos mensajes de la subscripción a la que estén subscritos. Y ¿Cómo se copían los mensajes en las distintas subscripciones?, pues como veremos más adelante, se hace mediante filtros SQL a las distintas propiedades del mensaje, lo que nos permite trabajar de una forma muy sencilla y familiar. Os dejo algunos enlaces que os pueden ser de interés.

https://azure.microsoft.com/en-us/documentation/articles/fundamentals-service-bus-hybrid-solutions/

https://azure.microsoft.com/es-es/documentation/articles/service-bus-dotnet-how-to-use-topics-subscriptions/

Esta funcionalidad es muy útil por ejemplo en sistemas de gestión de incidencias, en donde podemos clasificar las incidencias en función de la importancia de las mismas, y consumirlas por distintos clientes en función de esto. A continuación os voy a enseñar en un ejemplo cómo se pueden usar los temas del Service Bus de Azure.

Creando el servicio en Azure

Lo primero que tenemos que hacer es entrar en el portal de administración de Azure para crear un nuevo Service Bus.

Captura de pantalla 2015-07-01 a las 20.01.02

Una vez ahí, en el apartado de Service Bus, hacemos click en crear y completamos el formulario

Captura de pantalla 2015-07-01 a las 20.01.19

Seleccionamos el centro de datos que queremos y en el caso de querer usar los temas, tenemos que indicar el modo standard en lugar del modo basic.

Esta es la pantalla de opciones de un service bus una vez creado.

Captura de pantalla 2015-07-01 a las 20.07.44

Cómo usarlo desde nuestra aplicación

Vamos a crear una nueva solución con un proyecto de tipo aplicación de consola en Visual Studio 2013. Para poder usar el Service Bus, tendremos en primer lugar, que añadir desde Nuget el paquete Microsoft Azure Service Bus.

Tras este tendremos que añadir la cadena de conexión al app.config de la aplicación de consola. La cadena de conexión la podemos obtener en el portal de azure. Una vez dentro del Service Bus creado, en la parte inferior de la pantalla, hacemos click en Información de conexión. (Como podemos ver en la imagen inmediatamente anterior).

De ahí copiamos la cadena de conexión y la añadimos en la el app.config de la siguiente forma:

<appSettings>
        <!-- Service Bus specific app setings for messaging connections -->
        <add key="Microsoft.ServiceBus.ConnectionString" value="[connectionstringhere]"/>
    </appSettings>

El productor de mensajes

Vamos a empezar por ver el código del productor de mensajes.

class Program
    {
        static void Main(string[] args)
        {
            bool exit = false;
            int i = 1;

            do
            {
                switch (menu())
                {
                    case 1:

                        TopicHelper.CreateTopic("TestTopic");
                        break;
                    case 2:

                        Console.Write("Write name to this subscription: ");
                        string subscriptionName = Console.ReadLine();

                        Console.Write("Write filter: ");
                        string sqlFilter = Console.ReadLine();

                        SqlFilter filter = new SqlFilter(sqlFilter);

                        TopicHelper.CreateSubscription("TestTopic",subscriptionName,filter);
                        
                        break;

                    case 3:

                        Console.Write("Set message priority: ");
                        string priority = Console.ReadLine();

                        BrokeredMessage message = new BrokeredMessage("Example Service Bus Message");
                        message.Properties["Counter"] = i;
                        message.Properties["Priority"] = priority;

                        i += 1;

                        TopicHelper.SendMessage("TestTopic", message);
                        break;
                    default:
                        exit = true;
                        break;
                }
            }
            while (!exit);
        }

        static int menu()
        {
            Console.WriteLine("--- Option Menu ---");
            Console.WriteLine("0.- Exit");
            Console.WriteLine("1.- Create Topic");
            Console.WriteLine("2.- Create Subscription");
            Console.WriteLine("3.- Send Message");
            Console.Write("-->");

            int value = int.Parse(Console.ReadLine());

            return value;
        }
    }

En este caso, el productor nos ofrece un menú con 3 opciones: Crear el tema, crear una subscripción y enviar un mensaje.

    • La creación del tema es muy similar a las colas. Las diferencias comienzan a la hora de crear subscripciones.
    • En este caso, en primer lugar indicamos el nombre de la subscripción y a continuación el filtro que queremos aplicar para la misma. Las subscripciones, como ya se comentó anteriormente, utilizan filtros sql sobre las propiedades de los mensajes para copiar los mensajes que se envían al tema. Algunos ejemplos de estos filtros SQL podrían ser de la siguiente forma:
Priority = 'medium'
Priority = 'high'
Counter >= 3
  • El envío de mensajes, al igual que la creación de los temas, es muy similar a lo visto en el post anterior

En el caso del ejemplo que se ha realizado he creado dos subscripciones, una donde se copiarán los mensajes que lleven el valor de su propiedad Priority a ‘medium’ y otra para cuando tenga el valor ‘high’. Antes de ver el código de los helpers que hacen la conexión del Service Bus, vamos a ver la secuencia de acciones que hemos lanzado en el ejemplo para configurar el tema.

creation

Como se ha podido observar, para la comunicación con el Service Bus se usa una clase TopicHelper, que tiene los siguientes métodos interesantes:

public class TopicHelper
    {
        public static void CreateTopic(string topicName)
        {
            string connectionString =
                CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString");

            var namespaceManager =
                NamespaceManager.CreateFromConnectionString(connectionString);

            if (!namespaceManager.TopicExists(topicName))
            {
                namespaceManager.CreateTopic(topicName);
            }
        }

        public static void SendMessage(string topicName, BrokeredMessage message)
        {
            string connectionString =
                CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString");

            TopicClient Client =
                TopicClient.CreateFromConnectionString(connectionString, topicName);

            Client.Send(message);
        }

        public static void CreateSubscription(string topicName, string subscriptionName, SqlFilter filter)
        {
            string connectionString =
                CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString");

            var namespaceManager =
                NamespaceManager.CreateFromConnectionString(connectionString);

            if (!namespaceManager.SubscriptionExists(topicName, subscriptionName))
            {
                namespaceManager.CreateSubscription(topicName, subscriptionName, filter);
            }
        }
    }

Vamos a destacar aquí, por la novedad con respecto a la entrada en la que hablaba del uso de las colas, el método CreateSubscription. Este es el método que se usa para añadir una subscripción a un tema. Este método, además del nombre del tema, recibe el nombre de la subscrición y un parámetro de tipo SqlFilter, donde vamos a definir el filtro que usará esa subscripción para recibir los mensajes del tema.

El método básicamente, comprueba si existe una subscripción creada con ese nombre en el tema y en caso negativo la crea.

El consumidor de los mensajes

El código del consumidor de mensajes, es el que vemos a continuación.

class Program
    {
        private static string topicName = "TestTopic";
        private static string mediumSubscription = "Medium";
        private static string highSubscription = "High";

        public static void ThreadProcSubscriptionMedium()
        {
            Console.WriteLine("Entering to Medium Subscription Consumer");

            while(true)
            {
                BrokeredMessage message = TopicHelper.ReceiveMessage(topicName, mediumSubscription);

                Console.WriteLine("Read From Medium Priority Subscription");
                Console.WriteLine("Body: " + message.GetBody<string>());
                Console.WriteLine("MessageID: " + message.MessageId);
                Console.WriteLine("Test Property: " +
                message.Properties["Counter"]);
            }
        }

        public static void ThreadProcSubscriptionHigh()
        {
            Console.WriteLine("Entering to High Subscription Consumer");

            while(true)
            {
                BrokeredMessage message = TopicHelper.ReceiveMessage(topicName, highSubscription);

                Console.WriteLine("Read From Medium Priority Subscription");
                Console.WriteLine("Body: " + message.GetBody<string>());
                Console.WriteLine("MessageID: " + message.MessageId);
                Console.WriteLine("Test Property: " +
                message.Properties["Counter"]);
            }
        }

        static void Main(string[] args)
        {
            Thread thread1 = new Thread(new ThreadStart(ThreadProcSubscriptionMedium));
            Thread thread2 = new Thread(new ThreadStart(ThreadProcSubscriptionHigh));

            thread1.Start();
            thread2.Start();

            thread1.Join();
            thread2.Join();
        }
    }

Este código, crea dos hilos de ejecución, para poder leer simultáneamente de las dos subscripciones que hemos creado desde el productor, cuando recibe un mensaje de una subscripción u otra, lo imprime en pantalla indicando de la subscripción que lo ha hecho. Para la recepción de mensajes se utiliza la siguiente función de nuestra clase TopicHelper.

public static BrokeredMessage ReceiveMessage(string topicName, string nameSubscription)
        {
            string connectionString =
                CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString");

            SubscriptionClient Client =
                SubscriptionClient.CreateFromConnectionString
                        (connectionString, topicName, nameSubscription);

            BrokeredMessage message = null;

            try
            {
                message = Client.Receive();
                message.Complete();
            }
            catch(Exception ex)
            {
                message.Abandon();
            }

            return message;

        }

Esta función se conecta con el tema del Service Bus y una subscripción indicadas como parámetro. Cuando recibe el mensaje y lo hace correctamente, usa el método Complete() para eliminar el mensaje de la subscripción. En caso de error, usar el método Abandon() para devolverlo a la subscripción.

Cómo funciona el ejemplo

Vamos a ver una captura en la que se ve como funciona de forma simultánea el ejemplo cuando se ejecutan, tanto el productor como el consumidor.

topicIII

Y esto es todo por hoy, espero que os haya resultado interesante y que os sirva para comprender mejor todas las oportunidades que nos ofrece el Service Bus. En la próxima entrada veremos como combinar este con SharePoint Online en un ejemplo.

Un saludo a todos.

Anuncios

Primeros Pasos con el Service Bus de Azure: Las colas

Muy buenas a todos,

Después de unas semanas sin poder publicar porque he estado ocupado preparando un examen de inglés, vuelvo con una entrada de la que llevaba tiempo detrás. Dentro de mis objetivos del año, además de profundizar en cómo usar las APIs de SharePoint y de Office 365 (de lo que ya he publicado bastantes entradas en el blog), está el empezar a aprender de Azure. Recientemente os expliqué cómo hacer tareas programadas con Azure por medio de los webjobs, aplicados en el caso del post a SharePoint.

Timer Jobs para SharePoint OnLine

Hoy os quiero hablar de otro de los servicios que nos ofrece Azure y que cuando he indagado sobre él, me ha resultado muy interesante, el Service Bus. Este servicio nos proporciona métodos para comunicar nuestras aplicaciones. Estos métodos pueden ser muy diversos, desde una simple cola FIFO, sistema de colas basado en subscripciones o situaciones en las que no se necesitan colas, solo un mecanismo para comunicarse. Todos estos escenarios los proporcionar el Service Bus de Azure. Os dejo algunos enlaces para que indaguéis y leáis más sobre este servicio que tenemos disponible.

https://azure.microsoft.com/en-us/documentation/articles/fundamentals-service-bus-hybrid-solutions/

https://azure.microsoft.com/en-us/documentation/articles/service-bus-dotnet-how-to-use-queues/

En este post, vamos a centrarnos fundamentalmente en las colas FIFO, en las que un productor va a ir colocando mensajes y un consumidor los irá leyendo por estricto orden de llegada.

Untitled

Vamos a ver un ejemplo en el que podremos comprobar como funcionan las colas en Azure Service Bus. El ejemplo constará de dos aplicaciones de consola, una que actuará como productor y otra como consumidor. Vamos a ver también los pasos para poner en marcha este servicio en Azure y cómo usarlo desde nuestras aplicaciones.

Creando el servicio en Azure

Lo primero que tenemos que hacer es entrar en el portal de administración de Azure para crear un nuevo Service Bus.

Captura de pantalla 2015-07-01 a las 20.01.02

Una vez ahí, en el apartado de Service Bus, hacemos click en crear y completamos el formulario

Captura de pantalla 2015-07-01 a las 20.01.19

Seleccionamos el centro de datos que queremos y en nuestro caso, como solo vamos a usar en este ejemplo una cola FIFO, seleccionamos la opción mensajería de tipo Basic.

Esta es la pantalla de opciones de un service bus una vez creado.

Captura de pantalla 2015-07-01 a las 20.07.44

Cómo usarlo desde nuestra aplicación

Vamos a crear una nueva solución con un proyecto de tipo aplicación de consola en Visual Studio 2013. Para poder usar el Service Bus, tendremos en primer lugar, que añadir desde Nuget el paquete Microsoft Azure Service Bus.

Tras este tendremos que añadir la cadena de conexión al app.config de la aplicación de consola. La cadena de conexión la podemos obtener en el portal de azure. Una vez dentro del Service Bus creado, en la parte inferior de la pantalla, hacemos click en Información de conexión. (Como podemos ver en la imagen inmediatamente anterior).

De ahí copiamos la cadena de conexión y la añadimos en la el app.config de la siguiente forma:

<appSettings>
        <!-- Service Bus specific app setings for messaging connections -->
        <add key="Microsoft.ServiceBus.ConnectionString" value="[connectionstringhere]"/>
    </appSettings>

El productor de mensajes

A continuación os dejo el código del productor que he creado a modo de ejemplo:

class Program
    {
        static void Main(string[] args)
        {
            bool exit = false;
            int i = 1;

            do
            {
                switch (menu())
                {
                    case 1:

                        QueueHelper.CreateQueue("TestQueue");
                        break;
                    case 2:

                        BrokeredMessage message = new BrokeredMessage("Example Service Bus Message");
                        message.Properties["Counter"] = i;

                        i += 1;

                        QueueHelper.SendMessage("TestQueue", message);
                        break;
                    default:
                        exit = true;
                        break;
                }
            }
            while (!exit);
        }

        static int menu()
        {
            Console.WriteLine("--- Option Menu ---");
            Console.WriteLine("0.- Exit");
            Console.WriteLine("1.- Create Queue");
            Console.WriteLine("2.- Send Message");
            Console.Write("-->");

            int value = int.Parse(Console.ReadLine());

            return value;
        }
    }

El código del productor implementa un sencillo menú por consola con dos opciones: por un lado crear la cola que vamos a usar (para la primera vez que usamos la aplicación), y por otro lado envía un mensaje a la misma.

Los mensajes se envían usando la clase BrokeredMessage. Esta clase en el constructor, nos permite establecer el cuerpo del mensaje y usando las propiedades de la misma, pasar otros parámetros de interés del mensaje.

Cómo podéis ver, el productor hace uso de un helper que implementa la funcionalidad de interacción con el service bus. Os dejo también a continuación las funciones que se usan.

public static void CreateQueue(string queueName)
        {
            // Configure queue settings
            QueueDescription qd = new QueueDescription(queueName);
            qd.MaxSizeInMegabytes = 5120;
            qd.DefaultMessageTimeToLive = new TimeSpan(0, 1, 0);

            // Create a new queue with custom settings
            string connectionString =
                CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString");

            var namespaceManager =
                NamespaceManager.CreateFromConnectionString(connectionString);

            if (!namespaceManager.QueueExists(queueName))
            {
                namespaceManager.CreateQueue(qd);
            }
        }

        public static void SendMessage(string queueName, BrokeredMessage message)
        {
            string connectionString =
                CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString");

            QueueClient Client =
                QueueClient.CreateFromConnectionString(connectionString, queueName);

            Client.Send(message);
        }

La función que crea la cola es muy sencilla. En primer lugar establece las propiedades de la cola que vamos a crear, en este caso, tamaño de la misma y el tiempo de vida del mensaje. A continuación obtiene del app.config la cadena de conexión y se conecta con el Service Bus. Por último, comprueba si existe la cola y en caso negativo, la crea.

La función que envía un mensaje es aún más sencilla. Simplemente establece la conexión con la cola del Service Bus donde queramos publicar el mensaje y lo envía.

El consumidor de mensajes

El código del consumidor es el que véis a continuación:

class Program
    {
        static void Main(string[] args)
        {
            while(true)
            {
                BrokeredMessage message = QueueHelper.ReceiveMessage("TestQueue");

                Console.WriteLine("Body: " + message.GetBody<string>());
                Console.WriteLine("MessageID: " + message.MessageId);
                Console.WriteLine("Test Property: " +
                message.Properties["Counter"]);

            }
        }
    }

Este código es muy sencillo. Está continuamente a la escucha de que en la cola haya algún mensaje y en caso de que sea así lo recibe y lo imprime por pantalla.

Al igual que el productor, usa un helper para la conexión con el Service Bus. El código de la función ReceiveMessage es el siguiente:

public static BrokeredMessage ReceiveMessage(string queueName)
        {
            string connectionString =
  CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString");
            QueueClient Client =
              QueueClient.CreateFromConnectionString(connectionString, queueName);

            BrokeredMessage message = null;

            try
            {
                message = Client.Receive();

                message.Complete();
            }
            catch(Exception ex)
            {
                message.Abandon();
            }

            return message;
        }

La función que recibe un mensaje de la cola funciona de la siguiente manera. En primer lugar se conecta con la cola correspondiente del Service Bus. Tras esto espera a que haya un mensaje en la cola para leer, si se recibe correctamente usa la función Complete() para eliminar el mensaje recibido de la cola. En caso de que haya algún error, usa la función Abandon() para liberarlo de nuevo en la cola.

Cómo funciona el ejemplo

Vamos a ver en una captura como funciona el ejemplo que hemos desarrollado:

Untitled2

Cada vez que se ejecuta la opción enviar mensaje, el productor envía un mensaje y el receptor lo recibe y muestra en pantalla, ya que como vimos en el código, éste está siempre esperando nuevos mensajes para procesarlos.

Y hasta aquí todo lo que os quería enseñar. ¿Cuáles son los siguientes pasos?, pues en próximos post os contaré como funcionan las subscripciones o topics y más adelante mezclaré todo esto con SharePoint OnLine, para como siempre, avanzar en las opciones que tenemos disponibles en Azure y ver cómo las podemos usar con SharePoint, se pueden plantear, como veremos, ejemplos muy interesantes.

Un saludo a todos y hasta la próxima