Armazenar informações sobre o estado de sessão numa aplicação Web ASP.NET

Concluído

O protocolo HTTP que as aplicações Web utilizam não tem estado. Muitos aplicativos Web precisam manter informações de estado entre as solicitações para fornecer algum contexto para essas solicitações. Este contexto denomina-se sessão. Pode guardar as informações do estado para uma sessão de várias maneiras, mas algumas são mais adequadas do que outras. O que é adequado depende do ambiente em que a aplicação Web está a ser executada.

Opções para armazenar o estado de sessão

Em um aplicativo Web ASP.NET que depende de sessões, é importante usar um provedor de estado de sessão apropriado. O provedor de estado de sessão é responsável por persistir e manter o estado de cada sessão de usuário. Se um aplicativo Web se destina a suportar muitas centenas de milhares de usuários simultâneos, o provedor de estado de sessão deve oferecer suporte a sessões separadas e privadas para cada usuário.

Normalmente, é o servidor Web que gere as informações sobre a sessão. Os dados da sessão são, muitas vezes, apenas uma coleção de pares chave-valor. Cada sessão tem um identificador exclusivo.

Quando um cliente se conecta a um aplicativo Web e inicia uma nova sessão, o servidor gera um identificador de sessão e o passa de volta para o cliente como parte da mensagem de resposta HTTP. Esse identificador normalmente é retornado na forma de um cookie que o navegador da Web ou o aplicativo cliente pode salvar. Todos os pedidos subsequentes podem incluir este cookie como parte do pedido para que a aplicação Web saiba a que sessão pertence cada pedido.

Diagram showing the relationships between client apps, the web app running on the web server, and session state information identified by using cookies.

No servidor Web, os dados de sessão podem ser armazenados na memória, num ficheiro de disco, numa localização partilhada como o armazenamento da Tabela do Azure ou numa base de dados de qualquer tipo.

A retenção de dados de sessão na memória garante um acesso rápido, mas afeta a escalabilidade horizontal. Se o aplicativo Web for hospedado por vários servidores atuando como uma web farm ou como parte de uma implantação multirregião, todas as solicitações de um cliente que especificar um cookie específico deverão ser direcionadas para o mesmo servidor. Esta situação resulta em sessões temporárias.

É possível que este nível de afinidade cliente/servidor faça com que alguns servidores fiquem sobrecarregados enquanto outros são utilizados menos vezes. Além disso, se o servidor falhar, as informações de estado serão perdidas.

Salvar dados de sessão em um arquivo reduz as chances de perda de dados de sessão, mas pode ter problemas semelhantes se o arquivo for armazenado no sistema de arquivos local de um servidor. A afinidade cliente/servidor ainda é um problema. Se o servidor Web falhar, as informações de estado da sessão ficarão indisponíveis até que o servidor tenha sido recuperado.

A abordagem mais dimensionável consiste na escrita de dados de sessão num arquivo de dados partilhado ao qual todos os servidores possam aceder. Esta abordagem não só melhora o balanceamento de carga dos pedidos nos servidores, mas também garante a disponibilidade do estado de sessão se um servidor Web individual falhar.

Se estiver a utilizar o Azure, pode utilizar o armazenamento de Tabelas, a Base de Dados SQL do Azure ou um serviço como a Cache do Azure para Redis. O Redis é um serviço de colocação em cache altamente otimizado e concebido para armazenar pares chave-valor. Destas opções, a Cache do Azure para Redis proporciona o desempenho mais próximo do proporcionado quando se guarda sessões na memória.

Configurando um provedor de estado de sessão em um aplicativo Web ASP.NET

Um provedor de estado de sessão gerencia o estado da sessão em um aplicativo Web ASP.NET. O provedor de estado de sessão organiza os dados da sessão para cada cliente, lida com o tempo de vida dos dados da sessão (garantindo que eles sejam removidos quando uma sessão expira) e mantém a privacidade. Os dados da sessão geralmente são criptografados e não devem ser compartilhados entre usuários diferentes.

Em um aplicativo Web ASP.NET, você pode configurar um provedor de estado de sessão usando a <seção sessionState> do arquivo web.config. A <tag sessionState> especifica o provedor de sessão. Cada provedor é configurado em sua própria <seção de provedores> , que contém configurações específicas do provedor.

O provedor de estado de sessão padrão para ASP.NET opera na memória e não requer um provedor separado. A configuração assemelha-se à seguinte:

<configuration>
  ...
  <system.web>
    ...
    <sessionState mode="InProc" />
    ...
  </system.web>
  ...
</configuration>

Para usar um provedor diferente, defina o modo como Personalizado no <elemento sessionState> e adicione o pacote NuGet que contém o provedor ao seu aplicativo Web. Em seguida, modifique a seção sessionState> do <arquivo web.config para fazer referência ao provedor e definir as configurações para o provedor.

O exemplo seguinte mostra a configuração para o fornecedor de estado de sessão do Azure Cosmos DB. Este fornecedor escreve dados de sessão num contentor numa base de dados do Cosmos DB. Tem de especificar a base de dados e a coleção através dos parâmetros databaseId e collectionId.

<sessionState mode="Custom" customProvider="CosmosDBSessionStateProviderAsync">
  <providers>
    <add name="CosmosDBSessionStateProviderAsync" 
         cosmosDBEndPointSettingKey="[cosmosDBEndPointSetting]" 
         cosmosDBAuthKeySettingKey="[cosmosDBAuthKeySetting]" 
         databaseId="[DataBaseId]" 
         collectionId="[CollectionId]" 
         offerThroughput="5000" 
         connectionMode="Direct" 
         connectionProtocol="Tcp" 
         requestTimeout="5" 
         maxConnectionLimit="50" 
         maxRetryAttemptsOnThrottledRequests="10" 
         maxRetryWaitTimeInSeconds="10" 
         preferredLocations="" 
         partitionKey="" 
         partitionNumUsedByProvider="" 
         type="Microsoft.AspNet.SessionState.CosmosDBSessionStateProviderAsync, Microsoft.AspNet.SessionState.CosmosDBSessionStateProviderAsync, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  </providers>
</sessionState>

Você deve ter uma conta do Cosmos DB criada anteriormente. Em seguida, fornece o endereço do ponto final e a chave de autenticação nos parâmetros cosmosDBEndPointSettingKey e cosmosDBAuthKeySettingKey.

O segundo exemplo seguinte mostra a configuração do fornecedor da Cache do Azure para Redis. Mais uma vez, a instância da Cache do Azure para Redis já tem de existir.

<sessionState mode="Custom" customProvider="MySessionStateStore">
  <providers>
    <add name="MySessionStateStore"
         type="Microsoft.Web.Redis.RedisSessionStateProvider"
         host="[AzureCacheFirRedisEndpoint]"
         accessKey="[AccessKey]"
         ssl="true" />
  </providers>
</sessionState>

O endereço do ponto final a utilizar na definição do Nome do anfitrião encontra-se na página Descrição Geral da cache no portal do Azure:

Screenshot showing Azure Cache for Redis page in the Azure portal. The host name for the cache is highlighted.

Especifique AccessKey como sendo qualquer uma das chaves enumeradas na página Chaves de acesso do portal:

Screenshot showing the Access keys page for the cache in the Azure portal. The access keys are highlighted.

Muitos outros provedores que usam tecnologias diferentes para armazenar informações de estado de sessão estão disponíveis na Microsoft e em organizações parceiras.

Nota

A escolha do provedor de estado de sessão é transparente para o código do aplicativo. Você não precisará fazer alterações em seu aplicativo se mudar de provedor de estado de sessão.