Mensagens em fila da solução de problemas
Esta seção contém perguntas comuns e ajuda para solução de problemas com o uso de filas no WCF (Windows Communication Foundation).
Perguntas comuns
P: Usei o WCF Beta 1 e instalei o hotfix do MSMQ. Preciso remover o hotfix?
R: Sim. Esse hotfix deixou de ter suporte. Agora, o WCF funciona no MSMQ sem a necessidade de um hotfix.
P: Há duas associações para o MSMQ: NetMsmqBinding e MsmqIntegrationBinding. Qual eu devo usar e quando?
R: Use NetMsmqBinding quando quiser usar o MSMQ como transporte para a comunicação enfileirada entre dois aplicativos WCF. Use MsmqIntegrationBinding quando quiser usar aplicativos MSMQ existentes para se comunicar com novos aplicativos WCF.
P: Preciso fazer upgrade do MSMQ para usar as associações NetMsmqBinding e MsmqIntegration
?
R: Não. Ambas as associações funcionam com o MSMQ 3.0 no Windows XP e Windows Server 2003. Alguns recursos das associações ficam disponíveis quando você faz upgrade para o MSMQ 4.0 no Windows Vista.
P: Quais recursos das associações NetMsmqBinding e MsmqIntegrationBinding estão disponíveis no MSMQ 4.0, mas não no MSMQ 3.0?
R: Os seguintes recursos estão disponíveis no MSMQ 4.0, mas não no MSMQ 3.0:
A fila de mensagens mortas personalizadas tem suporte apenas no MSMQ 4.0.
O MSMQ 3.0 e o 4.0 lidam com mensagens suspeitas de maneiras diferentes.
Somente o MSMQ 4.0 dá suporte à leitura de transação remota.
P: Posso usar o MSMQ 3.0 em um lado de uma comunicação enfileirada e o MSMQ 4.0 do outro lado?
R: Sim.
P: Quero integrar aplicativos MSMQ existentes a novos clientes ou servidores WCF. Preciso fazer upgrade dos dois lados da infraestrutura do MSMQ?
R: Não. Você não precisa fazer upgrade para o MSMQ 4.0 em ambos os lados.
Solução de problemas
Esta seção contém respostas para os problemas mais comuns de solução de problemas. Alguns problemas que são limitações conhecidas também são descritos nas notas sobre a versão.
P: Estou tentando usar uma fila privada e recebo a seguinte exceção: System.InvalidOperationException
: a URL é inválida. A URL da fila não pode conter o caractere '$'. Use a sintaxe em net.msmq://machine/private/queueName para resolver uma fila privada.
R: Verifique o URI (Uniform Resource Identifier) da fila na configuração e no código. Não use o caractere "$" no URI. Por exemplo, para endereçar uma fila privada chamada OrdersQueue, especifique o URI como net.msmq://localhost/private/ordersQueue
.
P: Chamar ServiceHost.Open()
em meu aplicativo enfileirado gera a seguinte exceção: System.ArgumentException
: um endereço básico não pode conter uma cadeia de caracteres de consulta de URI. Por que?
R: Verifique o URI da fila no arquivo de configuração e no código. Enquanto as filas do MSMQ dão suporte ao uso do caractere '?', os URIs o interpretam como o início de uma consulta de cadeia de caracteres. Para evitar esse problema, use nomes de fila que não contêm caracteres '?'.
P: Meu envio foi bem-sucedido, mas nenhuma operação de serviço é invocada no receptor. Por que?
R: Para determinar a resposta, percorra a seguinte lista de verificação:
Verifique se os requisitos de fila transacional são compatíveis com as garantias especificadas. Observe os seguintes princípios:
Você pode enviar mensagens duráveis (datagramas e sessões) com garantias do tipo "exatamente uma vez" (ExactlyOnce =
true
) apenas para uma fila transacional.Você pode enviar sessões apenas com garantias do tipo "exatamente uma vez".
Uma transação é necessária para receber mensagens em uma sessão de uma fila transacional.
Você pode enviar ou receber mensagens voláteis ou duráveis (somente datagramas) sem garantias (ExactlyOnce =
false
) apenas para uma fila não transacional.
Verifique a fila de mensagens mortas. Se encontrar as mensagens lá, determine por que elas não foram entregues.
Verifique as filas de saída quanto a problemas de conectividade ou de endereçamento.
P: Eu especifiquei uma fila de mensagens mortas personalizada, mas quando inicio o aplicativo remetente, recebo uma exceção de que a fila de mensagens mortas não foi encontrada ou o aplicativo de envio não tem permissão para a fila de mensagens mortas. Por que isso está acontecendo?
R: O URI da fila de mensagens mortas personalizada deve incluir um "localhost" ou o nome do computador no primeiro segmento, por exemplo, net.msmq://localhost/private/myAppdead-letter queue.
P: Sempre é necessário definir uma fila de mensagens mortas personalizada ou há uma fila de mensagens mortas padrão?
R: Se as garantias forem do tipo "exatamente uma vez" (ExactlyOnce = true
) e você não especificar uma fila de mensagens mortas personalizada, o padrão será uma fila de mensagens mortas transacionais em todo o sistema.
Se não houver garantias (ExactlyOnce = false
), o padrão será não ter nenhuma funcionalidade de fila de mensagens mortas.
P: Meu serviço gera SvcHost.Open com uma mensagem "Os requisitos de endpointListener não podem ser atendidos pelo ListenerFactory". Por que?
a. Verifique seu contrato de serviço. Talvez você tenha esquecido de colocar "IsOneWay=true
" em todas as operações de serviço. As filas dão suporte apenas a operações de serviço unidirecionais.
P: Há mensagens na fila, mas nenhuma operação de serviço é invocada. Qual é o problema?
R: Determine se o host de serviço tem falhas. Verifique examinando o rastreamento ou implementando IErrorHandler
. O host de serviço falha, por padrão, quando uma mensagem suspeita é detectada.
P: Há mensagens na fila, mas meu serviço enfileirado hospedado na Web não está sendo ativado. Por que?
R: O motivo mais comum são as permissões.
Verifique se o processo
NetMsmqActivator
está em execução e se a identidade do processoNetMsmqActivator
recebe permissão de leitura e busca na fila.Se o
NetMsmqActivator
estiver monitorando filas em um computador remoto, verifique seNetMsmqActivator
não é executado com um token restrito. Para executar oNetMsmqActivator
com um token irrestrito:sc sidtype NetMsmqActivator unrestricted
Para problemas de host da Web não relacionados à segurança, consulte: Hospedagem da Web de um aplicativo enfileirado.
P: Qual é a maneira mais fácil de acessar sessões?
R: Defina AutoComplete=true
na operação que corresponde à última mensagem na sessão e defina AutoComplete=false
em todas as operações de serviço restantes.
P: Por que meu serviço gera um ProtocolException
ao ler de uma fila que contém mensagens de sessão enfileiradas e mensagens de datagrama enfileiradas?
R: Há uma diferença fundamental na maneira como as mensagens de sessão enfileiradas e as mensagens de datagrama enfileiradas são compostas. Por isso, um serviço que espera ler uma mensagem de sessão enfileirada não pode receber uma mensagem de datagrama enfileirada, e um serviço que espera ler uma mensagem de datagrama enfileirada não pode receber uma mensagem de sessão. Tentar ler os dois tipos de mensagens da mesma fila gera a seguinte exceção:
System.ServiceModel.MsmqPoisonMessageException: The transport channel detected a poison message. This occurred because the message exceeded the maximum number of delivery attempts or because the channel detected a fundamental problem with the message. The inner exception may contain additional information.
---> System.ServiceModel.ProtocolException: An incoming MSMQ message contained invalid or unexpected .NET Message Framing information in its body. The message cannot be received. Ensure that the sender is using a compatible service contract with a matching SessionMode.
A fila de mensagens mortas do sistema, bem como qualquer fila de mensagens mortas personalizadas, fica particularmente suscetível a esse problema quando um aplicativo envia mensagens de sessão enfileiradas e mensagens de datagrama enfileiradas do mesmo computador. Se uma mensagem não puder ser enviada com êxito, ela será movida para a fila de mensagens mortas. Nessas circunstâncias, é possível ter mensagens de sessão e de datagrama na fila de mensagens mortas. Não há como separar os dois tipos de mensagens em tempo de execução ao ler de uma fila, portanto, os aplicativos não devem enviar mensagens de sessão enfileiradas e mensagens de datagrama enfileiradas do mesmo computador.
Integração com o MSMQ: solução de problemas específicos
P: Quando envio uma mensagem ou quando abro o host de serviço, recebo um erro que indica que o esquema está errado. Por que?
R: Ao usar a associação de integração com o MSMQ, você precisa usar o esquema msmq.formatname. Por exemplo, msmq.formatname:DIRECT=OS:.\private$\OrdersQueue. Mas quando você especificar a fila de mensagens mortas personalizada, deverá usar o esquema net.msmq.
P: Quando uso um nome de formato público ou privado e abro o host de serviço no Windows Vista, recebo um erro. Por que?
R: O canal de integração do WCF no Windows Vista verifica se uma subconsulta pode ser aberta para a fila do aplicativo principal para lidar com mensagens suspeitas. O nome da fila secundária é derivado de um URI msmq.formatname passado para o ouvinte. O nome da fila secundária no MSMQ pode ser apenas um nome de formato direto. Por isso, você vê o erro. Altere o URI da fila para um nome de formato direto.
P: Ao receber uma mensagem de um aplicativo MSMQ, a mensagem fica na fila e não é lida pelo aplicativo WCF de destino. Por que?
R: Verifique se a mensagem tem um corpo. Se a mensagem não tiver corpo, o canal de integração do MSMQ a ignorará. Implemente IErrorHandler
para ser notificado sobre exceções e verifique os rastreamentos.
Solucionar problemas relacionados à segurança
P: Quando executo o exemplo que usa uma associação padrão no modo de grupo de trabalho, as mensagens parecem ser enviadas, mas nunca são recebidas pelo destinatário.
R: Por padrão, as mensagens são assinadas usando um certificado interno MSMQ que requer o serviço de diretório Active Directory. No modo de grupo de trabalho, como o Active Directory não está disponível, a assinatura da mensagem falha. Portanto, a mensagem chega na fila de mensagens mortas e a causa da falha, como "Assinatura incorreta", é indicada.
A solução alternativa é desativar a segurança. Isso é feito definindo Mode = None para fazê-lo funcionar no modo de grupo de trabalho.
Outra solução alternativa é obter o MsmqTransportSecurity da propriedade Transport e defini-lo como Certificate e definir o certificado do cliente.
Outra solução alternativa é instalar o MSMQ com a integração do Active Directory.
R: Quando envio uma mensagem com associação padrão (segurança de transporte ativada) no Active Directory para uma fila, recebo uma mensagem "certificado interno não encontrado". Como corrigir isso?
R: Isso significa que o certificado no Active Directory do remetente deve ser renovado. Para fazer isso, abra o Painel de Controle, Ferramentas Administrativas, Gerenciamento de Computador, clique com o botão direito do mouse em MSMQ e selecione Propriedades. Selecione a guia Certificado do Usuário e clique no botão Renovar.
P: Quando envio uma mensagem usando Certificate e especifico o certificado a ser usado, recebo uma mensagem "Certificado inválido". Como corrigir isso?
R: Você não pode usar um repositório de certificados do computador local com o modo de certificado. Você precisa copiar o certificado do repositório de certificados do computador para o repositório do usuário atual usando o snap-in Certificado. Para obter o snap-in Certificado:
Clique em Iniciar, selecione Executar, digite
mmc
e clique em OK.No Console de Gerenciamento da Microsoft, abra o menu Arquivo e selecione Adicionar/Remover Snap-in.
Na caixa de diálogo Adicionar/Remover Snap-in, clique no botão Adicionar.
Na caixa de diálogo Adicionar Snap-in Autônomo, selecione Certificados e clique em Adicionar.
Na caixa de diálogo do snap-in Certificados, selecione Minha conta de usuário e clique em Concluir.
Em seguida, adicione um segundo snap-in Certificados usando as etapas anteriores, mas desta vez selecione Conta do computador e clique em Avançar.
Selecione Computador Local e clique em Concluir. Agora, você pode arrastar e soltar certificados do repositório de certificados do computador para o repositório do usuário atual.
P: Quando meu serviço lê de uma fila em outro computador no modo de grupo de trabalho, recebo uma exceção de "acesso negado".
R: No modo de grupo de trabalho, para que um aplicativo remoto tenha acesso à fila, ele precisa ter permissão para acessar a fila. Adicione "Logon anônimo" à ACL (lista de controle de acesso) da fila e conceda a ela permissão de leitura.
P: Quando um cliente de serviço de rede (ou qualquer cliente que não tenha uma conta de domínio) envia uma mensagem enfileirada, o envio falha com um certificado inválido. Como corrigir isso?
R: Verifique a configuração de associação. A associação padrão tem a segurança do transporte do MSMQ ativada para assinar a mensagem. Desligue-a.
Recebimentos transacionados remotos
P: Quando tenho uma fila no computador A e um serviço WCF que lê mensagens de uma fila no computador B (o cenário de recebimento transacionado remoto), as mensagens não são lidas da fila. As informações de rastreamento indicam que o recebimento falhou com a mensagem "A transação não pode ser importada". O que posso fazer para corrigir isso?
R: Há três possíveis razões para isso:
Se você estiver no modo de domínio, o recebimento transacionado remoto exigirá acesso à rede do MSDTC (Coordenador de Transações Distribuídas da Microsoft). Você pode habilitá-lo usando Adicionar/Remover Componentes.
Verifique o modo de autenticação para se comunicar com o gerenciador de transações. Se você estiver no modo de grupo de trabalho, "Nenhuma Autenticação Necessária" deverá ser selecionado. Se você estiver no modo de domínio, "Autenticação Mútua Necessária" deverá ser selecionado.
Verifique se o MSDTC está na lista de exceções nas configurações do Firewall de Conexão da Internet.
Verifique se você está usando o Windows Vista. O MSMQ no Windows Vista dá suporte a leituras transacionadas remotas. O MSMQ em versões anteriores do Windows não dá suporte à leitura transacionada remota.
P: Quando o serviço que está lendo da fila é um serviço de rede, por exemplo, em um host da Web, por que recebo uma exceção de acesso negado ao ler da fila?
R: O acesso de leitura do serviço de rede precisa ser adicionado à ACL da fila para garantir que um serviço de rede possa ler da fila.
P: Posso usar o serviço de ativação do MSMQ para ativar aplicativos com base em mensagens em uma fila em um computador remoto?
R: Sim. Para fazer isso, você precisa configurar o serviço de ativação do MSMQ para ser executado como um serviço de rede e adicionar acesso de serviço de rede à fila no computador remoto.
Usando associações do MSMQ personalizadas com ReceiveContext habilitado
Ao usar uma associação MSMQ personalizada com ReceiveContext habilitado, o processamento de uma mensagem de entrada usa um thread do pool de threads porque o MSMQ nativo não dá suporte à conclusão de E/S para recebimentos ReceiveContext assíncronos. Isso ocorre porque o processamento dessa mensagem usa transações internas para ReceiveContext e o MSMQ não dá suporte ao processamento assíncrono. Para contornar esse problema, você pode adicionar um SynchronousReceiveBehavior ao ponto de extremidade para forçar o processamento síncrono ou definir MaxPendingReceives como 1.