Compartilhar via


Ativação do MSMQ

O exemplo MsmqActivation demonstra como hospedar aplicativos no WAS (Serviço de Ativação de Processos do Windows) que são lidos de uma fila de mensagens. Este exemplo usa o netMsmqBinding e se baseia no Two-Way Communication exemplo. Nesse caso, o serviço é um aplicativo hospedado na Web e o cliente é executado localmente e é exibido no console para observar o status dos pedidos de compra enviados.

Observação

O procedimento de instalação e as instruções de build para este exemplo estão localizados no final deste tópico.

O Serviço de Ativação de Processo do Windows (WAS), o novo mecanismo de ativação de processo para Windows Server 2008, fornece recursos semelhantes ao IIS que antes só estavam disponíveis para aplicativos baseados em HTTP para aplicativos que usam protocolos não HTTP. O WCF (Windows Communication Foundation) usa a interface do Adaptador do Ouvinte para comunicar solicitações de ativação recebidas por protocolos não HTTP compatíveis com o WCF, tais como TCP, Pipes Nomeados e MSMQ. A funcionalidade para receber solicitações em protocolos não HTTP é hospedada por serviços gerenciados do Windows em execução no SMSvcHost.exe.

O serviço Net.Msmq Listener Adapter (NetMsmqActivator) ativa aplicativos enfileirados com base em mensagens na fila.

O cliente envia pedidos de compra ao serviço dentro do escopo de uma transação. O serviço recebe os pedidos em uma transação e os processa. Em seguida, o serviço chama o cliente de volta com o status do pedido. Para facilitar a comunicação bidirecional, o cliente e o serviço usam filas para enfileirar ordens de compra e status das ordens.

O contrato de serviço IOrderProcessor define as operações unidirecionais de serviço que funcionam com o enfileiramento. A operação de serviço usa o ponto de extremidade de resposta para enviar status de ordens ao cliente. O endereço do ponto de extremidade de resposta é o URI da fila usada para enviar o status da ordem de volta para o cliente. O aplicativo de processamento de pedidos implementa esse contrato.

[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
public interface IOrderProcessor
{
    [OperationContract(IsOneWay = true)]
    void SubmitPurchaseOrder(PurchaseOrder po,
                                           string reportOrderStatusTo);
}

O contrato de resposta para o qual o status da ordem será enviado é especificado pelo cliente. O cliente implementa o contrato de status de ordens. O serviço usa o cliente gerado desse contrato para enviar o status do pedido de volta ao cliente.

[ServiceContract]
public interface IOrderStatus
{
    [OperationContract(IsOneWay = true)]
    void OrderStatus(string poNumber, string status);
}

A operação de serviço processa a ordem de compra enviada. O OperationBehaviorAttribute é aplicado à operação de serviço para especificar a inscrição automática na transação usada para receber a mensagem da fila e a conclusão automática da transação ao término da operação de serviço. A Orders classe encapsula a funcionalidade de processamento de pedidos. Nesse caso, ele adiciona a ordem de compra a um dicionário. A transação na qual a operação de serviço se inscreveu está disponível para as operações na classe Orders.

A operação de serviço, além de processar a ordem de compra enviada, responde ao cliente sobre o status do pedido.

public class OrderProcessorService : IOrderProcessor
{
    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public void SubmitPurchaseOrder(PurchaseOrder po, string reportOrderStatusTo)
    {
        Orders.Add(po);
        Console.WriteLine("Processing {0} ", po);
        Console.WriteLine("Sending back order status information");
        NetMsmqBinding msmqCallbackBinding = new NetMsmqBinding();
        msmqCallbackBinding.Security.Mode = NetMsmqSecurityMode.None;
        OrderStatusClient client = new OrderStatusClient(msmqCallbackBinding, new EndpointAddress(reportOrderStatusTo));
        // please note that the same transaction that is used to dequeue purchase order is used
        // to send back order status
        using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
        {
            client.OrderStatus(po.PONumber, po.Status);
            scope.Complete();
        }
    }
}

A associação de cliente a ser usada é especificada usando um arquivo de configuração.

O nome da fila MSMQ é especificado em uma seção appSettings do arquivo de configuração. O ponto de extremidade do serviço é definido na seção System.serviceModel do arquivo de configuração.

Observação

O nome da fila MSMQ e o endereço do ponto de extremidade usam convenções de endereçamento ligeiramente diferentes. O nome da fila MSMQ usa um ponto (.) para o computador local e separadores de barra invertida em seu caminho. O endereço de ponto de extremidade do WCF especifica um esquema net.msmq: usa "localhost" para o computador local e barras de encaminhamento em seu caminho. Para ler uma fila hospedada no computador remoto, substitua "." e "localhost" pelo nome do computador remoto.

Um arquivo .svc com o nome da classe é usado para hospedar o código de serviço em WAS.

O próprio arquivo Service.svc contém uma diretiva para criar o OrderProcessorService.

<%@ServiceHost language="c#" Debug="true" Service="Microsoft.ServiceModel.Samples.OrderProcessorService"%>

O arquivo Service.svc também contém uma diretiva de assembly para garantir o carregamento de System.Transactions.dll.

<%@Assembly name="System.Transactions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"%>

O cliente cria um escopo de transação. A comunicação com o serviço ocorre no escopo da transação, fazendo com que ela seja tratada como uma unidade atômica em que todas as mensagens são bem-sucedidas ou falham. A transação é confirmada chamando Complete no escopo da transação.

using (ServiceHost serviceHost = new ServiceHost(typeof(OrderStatusService)))
{
    // Open the ServiceHostBase to create listeners and start listening
    // for order status messages.
    serviceHost.Open();

    // Create a proxy with given client endpoint configuration
    OrderProcessorClient client = new OrderProcessorClient();

    // Create the purchase order
    PurchaseOrder po = new PurchaseOrder();
    po.CustomerId = "somecustomer.com";
    po.PONumber = Guid.NewGuid().ToString();

    PurchaseOrderLineItem lineItem1 = new PurchaseOrderLineItem();
    lineItem1.ProductId = "Blue Widget";
    lineItem1.Quantity = 54;
    lineItem1.UnitCost = 29.99F;

    PurchaseOrderLineItem lineItem2 = new PurchaseOrderLineItem();
    lineItem2.ProductId = "Red Widget";
    lineItem2.Quantity = 890;
    lineItem2.UnitCost = 45.89F;

    po.orderLineItems = new PurchaseOrderLineItem[2];
    po.orderLineItems[0] = lineItem1;
    po.orderLineItems[1] = lineItem2;

    //Create a transaction scope.
    using (TransactionScope scope = new
        TransactionScope(TransactionScopeOption.Required))
    {
        // Make a queued call to submit the purchase order
        client.SubmitPurchaseOrder(po,
       "net.msmq://localhost/private/ServiceModelSamplesOrder/OrderStatus");
        // Complete the transaction.
        scope.Complete();
    }

    //Closing the client gracefully closes the connection and cleans up
    //resources
    client.Close();

    Console.WriteLine();
    Console.WriteLine("Press <ENTER> to terminate client.");
    Console.ReadLine();

    // Close the ServiceHostBase to shutdown the service.
    serviceHost.Close();
    }

O código do cliente implementa o IOrderStatus contrato para receber o status do pedido do serviço. Nesse caso, ele imprime o status do pedido.

[ServiceBehavior]
public class OrderStatusService : IOrderStatus
{
    [OperationBehavior(TransactionAutoComplete = true,
                        TransactionScopeRequired = true)]
    public void OrderStatus(string poNumber, string status)
    {
        Console.WriteLine("Status of order {0}:{1} ",
                                         poNumber , status);
    }
}

A fila de status do pedido é criada no Main método. A configuração do cliente inclui a configuração para disponibilizar o serviço de status do pedido, conforme mostrado na configuração de exemplo a seguir.

<appSettings>
    <!-- use appSetting to configure MSMQ queue name -->
    <add key="targetQueueName" value=".\private$\ServiceModelSamples/service.svc" />
    <add key="responseQueueName" value=".\private$\ServiceModelSamples/OrderStatus" />
  </appSettings>

<system.serviceModel>

    <services>
      <service
         name="Microsoft.ServiceModel.Samples.OrderStatusService">
        <!-- Define NetMsmqEndpoint -->
        <endpoint address="net.msmq://localhost/private/ServiceModelSamples/OrderStatus"
                  binding="netMsmqBinding"
                  contract="Microsoft.ServiceModel.Samples.IOrderStatus" />
      </service>
    </services>

    <client>
      <!-- Define NetMsmqEndpoint -->
      <endpoint name="OrderProcessorEndpoint"
                address="net.msmq://localhost/private/ServiceModelSamples/service.svc"
                binding="netMsmqBinding"
                contract="Microsoft.ServiceModel.Samples.IOrderProcessor" />
    </client>

  </system.serviceModel>

Quando você executa o exemplo, as atividades de cliente e serviço são exibidas nas janelas do servidor e do console do cliente. Você pode ver o servidor receber mensagens do cliente. Pressione ENTER em cada janela do console para desligar o servidor e o cliente.

O cliente exibe as informações de status do pedido enviadas pelo servidor:

Press <ENTER> to terminate client.
Status of order 70cf9d63-3dfa-4e69-81c2-23aa4478ebed :Pending

Para configurar, compilar e executar o exemplo

  1. Verifique se o IIS 7.0 está instalado, pois ele é necessário para a ativação do WAS.

  2. Verifique se você executou o Procedimento de instalação avulsa dos exemplos do Windows Communication Foundation. Além disso, você deve instalar os componentes de ativação não HTTP do WCF:

    1. No menu Iniciar , escolha Painel de Controle.

    2. Selecione Programas e Recursos.

    3. Clique em Ativar ou desativar recursos do Windows.

    4. Em Resumo de Recursos, clique em Adicionar Recursos.

    5. Expanda o nó do Microsoft .NET Framework 3.0 e marque o recurso de Ativação não HTTP do Windows Communication Foundation.

  3. Para compilar a edição .NET do C# ou do Visual Basic da solução, siga as instruções contidas em Como Compilar as Amostras do Windows Communication Foundation.

  4. Execute o cliente executando client.exe de uma janela de comando. Isso cria a fila e envia uma mensagem para ela. Deixe o cliente em execução para ver o resultado do serviço lendo a mensagem

  5. O serviço de ativação do MSMQ é executado como Serviço de Rede por padrão. Portanto, a fila usada para ativar o aplicativo deve ter permissões de recebimento e espiada para o Serviço de Rede. É possível adicioná-las usando o MMC de Enfileiramento de Mensagens:

    1. No menu Iniciar , clique em Executar, digite Compmgmt.msc e pressione ENTER.

    2. Em Serviços e Aplicativos, expanda o Enfileiramento de Mensagens.

    3. Clique em Filas Particulares.

    4. Clique com o botão direito do mouse na fila (servicemodelsamples/Service.svc) e escolha Propriedades.

    5. Na guia Segurança , clique em Adicionar , dê uma olhada e receba permissões para o Serviço de Rede.

  6. Configure o WAS (Serviço de Ativação de Processo do Windows) para dar suporte à ativação do MSMQ.

    Como conveniência, as etapas a seguir são implementadas em um arquivo em lote chamado AddMsmqSiteBinding.cmd localizado no diretório de exemplo.

    1. Para dar suporte à ativação net.msmq, o site padrão deve primeiro ser associado ao protocolo net.msmq. Isso pode ser feito usando appcmd.exe, que é instalado com o conjunto de ferramentas de gerenciamento do IIS 7.0. Em um prompt de comando com privilégios elevados (administrador), execute o comando a seguir.

      %windir%\system32\inetsrv\appcmd.exe set site "Default Web Site"
      -+bindings.[protocol='net.msmq',bindingInformation='localhost']
      

      Observação

      Esse comando é uma única linha de texto.

      Esse comando adiciona uma associação de site net.msmq ao site padrão.

    2. Embora todos os aplicativos em um site compartilhem uma associação comum net.msmq, cada aplicativo pode habilitar o suporte a net.msmq individualmente. Para habilitar net.msmq para o aplicativo /servicemodelsamples, execute o comando a seguir em um prompt de comando com privilégios elevados.

      %windir%\system32\inetsrv\appcmd.exe set app "Default Web Site/servicemodelsamples" /enabledProtocols:http,net.msmq
      

      Observação

      Esse comando é uma única linha de texto.

      Esse comando permite que o aplicativo /servicemodelsamples seja acessado usando http://localhost/servicemodelsamples e net.msmq://localhost/servicemodelsamples.

  7. Se você não tiver feito isso anteriormente, verifique se o serviço de ativação do MSMQ está habilitado. No menu Iniciar , clique em Executar e digite Services.msc. Pesquise a lista de serviços para o Adaptador do Ouvinte Net.Msmq. Clique com o botão direito do mouse e selecione Propriedades. Defina o Tipo de Inicialização como Automático, clique em Aplicar e clique no botão Iniciar . Essa etapa deve ser realizada apenas uma vez antes do primeiro uso do serviço Adaptador de Escuta Net.Msmq.

  8. Para executar o exemplo em uma configuração de computador único ou cruzado, siga as instruções em Executar os exemplos do Windows Communication Foundation. Além disso, altere o código no cliente que envia a ordem de compra para refletir o nome do computador no URI da fila ao enviar a ordem de compra. Use o seguinte código:

    client.SubmitPurchaseOrder(po, "net.msmq://localhost/private/ServiceModelSamples/OrderStatus");
    
  9. Remova a vinculação do site net.msmq que você adicionou para este exemplo.

    Como conveniência, as seguintes etapas são implementadas em um arquivo em lote chamado RemoveMsmqSiteBinding.cmd localizado no diretório de exemplo:

    1. Remova net.msmq da lista de protocolos habilitados executando o comando a seguir de um prompt de comando com privilégios elevados.

      %windir%\system32\inetsrv\appcmd.exe set app "Default Web Site/servicemodelsamples" /enabledProtocols:http
      

      Observação

      Esse comando é uma única linha de texto.

    2. Para remover a associação de site do net.msmq, execute o comando a seguir em um prompt de comando com privilégios elevados.

      %windir%\system32\inetsrv\appcmd.exe set site "Default Web Site" --bindings.[protocol='net.msmq',bindingInformation='localhost']
      

      Observação

      Esse comando é uma única linha de texto.

    Aviso

    A execução do arquivo em lote redefinirá o DefaultAppPool para ser executado usando o .NET Framework versão 2.0.

Por padrão com o transporte de associação netMsmqBinding, a segurança é habilitada. Duas propriedades, MsmqAuthenticationMode e MsmqProtectionLevel, juntas determinam o tipo de segurança de transporte. Por padrão, o modo de autenticação é definido Windows como e o nível de proteção é definido como Sign. Para que o MSMQ forneça o recurso de autenticação e assinatura, ele deve fazer parte de um domínio. Se você executar este exemplo em um computador que não faz parte de um domínio, o seguinte erro será recebido: "O certificado de enfileiramento de mensagem interna do usuário não existe".

Para executar a amostra em um computador ingressado em um grupo de trabalho

  1. Se o computador não fizer parte de um domínio, desative a segurança de transporte definindo o modo de autenticação e o nível de proteção como nenhum, conforme mostrado na configuração de exemplo a seguir.

    <bindings>
        <netMsmqBinding>
            <binding configurationName="TransactedBinding">
                <security mode="None"/>
            </binding>
        </netMsmqBinding>
    </bindings>
    
  2. Altere a configuração no servidor e no cliente antes de executar o exemplo.

    Observação

    Configurar security mode para None equivale a configurar a segurança de MsmqAuthenticationMode, MsmqProtectionLevel e Message para None.

  3. Para habilitar a ativação em um computador pertencente a um grupo de trabalho, tanto o serviço de ativação quanto o processo de trabalho devem ser executados com uma conta de usuário específica (a mesma para ambos), e a fila deve possuir ACLs para essa conta de usuário.

    Para alterar a identidade sob a qual o processo de trabalho é executado:

    1. Execute Inetmgr.exe.

    2. Em Pools de Aplicativos, clique com o botão direito do mouse no AppPool (normalmente DefaultAppPool) e escolha Definir Padrões do Pool de Aplicativos....

    3. Altere as propriedades de identidade para usar a conta de usuário específica.

    Para alterar a identidade sob a qual o Serviço de Ativação é executado:

    1. Execute Services.msc.

    2. Clique com o botão direito do mouse no Adaptador Net.MsmqListener e escolha Propriedades.

  4. Altere a conta na guia LogOn .

  5. No grupo de trabalho, o serviço também deve ser executado usando um token irrestrito. Para fazer isso, execute o seguinte em uma janela de comando:

    sc sidtype netmsmqactivator unrestricted
    

Consulte também