AlwaysOn Availability Group em Cluster MultiSubnet - Erros de conexão e Paramêtros importantes relacionados ao Listener
Trabalhando com diversos clientes, percebo que muitos desenvolvedores tem dúvidas de como configurar uma string de conexão usando o SQL Server AlwaysOn Availability Group Listener em um cluster Multi Subnet. É interessante que essa é uma dúvida bem comum e, em diversos clientes percebi a necessidade de direcionar para a solução. Resolvi escrever este artigo já que percebo que não há muita informação sobre isso em português.
Num cluster local, o qual involve, geralmente, apenas um único endereço TCP IP para o Availability Group Listener, não há a necessidade de nenhuma mudança. O cliente irá apontar para o endereço IP do Listener ou o nome deste Listener (DNS Name) e a conexão ocorrerá com sucesso. Porém quando o Availbility Group involve mais de uma Subnet, onde há geralmente dois IPs associados, um para cada Subnet, o cliente então precisará utilizar o nome do Listener para garantir a transparência para a aplicação em caso de Failover. Se o desenvolvedor utilizar uma string de conexão sem os parâmetros corretos, suas conexões recebem erros de timeout e você provavelmente percebe que é um problema intermitente e não necessariamente para todas as conexões.
Bem, vamos tentar explicar o porque isso acontece.
Por padrão, quando um Availability Group Listener é criado, há uma opção chamada RegisterAllProvidersIP que é configurada com o valor 1 (True). Esta configuração é associada ao recurso Network Name (vinculado ao Listener) no Failover Cluster Manager. Isso significa que os endereços IP de ambas as localidades (Subnet 1 e 2) irão ser adicionados ao registro DNS do cliente (DNS A-record). Quando o cliente tenta acessar o Availability Group através do Listener ele, arbitrariamente ou ramdomicamente (se existisse essa palavra, hehe), tenta conectar a um dos dois endereços IP associados. Numa lógica rápida então, poderíamos dizer que aproximadamente 50% de todas os acessos irão receber erros de timeout e, por isso que você percebe que algumas conexões ocorrem com sucesso. A solução mais elegante e a que eu recomendo é a de utilizar um paramêtro adicional na string de conexão das suas aplicações. Este parâmetro se chama MultiSubnetFailover.
Explicando de forma simples, quando o cliente tenta acessar o AG através do Listener, com a opção MultiSubnetFailover ao invés de acessar um IP de forma arbitrário, o cliente realiza acesso simultaneo aos IP associados ao AG Listener (dependendo da forma que a conexão é feita ele pode simplesmente forçar o retry da conexão a ocorrer de forma mais rápida). O IP que responder é o que o cliente/aplicação irá utilizar. Esta é uma forma de acesso mais precisa e na minha conclusão irei dar mais alguns detalhes do porque esta opção é preferível comparada a uma outra opção disponível que irei comentar a seguir.
Ah! Mais um detalhe, para aplicações que fazem usam de drivers ao invés de conexões diretas através de string de conexão, o driver SQL Native Client, a partir da versão 11, suporta esta opção (MultiSubnetCluster)
RegisterAllProvidersIP + HostRecordTTL
Infelizmente, Há aplicações que não suportam a opção MultiSubnetFailover, por diversos motivos (uma aplicação legacy ou é aquela famosa caixinha fechada a qual a empresa que desenvolveu não existe mais ou não é favorável a fazer mudanças). Nesse caso você pode recorrer a mudanças nos parâmetros RegisterAllProvidersIP e HostRecordTTL.
Mudando a configuração RegisterAllProvidersIP para 0, o único IP que estiver Online será o IP registrado junto ao DNS do cliente. Há apenas uma consideração aqui que nos leva a falar do próximo parâmetro a ser alterado, o HostRecordTTL. Quando um failover ocorre entre instâncias de diferentes Subnets, as configurações de DNS podem impactar diretamente a conectividade das aplicações. Há uma propriedade relacionada ao DNS conhecida como TTL ou Time to Live, de forma simples podemos dizer que ela é responsável por dizer de quanto em quanto tempo o registro DNS de cada cliente será atualizado. Se o Listener mudar o endereço IP em que ele está respondendo (no caso de um Failover do AG entre Subnets distintas) isso não afeta diretamente na atualização do registro DNS do cliente, o que pode fazer com que ele ainda tente acessar o Availability Group utilizando o endereço TCP IP anterior (o IP utilizado na Subnet 1, por exemplo). Quando a replicação dos registros DNS ocorre para a máquina do cliente então, todos os registros são atualizados e seus clientes poderão utilizar o endereço IP correto (utilizado na Subnet 2).
Por padrão, essa atualização/replicação ocorre a cada 20 minutos, o que significa que você poderia ficar aguardando até 20 minutos para ser possível conectar com sucesso ao AG utilizando o Listener's Name. Para que essa replicação ocorra num tempo menor, é possível reduzir o parâmetro TTL, forçando essa atualização a ocorrer de forma mais frequente. Se você pesquisar em algumas documentações da Microsoft é recomendável diminuir esse parâmetro para, no mínimo, 5 minutos (ou 300 segundos - a configuração é em segundos), mas segundo a minha experiência e de acordo com a sua necessidade de negócios da sua empresa, você pode alterar até para um valor menor, talvez algo entre 2 e 3 minutos (120-180 segundos). Claro que quanto menor o valor para a configuração HostRecordTTL existe um leve aumento no tráfego da sua rede, devido a requisição constante de registros DNS.
Lembrando que essas configurações de HostRecordTTL e RegisterAllProvidersIP são feitas diretamente no recurso do Listener no Failover Cluster Manager, não no Active Directory ou no DNS, apesar de estarem relacionados. O time de AlwaysOn da Microsoft tem um artigo bem bacana sobre essas opções, incluindo um script Powershell que pode te ajudar a mudar essas configurações de forma mais simples e rápida.
Conclusão
Apesar de a opção de mudar os parâmetros RegisterAllProvidersIP e HostRecordTTL ser uma solução interessante para clientes que não possuem suporte a opção MultiSubnetFailover, o parâmetro MultiSubnetFailover é, sem dúvida, a melhor forma de acessar seu AG em um cluster Multi-Subnet através do Listener. Além de ser mais preciso, pois quando o cliente tenta acessar o AG através do Listener não irá acessar obrigatóriamente um IP aleatório, podemos evitar erros de timeout causados pela latência na replicação dos registros DNS devido as propriedades de TTL.
Espero poder trazer mais dicas e explicações focadas em Alta Disponibilidade em breve.
Até lá!
Um abraço,
Thiago Caserta.