Partilhar via


Ativação do MSMQ

O exemplo MsmqActivation demonstra como hospedar aplicativos no Serviço de Ativação de Processos do Windows (WAS) que são lidos de uma fila de mensagens. Este exemplo usa o netMsmqBinding e é baseado no exemplo de comunicação bidirecional. O serviço, neste caso, é um aplicativo hospedado na Web e o cliente é auto-hospedado e sai para o console para observar o status das ordens de compra enviadas.

Nota

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

O Serviço de Ativação de Processos do Windows (WAS), o novo mecanismo de ativação de processos para o 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 Windows Communication Foundation (WCF) usa a interface do adaptador de ouvinte para comunicar solicitações de ativação recebidas pelos protocolos não-HTTP suportados pelo WCF, 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 ordens de compra para o serviço a partir do escopo de uma transação. O serviço recebe as ordens em uma transação e as processa. Em seguida, o serviço chama de volta o cliente 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 de pedidos.

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

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

O contrato de resposta para enviar o status do pedido é especificado pelo cliente. O cliente implementa o contrato de status do pedido. O serviço usa o cliente gerado deste 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 o alistamento automático na transação que é usada para receber a mensagem da fila e a conclusão automática da transação após a conclusão da operação de serviço. A Orders classe encapsula a funcionalidade de processamento de pedidos. Neste caso, adiciona a ordem de compra a um dicionário. A transação na qual a operação de serviço alistada está disponível para as operações na Orders classe.

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 ligação do 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 para o serviço é definido na seção System.serviceModel do arquivo de configuração.

Nota

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 do ponto de extremidade WCF especifica um esquema net.msmq:, usa "localhost" para o computador local e usa barras em seu caminho. Para ler a partir de 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 no WAS.

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

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

O arquivo Service.svc também contém uma diretiva de assembly para garantir que System.Transactions.dll seja carregado.

<%@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 dentro do escopo da transação, fazendo com que ela seja tratada como uma unidade atômica onde todas as mensagens são bem-sucedidas ou falham. A transação é confirmada chamando Complete o 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 contrato para receber o IOrderStatus 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 Main pedido é criada no método. A configuração do cliente inclui a configuração do serviço de status do pedido para hospedar 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. Certifique-se de que o IIS 7.0 está instalado, pois é necessário para a ativação do WAS.

  2. Certifique-se de ter executado o procedimento de instalação única para os 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 dos Recursos, clique em Adicionar Recursos.

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

  3. Para criar a edição C# ou Visual Basic .NET da solução, siga as instruções em Criando os exemplos do Windows Communication Foundation.

  4. Execute o cliente executando client.exe a partir 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 visualização para o Serviço de Rede. Isso pode ser adicionado usando o MMC do serviço de enfileiramento de mensagens:

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

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

    3. Clique em Filas Privadas.

    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 e dê uma espiada e receba permissões para o Serviço de Rede.

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

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

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

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

      Nota

      Este comando é uma única linha de texto.

      Este comando adiciona uma ligação de site net.msmq ao site padrão.

    2. Embora todos os aplicativos dentro de um site compartilhem uma ligação net.msmq comum, cada aplicativo pode habilitar o suporte a net.msmq individualmente. Para habilitar net.msmq para o aplicativo /servicemodelsamples, execute o seguinte comando em um prompt de comando elevado.

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

      Nota

      Este comando é uma única linha de texto.

      Este 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 de 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. Esta etapa só deve ser feita uma vez antes do primeiro uso do serviço Net.Msmq Listener Adapter.

  8. Para executar o exemplo em uma configuração de computador único ou entre computadores, siga as instruções em Executando 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. Utilize o seguinte código:

    client.SubmitPurchaseOrder(po, "net.msmq://localhost/private/ServiceModelSamples/OrderStatus");
    
  9. Remova a ligação de site net.msmq adicionada para este exemplo.

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

    1. Remova net.msmq da lista de protocolos habilitados executando o seguinte comando em um prompt de comando elevado.

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

      Nota

      Este comando é uma única linha de texto.

    2. Remova a ligação de site net.msmq executando o seguinte comando a partir de um prompt de comando elevado.

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

      Nota

      Este comando é uma única linha de texto.

    Aviso

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

Por padrão, com o transporte de ligação, a netMsmqBinding segurança está habilitada. Duas propriedades eMsmqProtectionLevel, juntas, MsmqAuthenticationMode determinam o tipo de segurança de transporte. Por padrão, o modo de autenticação é definido como Windows 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 é recebido: "O certificado de enfileiramento de mensagens interno do usuário não existe".

Para executar o exemplo em um computador associado a 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 no exemplo de configuração 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.

    Nota

    Definir security mode como None é equivalente a definir MsmqAuthenticationMode, MsmqProtectionLevel e Message segurança como None.

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

    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 Identity para usar a conta de usuário específica.

    Para alterar a identidade em que 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