Servidores Indy - Modelo de Threads (1 / 3)

· Recursos

Os servidores Indy usam threads para gerenciar as conexões dos clientes. Toda vez que um novo cliente se conecta ao servidor, uma nova thread é criada para gerenciar essa conexão. Portanto, se você tiver 100 conexões, haverá 100 threads. Além disso, o Indy usa sockets bloqueantes, o que significa que ao ler ou escrever, a função não retorna até que a operação seja concluída.

Esse modelo tem algumas vantagens, como ser fácil de programar, pois o código é processado sequencialmente. Porém, como desvantagem, se o número de conexões aumentar, o desempenho piora progressivamente devido à troca de contexto de threads. A troca de contexto é o processo de armazenar o estado de uma thread para que ela possa ser restaurada e retomar a execução posteriormente. A troca rápida de contexto entre threads é custosa em termos de utilização de CPU. Se você criar 1000 conexões em um servidor, verá que a CPU está trabalhando mesmo sem nenhuma troca de dados — esse uso de CPU se deve à troca de contexto de threads.

Alternativas ao Modelo Indy 

Em vez de usar 1 thread por conexão, existem alternativas como IOCP (para Windows) ou EPOLL (para Linux), que utilizam um pool de threads para gerenciar as conexões e usam sockets não bloqueantes. Esse modelo é muito mais eficiente quando o número de conexões simultâneas é alto e escala muito melhor do que o modelo padrão de threads do Indy.

IOCP (Windows) 

As portas de conclusão de E/S fornecem um modelo de threading eficiente para processar múltiplas requisições de E/S assíncronas em um sistema multiprocessador. Quando um processo cria uma porta de conclusão de E/S, o sistema cria um objeto de fila associado para threads cujo único propósito é atender essas requisições. Processos que lidam com muitas requisições de E/S assíncronas simultâneas podem fazê-lo de forma mais rápida e eficiente usando portas de conclusão de E/S em conjunto com um pool de threads pré-alocado, em vez de criar threads no momento em que recebem uma requisição de E/S.

O modelo IOCP usa sockets não bloqueantes; em vez de usar Select, utiliza a função AcceptEx e um pool de threads para gerenciar as conexões dos clientes.

Para habilitar o IOCP no servidor Indy do sgcWebSockets, veja o código abaixo:

oServer := TsgcWebSocketHTTPServer.Create(nil);
oServer.NotifyEvents := neNOSync;
oServer.IOHandlerOptions.IOHandlerType := iohIOCP;
oServer.Active := True; 

Um novo servidor WebSocket + HTTP será criado e um pool de threads gerenciará as conexões. O número de threads utilizadas dependerá do número de CPUs do servidor.

EPOLL (Linux) 

O Epoll é uma chamada de sistema do kernel Linux para um mecanismo escalável de notificação de eventos de E/S, introduzido pela primeira vez na versão 2.5.44 do kernel Linux. Sua função é monitorar múltiplos descritores de arquivo para verificar se é possível realizar E/S em algum deles. Ele foi criado para substituir as chamadas de sistema POSIX select e poll mais antigas, a fim de obter melhor desempenho em aplicações mais exigentes, onde o número de descritores de arquivo monitorados é grande.

Confira a tabela a seguir comparando o desempenho para 100.000 operações de monitoramento:

Núm. de Operações poll select epoll
10 0.61 0.73 0.41
1002.93.00.42
100035350.53
100009909300.66

Portanto, usar o epoll é muito mais rápido quando você tem mais de 10 descritores de arquivo para monitorar.

O modelo EPOLL usa sockets não bloqueantes; em vez de usar Select, utiliza a função Accept assíncrona e um pool de threads para gerenciar as conexões dos clientes.

Para habilitar o EPOLL no servidor Indy do sgcWebSockets, veja o código abaixo:

oServer := TsgcWebSocketHTTPServer.Create(nil);
oServer.NotifyEvents := neNOSync;
oServer.IOHandlerOptions.IOHandlerType := iohEPOLL;
oServer.Active := True;