Estou tentando entender os detalhes mais baixos dos servidores web. Gostaria de saber se um servidor, digamos o Apache, está pesquisando continuamente novas solicitações ou se funciona com algum tipo de sistema de interrupção. Se for uma interrupção, o que está causando a interrupção, é o driver da placa de rede?
networking
webserver
embedded
user2202911
fonte
fonte
Respostas:
A resposta curta é: algum tipo de sistema de interrupção. Essencialmente, eles usam E / S de bloqueio, o que significa que eles dormem (bloqueiam) enquanto aguardam novos dados.
O servidor cria um soquete de escuta e bloqueia enquanto aguarda novas conexões. Durante esse período, o kernel coloca o processo em um estado de suspensão interrompível e executa outros processos. Este é um ponto importante: fazer a pesquisa de processo continuamente desperdiçaria CPU. O kernel é capaz de usar os recursos do sistema com mais eficiência, bloqueando o processo até que haja trabalho para ele fazer.
Quando novos dados chegam à rede, a placa de rede emite uma interrupção.
Vendo que há uma interrupção na placa de rede, o kernel, através do driver da placa de rede, lê os novos dados da placa de rede e os armazena na memória. (Isso deve ser feito rapidamente e geralmente é tratado dentro do manipulador de interrupção.)
O kernel processa os dados recém-chegados e os associa a um soquete. Um processo bloqueado nesse soquete será marcado como executável, o que significa que agora está qualificado para execução. Não é necessariamente executado imediatamente (o kernel pode decidir executar outros processos ainda).
Quando quiser, o kernel ativará o processo bloqueado do servidor da web. (Como agora é executável.)
O processo do servidor da web continua executando como se não houvesse tempo. Sua chamada do sistema de bloqueio retorna e processa quaisquer novos dados. Então ... vá para o passo 1.
fonte
accept
. São (felizmente, ou seria totalmente péssimo!) Tarefas independentes, executadas de forma assíncrona. À medida que as conexões entram, elas são colocadas em uma fila de onde asaccept
puxam. Somente se não houver, ele bloqueia.Existem muitos detalhes "inferiores".
Primeiro, considere que o kernel possui uma lista de processos e, a qualquer momento, alguns desses processos estão em execução e outros não. O kernel permite a cada processo em execução uma fatia do tempo da CPU, depois o interrompe e passa para o próximo. Se não houver processos executáveis, o kernel provavelmente emitirá uma instrução como HLT para a CPU que suspenderá a CPU até que haja uma interrupção de hardware.
Em algum lugar do servidor, há uma chamada do sistema que diz "me dê algo para fazer". Existem duas grandes categorias de maneiras pelas quais isso pode ser feito. No caso do Apache, ele chama
accept
um soquete que o Apache abriu anteriormente, provavelmente escutando na porta 80. O kernel mantém uma fila de tentativas de conexão e adiciona a essa fila toda vez que um TCP SYN é recebido. Como o kernel sabe que um TCP SYN foi recebido depende do driver do dispositivo; para muitas placas de rede, provavelmente há uma interrupção de hardware quando os dados da rede são recebidos.accept
pede que o kernel retorne para mim a próxima iniciação de conexão. Se a fila não estava vazia,accept
apenas retorna imediatamente. Se a fila estiver vazia, o processo (Apache) será removido da lista de processos em execução. Quando uma conexão é iniciada posteriormente, o processo é retomado. Isso é chamado de "bloqueio", porque, para o processo que a chama,accept()
parece uma função que não retorna até ter um resultado, que pode levar algum tempo a partir de agora. Durante esse período, o processo não pode fazer mais nada.Uma vez
accept
retornado, o Apache sabe que alguém está tentando iniciar uma conexão. Em seguida, chama o fork para dividir o processo Apache em dois processos idênticos. Um desses processos continua a processar a solicitação HTTP, o outro chamaaccept
novamente para obter a próxima conexão. Portanto, sempre há um processo mestre que não faz nada além de chamaraccept
e gerar subprocessos e, em seguida, há um subprocesso para cada solicitação.Isso é uma simplificação: é possível fazer isso com threads em vez de processos, e também é possível com
fork
antecedência, para que haja um processo de trabalho pronto quando uma solicitação for recebida, reduzindo assim a sobrecarga da inicialização. Dependendo de como o Apache estiver configurado, ele poderá executar uma dessas ações.Essa é a primeira categoria ampla de como fazê-lo, e é chamado de bloqueio IO porque o sistema chama como
accept
eread
ewrite
que operam em sockets irá suspender o processo até que eles têm algo a voltar.A outra maneira ampla de fazer isso é chamada de E / S não-bloqueadora ou baseada em eventos ou assíncrona . Isso é implementado com chamadas do sistema como
select
ouepoll
. Cada um deles faz a mesma coisa: você fornece a eles uma lista de soquetes (ou, em geral, descritores de arquivos) e o que você quer fazer com eles, e o kernel bloqueia até que esteja pronto para fazer uma dessas coisas.Com este modelo, você pode dizer ao kernel (com
epoll
): "Diga-me quando houver uma nova conexão na porta 80 ou novos dados para ler em qualquer uma dessas 9471 outras conexões que eu abri".epoll
bloqueia até que uma dessas coisas esteja pronta, então você faz. Então você repete. Chama sistema comoaccept
eread
ewrite
nunca mais bloco, em parte porque sempre que você chamá-los,epoll
apenas lhe disse que eles estão prontos para que não haveria nenhuma razão para bloquear, e também porque quando você abre o soquete ou o arquivo que você especificar que você quer que eles no modo sem bloqueio, para que essas chamadas falhem emEWOULDBLOCK
vez de bloquear.A vantagem deste modelo é que você precisa de apenas um processo. Isso significa que você não precisa alocar estruturas de pilha e kernel para cada solicitação. O Nginx e o HAProxy usam esse modelo, e é uma grande razão pela qual eles podem lidar com muito mais conexões que o Apache em hardware semelhante.
fonte