Este artigo foi traduzido por máquina.

Previsão: Nublado

O barramento de serviço de AppFabric de Windows Azure: tópicos

Joseph Fultz

 

Este artigo baseia-se a atualização de junho do CTP do Windows Azure AppFabric. Todas as informações estão sujeitas a alterações.

Joseph FultzNão é segredo entre meus colegas que a funcionalidade de barramento de serviço Windows Azure não tenha realmente muito suporte do me. No entanto, com a atualização de junho do Windows Azure AppFabric CTP, a Microsoft finalmente adicionou recursos suficientes para mover o barramento de serviço do que eu considerado não muito mais do que um espaço reservado para uma tecnologia realmente útil. Para meu objetivo aqui, é a peça essencial da tecnologia de mensagens agora oferece o barramento de serviço AppFabric Tópicos, um sofisticado recurso de publicação e assinatura. Falarei sobre tópicos neste artigo e draw, como Estou tão freqüentemente apt fazer, de minha experiência no setor de varejo para examinar como a tecnologia pode ser usada para facilitar as verificações de estoque inter-store.

Você já passaram para comprar algo e encontrado que o último em uma só foi vendido ou que o item desejado é de alguma maneira confuso? Quando isso acontece, o auxiliar de venda freqüentemente irá entrar no sistema de POS e verificar o estoque nas lojas nas proximidades. Mais freqüentemente que não, essa verificação é contra contagens de estoque que são mantidas em um banco de dados central ou de recursos empresariais (ERP) de sistema de algum tipo de planejamento e o auxiliar geralmente verifica pelo número de armazenamento usando o seu conhecimento tribal dos armazenamentos próximos. Freqüentemente, os dados são um pouco obsoleto porque ele possui apenas atualizado como parte do final do dia de processamento quando os logs de transação e outros dados são carregados e processados pelo sistema corporativo.

Um cenário mais ideal seria o que um armazenamento poderia a qualquer momento lançar uma solicitação sobre a disponibilidade do produto para o ether e armazenamentos próximos responderia, indicando se eles tinham a ele. Esse é o que vou configurar usando o barramento de serviço de AppFabric de Windows Azure, conforme representado na a Figura 1.

An Inventory-Check Message
Figura 1 uma mensagem de verificação de inventário

Tópicos fornecem um mecanismo durável que me permite empurrar o conteúdo fora para até 2.000 assinantes por tópico. Que a limitação de assinante é desfavorável, como ela potencialmente força uma arquitetura de solução (como aquele que descreverei) para contornar isso criando segmentos de alguma forma do tópico. Por exemplo, em vez dos Estados Unidos Tópico Verificar estoque que assinantes filtrar por região, talvez eu tivesse que criar um SouthCentral EUA Consulte o tópico de estoque e filtrar ainda mais para a filial local específica. Com essa limitação, demonstrarei com meu único estoque verificar tópico, como posso pode prometer que não tenho mais de um punhado de locais de franquia em meu país das Maravilhas.

 

 

Recebendo a mensagem

Você pode baixar a atualização de junho de CTP AppFabric Windows Azure de bit.ly/p3DhAUe encontre o portal de gerenciamento em portal.appfabriclabs.com. Vai acessar o portal de gerenciamento para recuperar algumas partes de informação necessário para usar no meu código (consulte a Figura 2).

Getting Information from the Windows Azure AppFabric Management Portal
Figura 2, obtendo informações a partir do Portal de gerenciamento de AppFabric de Windows Azure

Eu preciso pegar o serviço de Gateway, o emissor padrão (sempre "proprietário" na versão CTP) e a chave padrão. Porque eu preciso esses em todo o meu exemplo, criarei-los no escopo do objeto:

private string sbNamespace = "jofultz";
private string issuerName = "owner";
private string issuerKey = "25vtsCkUPBtB39RdiBbUtCQglYRPOdHHC4MvX5fvxxxx";

Usarei essas variáveis em minhas funções para criar o tópico e, em seguida para postar mensagens para o tópico. Há uma interface REST para aqueles que desejam usá-lo ou que não estão implantando em uma plataforma que permite o uso da biblioteca cliente. Como estou criando um cliente Windows, usarei a biblioteca. Para isso, preciso adicionar referências às Microsoft.ServiceBus, Microsoft.ServiceBus.Message e System. ServiceModel, conforme mostrado na a Figura 3.

Adding References
Figura 3 Adicionando referências

Depois disso, algumas linhas simples de código são tudo o que são necessários para o tópico configurar:

SharedSecretCredential credential =
  TransportClientCredentialBase.CreateSharedSecretCredential(
  issuerName, issuerKey);
 
Uri sbUri = ServiceBusEnvironment.CreateServiceUri(
  "sb", sbNamespace, String.Empty);
ServiceBusNamespaceClient sbNSClient =
  new ServiceBusNamespaceClient(sbUri, credential);
Topic newTopic = sbNSClient.CreateTopic(topicName);

O que se tornará importante como inicio lançando mensagens por aí é a capacidade das lojas para filtrar as mensagens e obter somente aqueles que são relevantes para o local de recebimento com base na região. A API oferece suporte a correlação e da assinatura IDs como cidadãos de primeira classe, mas a filtragem quero usar meu conhecimento dos dados e filtro com base no conteúdo da solicitação. Assim, eu quero fechar geograficamente armazenamentos para procurar e responder às solicitações de uns dos outros para estoque com base na região. Ao mesmo tempo, preciso certificar-se de que o armazenamento de origem não pegar suas próprias solicitações. Solicitações incluirá o SKU de item em questão, a região em que a consulta é feita e o RequesterID para que o armazenamento de origem pode filtrar suas próprias solicitações no tópico:

[Serializable]
class InventoryQueryData
{
  public string Region;
  public string ResponderID;
  public string RequesterID;
  public string Sku;
  public int Count;
}

Observe o atributo [Serializable] que adicionamos à classe. Você pode marcar as propriedades como DataMembers e use DataContract bem, mas o ponto é que qualquer tipo que pretende enviar o tópico precisa ser serializável.

Criei um formulário simples que me permite inserir uma seqüência arbitrária para a SKU e selecione uma lista para o armazenamento de lançamento. O código por trás do meu botão consulta é semelhante ao código para se conectar e criar o tópico e lembra as construções típicas encontrar ao trabalhar com as APIs de mensagens, como mostrado na a Figura 4.

Figura 4 Obtendo os valores de dados

// Assign data values.
InventoryQueryData data = new InventoryQueryData();
data.Sku = txtSKU.Text;
data.StoreID = cboStore.SelectedText;
data.Region = cboStore.SelectedValue.ToString();
 
Uri sbUri = ServiceBusEnvironment.CreateServiceUri("sb", sbNamespace, string.Empty);
SharedSecretCredential credential = TransportClientCredentialBase.CreateSharedSecretCredential
(issuerName, issuerKey);
 
MessagingFactory msgFactory = MessagingFactory.Create(sbUri, credential);
TopicClient topicClient = msgFactory.CreateTopicClient(topicName);
MessageSender MsgSender = topicClient.CreateSender();
 
BrokeredMessage msg = BrokeredMessage.CreateMessage(data);
// Add props to message for filtering.
msg.Properties["Region"] = data.Region;
msg.Properties["RequesterID"] = data.RequesterID;
 
msg.TimeToLive = TimeSpan.FromSeconds(60);
 
MsgSender.Send(data);

Existem duas coisas a serem observadas aqui. Primeiro, adicionei os pares nome-valor que preciso para filtragem à coleção BrokeredMessage.Properties. Em segundo lugar, como uma questão de tempo de execução de manutenção, usei o TimeToLive (TTL) um valor de 60 segundos, o que deve evitar as inscrições no tópico muito obtenção de backup. Obviamente, você geralmente desejará uma abordagem mais informada para o TTL de separação, mas imagino se a solicitação não assinantes chegar nesse tempo, provavelmente é muito longo porque há um cliente posicione pé lá aguardando. Além disso, isso é apenas um exemplo.

Qualquer mensagem enviada para o barramento está na forma de um BrokeredMessage que tem um método de fábrica CreateMessage. Isso simplesmente encapsula os dados em uma instância de um tipo de BrokeredMessage que contém todas as construções necessárias para um sistema de mensagens totalmente funcional.

Com isso que tenho tudo o que preciso pegar uma mensagem para os assinantes do tópico Verificar estoque, portanto, agora começarei como configurar os clientes de assinatura para buscar as mensagens e responder.

Tocando o fluxo de tópico e responder

Com o meu cliente no lugar, estou pronto para enviar um fluxo contínuo de solicitações, mas pouco mais do que os bits de permissão certa agora será soltos no ether wild. Posso criar um aplicativo do Windows Form e reutilizar lista XML store e o InventoryQueryData do primeiro aplicativo (remetente). Precisarei criar uma assinatura exclusiva para cada cliente que está escutando o tópico. Isso é realizado facilmente o suficiente, combinando um nome de inscrição com o número da loja que quero ouvir. Meu aplicativo de teste pouco permite que eu selecione o número de armazenamento da combobox, portanto, eu, inclua esse valor para o nome de inscrição de base para criar o nome de inscrição exclusivo. É importante garantir que cada cliente tem uma assinatura exclusiva; dois ou mais usando a mesma assinatura criaria uma condição de corrida em que os subscritores concorrer para a mensagem e o primeiro para receber e excluir seria a vencedora:

Topic invTopic = sbNSClient.GetTopic(topicName);
SubscriptionName = "InventoryQuerySubscription" + this.cboStore.Text;
SqlFilterExpression RegionFilter = new SqlFilterExpression("Region = '" +
  cboStore.SelectedValue + "' AND RequesterID <> '" + cboStore.Text + "'");
 
Subscription sub = invTopic.AddSubscription(SubscriptionName, RegionFilter);

Como adiciono a inscrição para o tópico, eu também pode passar em um filtro de modo que cada loja recebe apenas as solicitações de verificação de inventário para sua própria região. Observe que você pode desenvolver seu próprio tipo FilterExpression do tipo base, mas a API inclui quatro tipos que devem abranger a maioria das situações, especialmente se usado em conjunto: CorrelationFilterExpression, MatchAllFilterExpression, MatchNoneFilterExpression e SqlFilterExpression. Usei o SqlFilterExpression, que me permitiu facilmente e instintivamente escreve essa expressão para obter as mensagens para a região do Texas, por exemplo e excluir mensagens originadas meu próprio armazenamento:

"Region = '[Region]' AND RequesterID <> '[StoreID]'"

Só preciso filtrar as solicitações recebidas por meio de, mas em alguns casos eu poderia teoricamente "corrigir" alguns dados na forma como no uso de um RuleDescription para, digamos, combinar um SqlFilterExpression com um SqlFilterAction. A primeira identifica as mensagens que tenho como alvo, enquanto o último define a ação que deve ser tomada. Esse tipo de funcionalidade pode ser útil quando os dados provenientes precisa ser manipulados em algo que funcione para ambos os lados do barramento e o destinatário não podem ou não ser alterados.

Uma vez definida a inscrição até ele persistirão mesmo após o cliente fecha para baixo. Esta situação é ideal para esse cenário; Simplesmente, criarei uma SubscriptionClient sempre que eu iniciar o monitoramento e ele será anexado à conexão existente. No entanto, nem todos desejarão desse comportamento. Pode imaginar a situações onde você gostaria de remover a assinatura quando o cliente é encerrado:

SubscriptionClient subClient = msgFactory.CreateSubscriptionClient(
  topicName, SubscriptionName);
MessageReceiver msgReceiver = subClient.CreateReceiver(ReceiveMode.ReceiveAndDelete);
msgReceiver.Open();

Observe, na chamada para CreateReceiver, que defini ReceiveMode como ReceiveAndDelete. Você também poderia usar PeekLock para o ReceiveMode. Aqui, eu simplesmente querer pegar a mensagem e o processo que e eu não tiver nenhuma necessidade para garantir o recebimento adequado e processamento antes para exclusão, porque se a mensagem for perdida, não é um grande problema. Se eu precisava de comportamento que era mais garantida e confiável, provavelmente faria duas coisas. Eu não seria definir o TTL da mensagem, tópico ou assinatura e deixe em vez disso, as mensagens live indefinidamente. Ou, o que eu daria ele um TTL muito alto para que o receptor teve tempo suficiente para processar ou mover para uma fila de exceção para que as mensagens não entregues somente verdadeiramente acabaria na fila de inatividade. Além disso, eu usaria PeekLock no receptor para ler e processar os dados e remover apenas a mensagem após a conclusão do processo relacionado. Criar manualmente esse comportamento de transações distribuídas pode conduzir rapidamente a outros problemas, tais como filas suspeitas, mas vamos abordá desse comportamento e problema definido em outra ocasião.

Depois que você abrir o receptor insiro um loop para verificar se há mensagens. A API tem um método de recebimento direto que retornará o BrokeredMessage. No entanto, usarei o método TryReceive, que retornará um bool para indicar êxito (consulte a Figura 5). Transmitirei um tempo limite relativamente curto para este método, que deve ser grande o suficiente para verificar e receber a mensagem. Se uma mensagem for recebida, vou trabalhar com ela e verifique imediatamente para outra mensagem. Se nenhuma mensagem for recebida, examinarei o segmento para um bit de suspensão e verificar novamente.

Figura 5 Verificando mensagens

while (MonitorOn)
{
  BrokeredMessage NewMsg;
  bool recvSuccess = msgReceiver.TryReceive(TimeSpan.FromSeconds(3), out NewMsg);
 
  if (recvSuccess)
  {
    this.lbMessages.Items.Add(NewMsg.MessageId);
    InventoryQueryData RequestObject =
      NewMsg.GetBody<CreateInquiry.InventoryQueryData>();
    ProcessMessage(RequestObject);
  }
  else
  {
    System.Threading.Thread.Sleep(3000);
  }
}

Meu objeto de solicitação está contido na BrokeredMessage e recuperá-lo eu vou chamar o GetBody <T>, passando o tipo de objeto. A implicação aqui é que tipos de objeto precisam corresponder em ambos os lados do barramento. Você pode fazer isso usando tipos de proxy ou, no caso de incerteza ou antigo XML sem formatação, chegando pela, você poderia passar o objeto como uma seqüência de caracteres e manipulá-lo como XML.

Até a próxima vez …

Neste ponto, todo o trabalho é feito para criar a mensagem e levá-lo todos os nós interessado e para que eles possam buscar a mensagem do tópico. Demonstrei os recursos que me permitem não apenas a mensagem de difusão, mas também filtrar apropriadamente para o receptor inscrito. Próximo mês será trabalho por meio de viagem de demonstrar o uso complementar de filas e correlação para concluir o cenário e complementam a Noções básicas sobre os novos recursos do barramento de serviço de Windows Azure AppFabric. Eu também terá o código completo disponível para download.

Joseph Fultz é um arquiteto de software na Hewlett-Packard Co, trabalhando como parte do grupo de TI Global Home da HP.com.  Anteriormente, era arquiteto de software na Microsoft, trabalhando com seus clientes empresariais e ISV de camada superior, definindo soluções de arquitetura e design.

Graças ao seguir técnico especialista para revisar este artigo: Jim Keane