Os mecanismos de servidor IOCP (Windows) e EPOLL (Linux) do sgcWebSockets lidam com milhares de conexões usando um pequeno conjunto de threads, em vez de uma thread por conexão, o que os torna a escolha certa para servidores sob carga concorrente intensa. Até agora, porém, eles não tinham como perceber um par que fica em silêncio sem se despedir. Duas novas opções, TCPKeepAlive e KeepAliveTimeout, fecham essa lacuna.
Um Par Silencioso Nunca Produz um Evento
IOCP e EPOLL são orientados a eventos: o mecanismo permanece inativo até que o sistema operacional o informe que um socket tem dados, foi fechado ou apresentou erro. Isso funciona bem até que um par desapareça sem enviar um FIN ou RST limpo, por exemplo um cliente que trava, um NAT ou firewall que descarta um mapeamento ocioso, ou uma rota que muda silenciosamente. Nenhum evento chega para esse socket, então a conexão permanece ESTABLISHED no servidor indefinidamente.
O IOHandler clássico de thread por conexão não tem esse problema, porque cada conexão bloqueia em uma leitura com tempo limite, de modo que uma conexão silenciosa é percebida e liberada na próxima vez que essa leitura expira. IOCP e EPOLL não tinham um mecanismo equivalente, que é exatamente o que essas duas novas opções acrescentam.
TCPKeepAlive: Deixe o Sistema Operacional Observar
Ative TCPKeepAlive e o próprio sistema operacional começa a sondar uma conexão assim que ela fica ociosa por Time segundos, repetindo a cada Interval segundos até que o par responda ou a conexão seja descartada. Está desativado por padrão; os valores abaixo correspondem aos padrões quando ativado.
Server.IOHandlerOptions.IOHandlerType := iohEPOLL;
Server.IOHandlerOptions.EPOLL.TCPKeepAlive.Enabled := True;
Server.IOHandlerOptions.EPOLL.TCPKeepAlive.Time := 60; // seconds idle before probing
Server.IOHandlerOptions.EPOLL.TCPKeepAlive.Interval := 10; // seconds between probes
Em um servidor Windows, as mesmas três propriedades ficam em IOHandlerOptions.IOCP.TCPKeepAlive.
KeepAliveTimeout: Um Tempo Limite de Ociosidade em Nível de Aplicação
KeepAliveTimeout adota uma abordagem diferente e mais direta: fecha qualquer conexão que tenha permanecido ociosa por mais tempo do que o número de segundos informado, independentemente do que as sondagens de keepalive do sistema operacional decidam. É o que mais se aproxima da forma como o IOHandler de thread por conexão já libera uma conexão silenciosa, está desativado por padrão (um valor 0), e apenas conexões realmente ociosas são afetadas, uma requisição sendo lida ou uma resposta sendo escrita nunca é interrompida por ele.
Server.IOHandlerOptions.EPOLL.KeepAliveTimeout := 120; // seconds
// Windows
Server.IOHandlerOptions.IOCP.KeepAliveTimeout := 120;
Defina-o com folga acima da sua requisição ou resposta mais lenta esperada, por exemplo 120 segundos para um servidor HTTP ou WebSocket típico, de modo que conexões genuinamente mortas sejam eliminadas rapidamente sem nunca afetar uma que esteja apenas lenta.
Uma Terceira Forma de Detectar uma Desconexão
O sgcWebSockets já oferecia duas formas de perceber que um par desapareceu: ativar CleanDisconnect em TsgcWebSocketClient, para que um cliente bem-comportado avise o servidor antes de sair, ou executar um heartbeat do lado do servidor que envia ping a cada cliente em um intervalo. Ambas dependem de cooperação, do cliente no primeiro caso, do seu próprio ciclo de ping/pong no segundo. TCPKeepAlive e KeepAliveTimeout são a primeira opção que não precisa de nada disso: o servidor detecta uma conexão morta totalmente por conta própria.
Disponibilidade
Ambas as opções já estão disponíveis no sgcWebSockets para Delphi e C++ Builder 7 a 13, em IOHandlerOptions.EPOLL e IOHandlerOptions.IOCP, ao lado das configurações existentes EPOLLThreads, IOCPThreads e WorkOpThreads. Estão desativadas por padrão, então nada muda em servidores existentes a menos que você as ative.
Baixe a versão de teste e leia a referência completa de IOCP e EPOLL na página do produto sgcWebSockets.
Dúvidas ou comentários? Entre em contato, você receberá uma resposta das pessoas que escreveram o código.
