Você está aqui: Início > Produtos > Network Monitor (Pro) > Manual > Uso de sockets KEEPALIVE para evitar erros 10054

Uso de sockets KEEPALIVE para evitar erros 10054

by Vasiliy Ovchinnikov

Introdução

Nos sistemas com bancos InterBase ou Firebird, feitos para trabalhar em tempo real ou quase em tempo real, há o problema de acompanhar o status da conexão do cliente no servidor e de desconectar à força quando o cliente fica inacessível porque a conexão caiu.

É importante liberar logo os recursos ocupados por essas conexões fantasma, principalmente em servidores com arquitetura Classic. Se alguns usuários entram por uma conexão de modem instável, o risco de queda é alto.

Por exemplo, o cliente grava um conjunto de registros alterado e, depois do UPDATE (sem o COMMIT), a conexão cai.

Em geral, o aplicativo cliente reconecta ao servidor, mas o cliente (que continua trabalhando com os dados cuja gravação falhou por causa da queda) não consegue salvar as mudanças: recebe um conflito de bloqueio ("lock conflict on update"). A conexão anterior, que abriu a transação (na qual o UPDATE foi executado e o COMMIT não), ainda segura esses registros.

Quedas também acontecem na rede local, se o hardware (placas de rede, hubs, comutadores) está com defeito ou mal ajustado, e/ou por congestionamento. Nos logs do InterBase e do Firebird, falhas de conexão TCP aparecem como erro 10054 no Windows e 104 no Unix; falhas NetBEUI aparecem como erros 108/109.

Métodos de controle de conexões presas

No InterBase e no Firebird, os mecanismos de pacotes DUMMY ou de sockets KEEPALIVE acompanham e desativam essas conexões "mortas".

No InterBase 5.0 e posteriores, o mecanismo de pacotes DUMMY fica na camada de aplicação, entre o servidor InterBase/Firebird e a biblioteca cliente gds32/fbclient. Ele está no ibconfig/firebird.conf e não é o assunto deste artigo.

Nota

Pela experiência anterior, a estabilidade do mecanismo de pacotes dummy (o do InterBase 5.0, corrigido várias vezes no Firebird 1.5.x) depende muito do sistema do servidor e do cliente, das versões da pilha TCP e de outras condições. Na prática, a eficácia desse sistema numa rede real tende a zero.

Os sockets KEEPALIVE são um mecanismo mais interessante. Implementado no InterBase 6.0 e posteriores, serve para detectar queda de conexão. O KEEPALIVE é ativado pela opção de socket SO_KEEPALIVE na abertura. Não é preciso configurá-la à mão no Firebird 1.5 ou superior: ela já está no código do servidor Firebird, tanto no Classic quanto no Superserver.

No InterBase e no Firebird anteriores à 1.5, na variante Classic, é preciso um ajuste extra. Esse ajuste está descrito abaixo.

Nesse caso, a pilha TCP do sistema operacional (e não o servidor Firebird) passa a responder pelo status da conexão. Para o mecanismo funcionar, é preciso ajustar os parâmetros KEEPALIVE.

Descrição do KEEPALIVE

O comportamento dos sockets KEEPALIVE é controlado pelos parâmetros da tabela a seguir.

Parâmetro Descrição
KEEPALIVE_TIME Intervalo após o qual começam as sondas KEEPALIVE
KEEPALIVE_INTERVAL Intervalo entre as sondas KEEPALIVE
KEEPALIVE_PROBES Quantidade de sondas KEEPALIVE

A pilha TCP observa o momento em que os pacotes param de circular entre o cliente e o servidor e dispara o temporizador KEEPALIVE. Quando o temporizador chega a KEEPALIVE_TIME, a pilha TCP do servidor envia a primeira sonda KEEPALIVE. A sonda é um pacote vazio com a flag ACK, enviado ao usuário. Se o cliente está bem, a pilha TCP dele responde com um pacote ACK, e a pilha do servidor zera o temporizador KEEPALIVE ao receber a resposta.

Se o cliente não responde à sonda, o servidor continua enviando sondas. A quantidade é o valor de KEEPALIVE_PROBES, no intervalo KEEPALIVE_INTERVAL. Se o cliente não responde à última sonda, depois de mais um KEEPALIVE_INTERVAL a pilha TCP do sistema fecha a conexão, e o servidor (neste caso, a instância do InterBase ou do Firebird) libera os recursos daquela conexão.

Assim, uma conexão de cliente com falha é fechada depois deste intervalo:

KEEPALIVE_TIME+ ( KEEPALIVE_PROBES+1)* KEEPALIVE_INTERVAL.

Por padrão, os valores são grandes demais e o uso fica pouco eficaz. Por exemplo, o padrão de KEEPALIVE_TIME é "2 horas", no Linux e no Windows. Na prática, 1 ou 2 minutos bastam para decidir a desconexão forçada de um cliente inacessível. Por outro lado, o padrão do KEEPALIVE às vezes força desconexões em redes Windows que ficam inativas essas 2 horas (dá para questionar se essas conexões são necessárias no aplicativo, mas isso é outro assunto).

Abaixo está o ajuste desses parâmetros no Windows e no Linux.

Configuração do KEEPALIVE no Linux

No Linux, os parâmetros KEEPALIVE podem ser alterados editando o sistema de arquivos /proc ou chamando o sysctl.

No primeiro caso, edite estas linhas:

/proc/sys/net/ipv4/tcp_keepalive_time /proc/sys/net/ipv4/tcp_keepalive_intvl /proc/sys/net/ipv4/tcp_keepalive_probes

No segundo caso, execute estes comandos:

sysctl -w net.ipv4.tcp_keepalive_time=value sysctl -w net.ipv4.tcp_keepalive_intvl=value sysctl -w net.ipv4.tcp_keepalive_probes=value

O tempo é expresso em segundos.

Para aplicar esses parâmetros automaticamente na reinicialização do servidor, inclua o seguinte:

net.ipv4.tcp_keepalive_intvl = value net.ipv4.tcp_keepalive_time = value net.ipv4.tcp_keepalive_probes = value

Substitua a palavra <value> pelos valores necessários.

Se você usa o Firebird Classic anterior à 1.5, inclua o seguinte em /etc/xinet.d/firebird:

FLAGS=REUSE KEEPALIVE

Ajuste do KEEPALIVE no Windows 95/98/ME

Ramo do registro:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD\MSTCP

O ajuste de TCP está descrito aqui:

http://support.microsoft.com/default.aspx?scid=kb;en-us;158474

Parâmetros:

  • KeepAliveTime = milliseconds
    Type: DWORD
    No Windows 98, tipo STRING.
    Define o tempo de inatividade da conexão, em milissegundos.
    Quando esse tempo acaba, as sondas KEEPALIVE começam.
    O valor padrão é 2 horas (7200000).
  • KeepAliveInterval = 32-digit value
    Type: DWORD
    No Windows 98, tipo STRING.
    Define o tempo entre as sondas KEEPALIVE (em milissegundos).
    Quando o intervalo KeepAliveTime acaba,
    a cada KeepAliveInterval (em milissegundos)
    são enviadas sondas KEEPALIVE, no máximo
    MaxDataRetries. Se não houver resposta, a conexão
    é fechada. O valor padrão é 1 segundo (1000).
  • MaxDataRetries = 32-digit value
    Type: STRING
    Define a quantidade máxima de sondas KEEPALIVE.
    O valor padrão é 5.

Configuração do KEEPALIVE no Windows 2000/NT/XP

Ramo do registro:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\.

Ajuste de TCP:

XP: http://support.microsoft.com/kb/314053

O parâmetro MaxDataRetries é substituído por TCPMaxDataRetransmissions.

Os demais parâmetros têm os mesmos nomes do Windows 9x

Configuração do KEEPALIVE no Windows (para clientes)

Este ajuste é opcional, mas pode reduzir as mensagens de falha de conexão em canais instáveis. Inclua no ramo do registro:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

o parâmetro DisableDHCPMediaSense=1. A descrição está aqui:

https://support.microsoft.com/en-us/help/239924/how-to-disable-the-media-sensing-feature-for-tcp-ip-in-windows

Exemplo

Veja o ajuste do Firebird SQL Server 1.5.2 CS no Linux.

  • Confira se o mecanismo de pacotes DUMMY está desativado no firebird.conf
    (o parâmetro está comentado)
    .......
    #DummyPacketsInterval=0
    ......
  • Confira se existe o arquivo de configuração /etc/xinet.d/firebird

    Deixamos tudo como ficou na instalação. Não é preciso incluir nada.

  • Altere os parâmetros da pilha TCP:

    sysctl -w net.ipv4.tcp_keepalive_time = 15 sysctl -w net.ipv4.tcp_keepalive_intvl = 10 sysctl -w net.ipv4.tcp_keepalive_probes = 5

  • Conecte em qualquer banco do servidor a partir de um cliente da rede

  • Confira o tráfego no servidor com qualquer filtro de pacotes.

    Com os parâmetros em /proc/sys/net/tcp_keepalive_*, em até 15 segundos depois que o canal para, o servidor cria uma sonda. Se o cliente está "vivo", o servidor recebe um pacote de resposta. 15 segundos depois, a verificação se repete, e assim por diante.

  • Se o cliente é desligado fisicamente (o multiplexador ou o modem desliga de repente — tudo é possível), o servidor não recebe resposta e passa a enviar sondas a cada 10 segundos. Se o cliente não responde à quinta sonda, 10 segundos depois o processo do servidor encerra e libera recursos e bloqueios. Se o cliente dá algum sinal e responde pelo menos à quinta sonda (no pior caso), depois de mais 15 segundos de tempo limite o servidor volta a enviar sondas. E assim por diante.

Orientações

Para fechar, algumas orientações sobre como escolher os valores de KEEPALIVE.

Primeiro, defina o KEEPALIVE_TIME necessário. Quanto maior o valor, mais tarde começam as sondas KEEPALIVE. Se você vê o tempo todo erros 10054/104 no log do servidor e precisa apagá-los à mão, o recomendado é aumentar o KEEPALIVE_TIME.

Depois, KEEPALIVE_INTERVAL e KEEPALIVE_PROBES precisam atender à liberação antecipada das conexões já presas. Se os usuários entram por canais instáveis, provavelmente você vai querer mais sondas e um intervalo maior entre elas, para o usuário perceber a falha e reconectar. Se os clientes usam DSL ou acessam o servidor SQL pela rede local, dá para diminuir o intervalo entre as sondas KEEPALIVE.

Recomendação geral: se os clientes recebem muitas mensagens de erro ao salvar, por conflito de bloqueio, sem motivo aparente (não há conexões concorrentes nos mesmos dados), aumente a reação do sistema à liberação das conexões presas. Na prática, KEEPALIVE_TIME pode ser de 1 minuto ou mais. Estime o tempo da transação mais longa, para o tráfego não ficar sobrecarregado com verificações KEEPALIVE de conexões normais que abriram transações longas. KEEPALIVE_INTERVAL fica em 10 segundos ou mais, e KEEPALIVE_PROBES em 5 verificações ou mais. Com muitos usuários ao mesmo tempo, lembre que verificar com muita frequência pode aumentar bastante o tráfego da rede.

Lembre também que, se os usuários alteram dados em comum com frequência, erros de bloqueio vão ocorrer mesmo numa situação normal. Nesse caso, o aplicativo cliente precisa tratar o erro de bloqueio corretamente. Ao mesmo tempo, o aplicativo deve reduzir a ocorrência desses erros.

Exemplos de configuração padrão

Por fim, mais alguns exemplos de configuração padrão. O tempo de indisponibilidade é o período em que os usuários não conseguem atualizar dados (que naquele momento foram atualizados pela transação aberta pela conexão presa). O tempo total é o prazo após o qual a conexão presa é fechada.

  • Clientes usam conexão por modem; a maioria das transações do sistema é curta; a indisponibilidade fica limitada a 3 minutos:

    KEEPALIVE_TIME 1 minutes KEEPALIVE_PROBES 3 KEEPALIVE_INTERVAL 30 seconds TOTAL 3 minutes

  • Clientes usam a LAN; a maioria das transações do sistema é curta; a indisponibilidade fica limitada a 2 minutos:

    KEEPALIVE_TIME 30 sec KEEPALIVE_PROBES 5 KEEPALIVE_INTERVAL 10 sec TOTAL 90 seconds

  • Clientes usam qualquer conexão; a indisponibilidade não é limitada:

    KEEPALIVE_TIME12 minutes KEEPALIVE_PROBES 7 KEEPALIVE_INTERVAL 15 sec TOTAL 14 minutes

Esperamos que os exemplos bastem para ajustar corretamente o mecanismo KEEPALIVE da pilha TCP.

Fonte: