Desenvolvimento de aplicações para a Cloud Queue
O serviço Queue Fornece uma infra-estrutura escalável e com grande disponibilidade para comunicação de mensagens na cloud. Esquema URL Tamanho máximo Referência API http://[storageaccount].queue.cor e.windows.net/[queuename] 8KB (string) http://msdn.microsof t.com/en-us/library/ dd179363.aspx 2 Cátia Vaz 2011/2012
Exemplo de utilização: padrão Web + Worker Role Web role Lida com os pedidos dos utilizadores Coloca items na queue Worker role Processa os items a partir da queue Public internet n m Load balancer Web role Q Worker role Cloud storage (tables, blobs, queues) 3 Cátia Vaz 2011/2012
Arquitectura do serviço Queue 4 Cátia Vaz 2011/2012
Conceitos de Queue Storage Account sally Queue thumbnail jobs photo processing jobs Message 128x128, http:// 256x256, http:// http:// http:// - Oferece garantia na entrega das mensagens - Despacho do trabalho simples e assíncrono - A semântica de programação assegura que a mensagem pode ser processada pelo menos uma vez - Têm uma performance eficiente. - O acesso é via REST
Processamento de mensagens na queue Producers Consumers P 2 C 1 1. Dequeue(Q, 30 sec) msg 1 4 3 2 1 P 1 C 2 2. Dequeue(Q, 30 sec) msg 2
Processamento de mensagens na queue Produtores Consumidores P 2 1 C 1 1. Dequeue(Q, 30 sec) msg 1 5. C 1 crashed P 1 4 3 2 1 2 C 2 2. Dequeue(Q, 30 sec) msg 2 3. C2 consumed msg 2 4. Delete(Q, msg 2) 7. Dequeue(Q, 30 sec) msg 1 6. msg1 visível 30 segundos após Dequeue
Account, Queues e Mensagens Uma account pode conter várias queues O nome da queue fica contextualizado pela conta. Uma queue contém messagens Não existe limite no número de mensagem armazenadas numa queue Uma mensagem é armazenada no máximo uma semana numa queue http://<account>.queue.core.windows.net/<queuename> Mensagens Tamanho das mensagens <= 8 KB Têm os seguintes atributos: MessageID PopReceipt Messagettl 8 Cátia Vaz 2011/2012
Limites e Restrições As limitações do serviço Queue são as seguintes: O serviço queue suporta um número ilimitado de mensagens, mas cada mensagem não pode ter mais do que 64KB de tamanho Se a mensagem tiver maior tamanho, pode-se armazenar o object no Blob ou Table e enviar o link como mensagem. O comportamento FIFO das mensagens enviadas para o serviço Queue não é garantido. As mensagens podem ser recebidas por qualquer ordem. Uma mensagem pode ser recebida mais do que uma vez. As mensagens pode ser em formato texto ou binário, mas sempre no formato de codificação Base64 As mensagens armazenadas no serviço Queue têm como tempo de expiração de 7 dias. Após 7 dias, as mensagens são garbagecollected. 9 Cátia Vaz 2011/2012
Nomes das queues Restrições nos nomes das Queues: O nome tem de ser único no contexto da conta Tem de iniciar com uma letra ou número e apenas letras minúsculas, com dimensão entre 3 e 63. Não pode conter caracteres especiais excepto (-), o qual tem de ser seguido por um caracter ou número. 10 Cátia Vaz 2011/2012
Microsoft.WindowsAzure.StorageClient Nome da Classe CloudStorageAccount CloudQueueClient CloudQueue CloudQueueMessage Descrição Uma classe utilitária que retorna a informação de um account através de um ficheiro de configuração ou cria uma instância de um storage account a partir dos parâmetros da account. Uma classe wrapper para obter as referências dos objectos principais da queue. A classe consiste de métodos como GetQueueReference() e ListQueues() Consiste de operações de Queue tais como: Create(), Delete(), AddMessage(), e GetMessage(). Representa uma mensagem da queue com propriedades como InsertionTime, ExpirationTime, NextVisibleTime, ID, e PopReceipt. 11 Cátia Vaz 2011/2012
Operações Comuns ListQueues GetMessage AddMessage Delete DeleteMessage Ver mais: CloudQueue
Inserir uma mensagem CloudStorageAccount storageaccount = CloudStorageAccount.Parse( RoleEnvironment.GetConfigurationSettingValue("StorageConnectionString")); CloudQueueClient queueclient = storageaccount.createcloudqueueclient(); CloudQueue queue = queueclient.getqueuereference("myqueue"); queue.createifnotexist(); CloudQueueMessage message = new CloudQueueMessage("Hello, Cloud"); queue.addmessage(message);
Obter uma mensagem CloudStorageAccount storageaccount = CloudStorageAccount.Parse( RoleEnvironment.GetConfigurationSettingValue("StorageConnectionSt ring")); CloudQueueClient queueclient = storageaccount.createcloudqueueclient(); CloudQueue queue = queueclient.getqueuereference("myqueue"); CloudQueueMessage Message = queue.getmessage();
Retirar a próxima mensagem CloudStorageAccount storageaccount = CloudStorageAccount.Parse( RoleEnvironment.GetConfigurationSettingValue("StorageConnectionString")); CloudQueueClient queueclient = storageaccount.createcloudqueueclient(); CloudQueue queue = queueclient.getqueuereference("myqueue"); CloudQueueMessage retrievedmessage = queue.getmessage(); queue.deletemessage(retrievedmessage);
Obter o tamanho da queue CloudStorageAccount storageaccount = CloudStorageAccount.Parse( RoleEnvironment.GetConfigurationSettingValue("StorageConnectionString")); CloudQueueClient queueclient = storageaccount.createcloudqueueclient(); CloudQueue queue = queueclient.getqueuereference("myqueue"); int freshmessagecount = queue.retrieveapproximatemessagecount(); int? cachedmessagecount = queue.approximatemessagecount;
Manipular mensagens cuja dimensão exceda os 64 KB private static void HandleUploadImage(){ var cloudblobclient = GetCloudStorageAcount().CreateCloudBlobClient(); var cloudblobcontainer = cloudblobclient.getcontainerreference("images"); cloudblobcontainer.createifnotexist(); var filestream = new FileStream(@"F:\bg.jpg", FileMode.Open); Console.WriteLine("Image size: {0}", filestream.length); var blobid = Guid.NewGuid().ToString(); var cloudblob = cloudblobcontainer.getblobreference(blobid); cloudblob.uploadfromstream(filestream); var cloudqueueclient = GetCloudStorageAccount().CreateCloudQueueClient(); var cloudqueue = cloudqueueclient.getqueuereference("imageupload"); cloudqueue.createifnotexist(); } var cloudqueuemessage = new CloudQueueMessage(blobid); cloudqueue.addmessage(cloudqueuemessage, TimeSpan.FromDays(7)); Console.WriteLine("Blob uploaded and enqueued [ {0} ]", blobid); 17 Cátia Vaz 2011/2012
Manupular mensagens cuja dimensão exceda os 64 KB private static void ProcessImage(){ var cloudqueueclient = GetCloudStorageAccount().CreateCloudQueueClient(); var cloudqueue = cloudqueueclient.getqueuereference("imageupload"); var cloudqueuemessage = cloudqueue.getmessage(); if(cloudqueuemessage! = null) { var blobid = cloudqueuemessage.asstring; Console.WriteLine("Queue message retrieved with content. [{0}]", blobid); } var cloudblobclient = GetCloudStorageAccount().CreateCloudBlobClient(); var cloudblobcontainer = cloudblobclient.getcontainerreference("images"); var cloudblob = cloudblobcontainer.getblobreference(blobid); var memorystream = new MemoryStream(); cloudblob.downloadtostream(memorystream); Console.WriteLine("Image size: {0}", memorystream.length); } 18 Cátia Vaz 2011/2012
Padrão de Desenho Síncrono Cada thread dedicada a um pedido Bloqueia cada passo do trabalho feito por cada pedido, e depois responde e repete Client Request #1 Web App Front End The Work #1 Client Response #1 Client Request #2 Thread Waiting Thread blocks Response #1 O tempo passa Esta abordagem escala menos Cada pedido é armazenado numa thread stack As threads bloqueiam mesmo quando não existe trabalho a ser feito Adicionar uma thread permite apenas um único pedido concorrente adicional
Padrão de desenho assíncrono Cada thread processo um trabalho, sempre que está pronto Uma thread que processa um pedido, pode processar outro, antes de o anterior completar Web App Front End The Work #1 Esta abordagem escala melhor Thread Thread Context É feito explicitamente tracking dos pedidos dos clientes nas estruturas de dados das aplicações As threads nunca bloqueiam quando não existe trabalho a ser processado Cada thread pode possivelmente manipular vários pedidos concorrentes
StorageClient API: Suporte síncrono public void AddMessage( string queuename, CloudQueueMessage queuemessage) { CloudQueue q = QueueClient.GetQueueReference(queueName); q.addmessage(queuemessage); }
StorageClient API: Suporte assíncrono public void AddMessageAsync(string queuename, CloudQueueMessage queuemessage, int ttlsecs) { CloudQueue q = QueueClient.GetQueueReference(queueName); using (System.Threading.ManualResetEvent evt = new System.Threading.ManualResetEvent(false)) { q.beginaddmessage(queuemessage, TimeSpan.FromSeconds(ttlsecs), new AsyncCallback(result =>{ var qc = result.asyncstate as CloudQueue; qc.endaddmessage(result); evt.set(); } ), q); evt.waitone(); }}
AsyncCallback public delegate void AsyncCallback( IAsyncResult ar ) Resultado da operação assíncrona public interface IAsyncResult{ Object AsyncState; WaitHandle AsyncWaitHandle ; bool CompletedSynchronously; bool IsCompleted; } 23 Cátia Vaz 2011/2012
Outro exemplo public IEnumerable<CloudQueueMessage> GetMessagesAsync(string queuename, int numberofmessages, int visibilitytimeoutinsecs) { CloudQueue q = QueueClient.GetQueueReference(queueName); IEnumerable<CloudQueueMessage> ret = null; using (System.Threading.ManualResetEvent evt = new System.Threading.ManualResetEvent(false)){ q.begingetmessages(numberofmessages, TimeSpan.FromSeconds(visibilityTimeoutInSecs), new AsyncCallback(result => { var qc = result.asyncstate as CloudQueue; ret = qc.endgetmessages(result); evt.set();}), q); evt.waitone(); } return ret;} 24 Cátia Vaz 2011/2012
Cenário 1 25 Cátia Vaz 2011/2012
Cenário 2 26 Cátia Vaz 2011/2012
Cenário 3 27 Cátia Vaz 2011/2012
Windows Azure Data Storage Container Blobs http://<account>.blob.core.windows.net/<container> Account Table Entities http://<account>.table.core.windows.net/<table> Queue Messages http://<account>.queue.core.windows.net/<queue>