EPOLL

Suportado por

 

TsgcWebSocketServer

TsgcWebSocketHTTPServer

 

*Requer a Edição Enterprise do sgcWebSockets.

 

EPOLL para Linux é uma API que permite tratar milhares de conexões usando um pool limitado de threads em vez de usar uma thread por conexão, como o Indy faz por padrão.

Para habilitar EPOLL para servidores Indy, vá até a propriedade IOHandlerOptions e selecione iohIEPOLL como IOHandler Type.


Server.IOHandlerOptions.IOHandlerType := iohEPOLL;
Server.IOHandlerOptions.EPOLL.EPOLLThreads := 0;
Server.IOHandlerOptions.EPOLL.WorkOpThreads := 0;
Server.IOHandlerOptions.EPOLL.PartialRequestTimeout := 0;
Server.IOHandlerOptions.EPOLL.TCPKeepAlive.Enabled := True;
Server.IOHandlerOptions.KeepAliveTimeout := 120;

 

EPOLLThreads são as threads utilizadas para requisições assíncronas EPOLL (operações sobrepostas/overlapped); por padrão o valor é zero, o que significa que o número de threads é calculado utilizando o número de processadores (exceto para Delphi 7 e 2007, onde o número de threads é definido como 32 porque a função cpucount não é suportada). Você pode ajustar o número de threads manualmente.

WorkOpThreads define o número mínimo de threads de trabalho mantidas prontas para processar requisições, 0 por padrão. Uma thread EPOLL apenas detecta que um socket está pronto e entrega o trabalho a este pool, de modo que ela nunca fica bloqueada por um cliente lento. O pool cresce sob demanda até um limite máximo fixo sempre que todas as threads de trabalho já estão ocupadas, portanto não é necessário dimensioná-lo com antecedência. Aumente este valor apenas se quiser que o pool já esteja aquecido antes da primeira requisição, o que evita o custo de criar threads durante uma rajada inicial de conexões.

Alterado na versão 2026.9.0. WorkOpThreads costumava fixar cada conexão em uma destas threads, de modo que todas as requisições de uma conexão eram executadas na mesma thread, e WorkOpRoundRobin escolhia como as novas conexões eram distribuídas entre elas. Essa fixação foi removida: uma conexão parada aguardando o restante de uma requisição bloqueava todas as outras conexões atribuídas à mesma thread, o que travava o servidor. As requisições de uma mesma conexão agora podem ser executadas em threads diferentes, portanto não se pode mais presumir que aquilo que é mantido por thread, como uma conexão de banco de dados ou um cache local da thread, acompanhe uma conexão. WorkOpRoundRobin não existe mais. Remova-o do seu código e, se você o habilitou no Object Inspector, apague também a linha WorkOpRoundRobin do .dfm do formulário; caso contrário, o formulário não carrega.

PartialRequestTimeout permite que o servidor aguarde o restante de um corpo de requisição HTTP cujo tamanho já é conhecido, em milissegundos e 0 por padrão, o que desabilita o recurso. Sem ele, um corpo de requisição que não chega por completo dentro de um único evento de prontidão, por exemplo um POST grande enviado em vários pacotes, é descartado silenciosamente e a conexão é encerrada sem resposta. A espera nunca é executada em uma thread EPOLL, que atende muitas conexões e nunca deve bloquear; ela é executada no pool de threads descrito acima, que cresce sob demanda até um limite máximo fixo, de modo que um cliente lento ou que não responde não consegue esgotá-lo nem prejudicar as demais conexões.

TCPKeepAlive permite que o sistema operacional sonde conexões ociosas e detecte um peer que desapareceu silenciosamente (desabilitado por padrão). Quando TCPKeepAlive.Enabled é definido como True, o S.O. começa a sondar uma conexão depois que ela permanece ociosa por TCPKeepAlive.Time segundos (60 por padrão), repetindo a cada TCPKeepAlive.Interval segundos (10 por padrão) até que o peer responda ou a conexão seja encerrada.

KeepAliveTimeout encerra qualquer conexão que tenha ficado ociosa por mais tempo do que o número de segundos informado (0 por padrão, o que significa desabilitado). Apenas conexões ociosas são afetadas; uma requisição que está sendo lida ou uma resposta que está sendo escrita nunca é interrompida por este timeout. Esta é a opção mais próxima de como o IOHandler padrão de uma thread por conexão libera uma conexão silenciosa, e não depende do sistema operacional nem de qualquer cooperação por parte do peer.

 

Habilitar o EPOLL para servidores Linux é recomendado quando você precisa tratar milhares de conexões. Se o seu servidor está tratando no máximo 100 conexões concorrentes, você pode permanecer com o modelo de threads padrão do Indy.

 

 

Evento OnDisconnect não disparado

 

O EPOLL funciona de forma diferente do IOHandler indy padrão. Com o IOHandler indy padrão, cada conexão é executada em uma thread, e essas threads ficam em execução o tempo todo verificando se a conexão está ativa, de modo que, se houver uma desconexão, ela é notificada em um curto período de tempo.

 

O EPOLL funciona de forma diferente, há um pool de threads que trata de todas as conexões, em vez de 1 thread = 1 conexão como o indy faz por padrão. Para EPOLL, a única maneira de detectar se uma conexão ainda está ativa é tentar escrever no socket; se houver algum erro, significa que a conexão está fechada. Há 3 opções para detectar desconexões:

 

1. Se você usar TsgcWebSocketClient, pode habilitá-lo na propriedade Options, CleanDisconnect := True (por padrão está desabilitado). Se estiver habilitado, antes de o cliente desconectar, ele envia uma mensagem informando o servidor sobre a desconexão, então o servidor receberá essa mensagem e o evento OnDisconnect será gerado.

2. Você pode habilitar o heartbeat no lado do servidor, por exemplo a cada 60 segundos, de modo que ele tentará enviar um ping a todos os clientes conectados e, se houver algum cliente desconectado, OnDisconnect será chamado.

3. Você pode habilitar TCPKeepAlive e/ou definir KeepAliveTimeout nas IOHandlerOptions do servidor. Isso permite que o próprio servidor detecte um peer que ficou silencioso, por exemplo porque o cliente travou ou a conexão de rede caiu sem enviar uma mensagem de fechamento, e feche a conexão, sem depender de o cliente enviar qualquer coisa.

 

Linux Connections Limit

 

Se você quiser aumentar o número de conexões abertas concorrentes, utilize o seguinte comando

 

ulimit -n 10000

 

O comando anterior define o número máximo de descritores de arquivos abertos como 10000