Práticas recomendadas de hospedagem dos Serviços de Informações da Internet

Este tópico descreve algumas melhores práticas para hospedar serviços do Windows Communication Foundation (WCF).

Implementando serviços WCF como DLLs

Implementar um serviço WCF como uma DLL implantada no diretório \bin de um aplicativo Web permite reutilizar o serviço fora do modelo de aplicativo Web, por exemplo, em um ambiente de teste que pode não ter os Serviços de Informações da Internet (IIS) implantados.

Hosts de serviço em aplicativos hospedados no IIS

Não use as APIs de auto-host imperativas para criar novos hosts de serviço que escutam em transportes de rede sem suporte nativo pelo ambiente de hospedagem do IIS (por exemplo, IIS 6.0 para hospedar serviços TCP, porque a comunicação TCP não tem suporte nativo no IIS 6.0). Essa abordagem não é recomendada. Os hosts de serviço criados de forma imperativa não são conhecidos no ambiente de hospedagem do IIS. O ponto crítico é que o processamento feito por serviços criados imperativamente não é contabilizado pelo IIS quando determina se o pool de aplicativos de hospedagem está ocioso. O resultado é que os aplicativos que têm hosts de serviço criados de forma imperativa têm um ambiente de hospedagem do IIS que descarta agressivamente os processos de host do IIS.

URIs e pontos de extremidade hospedados no IIS

Os pontos de extremidade para um serviço hospedado no IIS devem ser configurados usando Uniform Resource Identifiers (URIs) relativos, não endereços absolutos. Isso garante que o endereço do ponto de extremidade esteja dentro do conjunto de endereços URI que pertencem ao aplicativo de hospedagem e garante que a ativação baseada em mensagem ocorra conforme o esperado.

Gerenciamento de Estado e Reciclagem de Processos

O ambiente de hospedagem do IIS é otimizado para serviços que não mantêm o estado local na memória. O IIS recicla o processo de host em resposta a uma variedade de eventos externos e internos, fazendo com que qualquer estado volátil armazenado exclusivamente na memória seja perdido. Os serviços hospedados no IIS devem armazenar seu estado externo ao processo (por exemplo, em um banco de dados) ou em um cache na memória que pode ser facilmente recriado se ocorrer um evento de reciclagem de aplicativo.

Observação

Os protocolos que o WCF usa para confiabilidade e segurança da camada de mensagens usam o estado volátil na memória. Sessões confiáveis e sessões de segurança do WCF podem terminar inesperadamente devido a reciclagens de aplicativos. Os aplicativos hospedados no IIS que fazem uso desses protocolos devem depender de algo diferente da chave de sessão fornecida pelo WCF para correlacionar o estado da camada de aplicativo (por exemplo, um constructo de camada de aplicativo ou cabeçalho de correlação personalizado) ou desabilitar a reciclagem de processo do IIS para o aplicativo hospedado.

Otimizando o desempenho em cenários de camada intermediária

Para obter um desempenho ideal em um cenário de camada intermediária, um serviço que chama outros serviços em resposta a mensagens de entrada, instancie o cliente de serviço do WCF para o serviço remoto uma vez e reutilize-o em várias solicitações de entrada. A instanciação de clientes de serviço WCF é uma operação cara em relação a fazer uma chamada de serviço em uma instância de cliente pré-existente e cenários de camada intermediária produzem ganhos de desempenho distintos armazenando em cache clientes remotos entre solicitações. Os clientes de serviço do WCF são thread-safe, portanto, não é necessário sincronizar o acesso a um cliente em vários threads.

Cenários de camada intermediária também produzem ganhos de desempenho usando as APIs assíncronas geradas pela opção svcutil /a. A opção /a faz com que a Ferramenta de Utilitário de Metadados do ServiceModel (Svcutil.exe) gere BeginXXX/EndXXX métodos para cada operação de serviço, o que permite que chamadas potencialmente longas para serviços remotos sejam feitas em threads em segundo plano.

WCF em cenários multilocatários ou multi-nomeados

Você pode implantar serviços WCF dentro de um Web farm do IIS, onde um conjunto de computadores compartilham um nome externo comum (como http://www.contoso.com), mas são tratados individualmente por nomes do host diferentes (por exemplo, http://www.contoso.com podem direcionar o tráfego para dois computadores diferentes nomeados http://machine1.internal.contoso.com e http://machine2.internal.contoso.com). Esse cenário de implantação é totalmente compatível com o WCF, mas requer uma configuração especial do site do IIS que hospeda serviços WCF para exibir o nome de host correto (externo) nos metadados do serviço (WSDL).

Para garantir que o nome do host correto apareça no WCF de metadados de serviço gerado, configure a identidade padrão para o site do IIS que hospeda serviços WCF para usar um nome do host explícito. Por exemplo, os computadores que residem dentro do farm www.contoso.com devem usar uma associação de site do IIS de *:80:www.contoso.com para HTTP e *:443:www.contoso.com para HTTPS.

Você pode configurar associações de site do IIS usando o snap-in do Console de Gerenciamento da Microsoft (MMC) do IIS.

Pools de aplicativos em execução em diferentes contextos de usuário substituem conjuntos de outras contas na pasta temporária

Para garantir que os pools de aplicativos em execução em diferentes contextos de usuário não possam substituir conjuntos de outras contas na pasta de arquivos de ASP.NET temporária, use diferentes identidades e pastas temporárias para diferentes aplicativos. Por exemplo, se você tiver dois aplicativos virtuais /Application1 e /Application2, poderá criar dois pools de aplicativos, A e B, com duas identidades diferentes. O pool de aplicativos A pode ser executado em uma identidade de usuário (user1), enquanto o pool de aplicativos B pode ser executado em outra identidade de usuário (user2) e configurar /Application1 para usar A e /Application2 para usar B.

No Web.config, você pode configurar a pasta temporária usando <system.web/compilation/@tempFolder>. Para /Application1, pode ser "c:\tempForUser1" e para o application2 pode ser "c:\tempForUser2". Conceda permissão de gravação correspondente a essas pastas para as duas identidades.

Em seguida, user2 não pode alterar a pasta de geração de código para /application2 (em c:\tempForUser1).

Habilitando o processamento assíncrono

Por padrão, as mensagens enviadas a um serviço WCF hospedado no IIS 6.0 e anteriores são processadas de maneira síncrona. O ASP.NET chama o WCF em seu próprio thread (o thread de trabalho do ASP.NET) e o WCF usa outro thread para processar a solicitação. O WCF mantém o thread de trabalho do ASP.NET até concluir o processamento. Isso leva ao processamento síncrono de solicitações. O processamento de solicitações de forma assíncrona permite maior escalabilidade porque reduz o número de threads necessários para processar uma solicitação; o WCF não se mantém no thread de ASP.NET durante o processamento da solicitação. O uso de comportamento assíncrono não é recomendado para computadores que executam o IIS 6.0 porque não há como restringir as solicitações de entrada que abrem o servidor para ataques de Negação de Serviço (DOS). A partir do IIS 7.0, foi introduzida uma restrição de solicitação simultânea: [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET\2.0.50727.0]"MaxConcurrentRequestsPerCpu. Com essa nova restrição, é seguro usar o processamento assíncrono. Por padrão, no IIS 7.0, o manipulador e o módulo assíncronos são registrados. Se isso tiver sido desativado, você poderá habilitar manualmente o processamento assíncrono de solicitações no arquivo Web.config do aplicativo. As configurações usadas dependem da configuração de aspNetCompatibilityEnabled. Se você tiver aspNetCompatibilityEnabled definido como false, configure o System.ServiceModel.Activation.ServiceHttpModule conforme mostrado no snippet de configuração a seguir.

<system.serviceModel>  
    <serviceHostingEnvironment aspNetCompatibilityEnabled="false" />
  </system.serviceModel>  
  <system.webServer>  
    <modules>  
      <remove name="ServiceModel"/>  
      <add name="ServiceModel"
           preCondition="integratedMode,runtimeVersionv2.0"
           type="System.ServiceModel.Activation.ServiceHttpModule, System.ServiceModel,Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>  
    </modules>  
    </system.webServer>  

Se você tiver aspNetCompatibilityEnabled definido como true, configure o System.ServiceModel.Activation.ServiceHttpHandlerFactory conforme mostrado no snippet de configuração a seguir.

<system.serviceModel>  
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
  </system.serviceModel>  
  <system.webServer>  
    <handlers>  
          <clear/>  
          <add name="TestAsyncHttpHandler"
               path="*.svc"
               verb="*"
               type="System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
               />  
    </handlers>
  </system.webServer>  

Confira também