Estou procurando entender alguns problemas de desempenho do servidor que estou vendo com um servidor da Web (para nós) muito carregado. O ambiente é o seguinte:
- Debian Lenny (todos os pacotes estáveis + corrigidos para atualizações de segurança)
- Apache 2.2.9
- PHP 5.2.6
- Instância grande do Amazon EC2
O comportamento que observamos é que a Web normalmente se sente responsiva, mas com um pequeno atraso para começar a lidar com uma solicitação - às vezes uma fração de segundo, às vezes 2-3 segundos nos nossos horários de pico. A carga real no servidor está sendo relatada como muito alta - geralmente 10.xx ou 20.xx, conforme relatado por top
. Além disso, a execução de outras coisas no servidor durante esses períodos (pares vi
) é muito lenta, portanto a carga está definitivamente lá em cima. Curiosamente, o Apache permanece muito responsivo, além do atraso inicial.
Temos o Apache configurado da seguinte maneira, usando o prefork:
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 150
MaxRequestsPerChild 0
E KeepAlive como:
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
Observando a página de status do servidor, mesmo nesses momentos de carga pesada, raramente atingimos o limite do cliente, geralmente atendendo entre 80 a 100 solicitações e muitas daquelas no estado de manutenção de atividade. Isso me diz para descartar a lentidão inicial da solicitação como "aguardando um manipulador", mas posso estar errado.
O monitoramento CloudWatch da Amazon me diz que, mesmo quando nosso sistema operacional está relatando uma carga> 15, nossa utilização da CPU da instância está entre 75 e 80%.
Exemplo de saída de top
:
top - 15:47:06 up 31 days, 1:38, 8 users, load average: 11.46, 7.10, 6.56
Tasks: 221 total, 28 running, 193 sleeping, 0 stopped, 0 zombie
Cpu(s): 66.9%us, 22.1%sy, 0.0%ni, 2.6%id, 3.1%wa, 0.0%hi, 0.7%si, 4.5%st
Mem: 7871900k total, 7850624k used, 21276k free, 68728k buffers
Swap: 0k total, 0k used, 0k free, 3750664k cached
A maioria dos processos se parece com:
24720 www-data 15 0 202m 26m 4412 S 9 0.3 0:02.97 apache2
24530 www-data 15 0 212m 35m 4544 S 7 0.5 0:03.05 apache2
24846 www-data 15 0 209m 33m 4420 S 7 0.4 0:01.03 apache2
24083 www-data 15 0 211m 35m 4484 S 7 0.5 0:07.14 apache2
24615 www-data 15 0 212m 35m 4404 S 7 0.5 0:02.89 apache2
Exemplo de saída vmstat
ao mesmo tempo que o acima:
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
8 0 0 215084 68908 3774864 0 0 154 228 5 7 32 12 42 9
6 21 0 198948 68936 3775740 0 0 676 2363 4022 1047 56 16 9 15
23 0 0 169460 68936 3776356 0 0 432 1372 3762 835 76 21 0 0
23 1 0 140412 68936 3776648 0 0 280 0 3157 827 70 25 0 0
20 1 0 115892 68936 3776792 0 0 188 8 2802 532 68 24 0 0
6 1 0 133368 68936 3777780 0 0 752 71 3501 878 67 29 0 1
0 1 0 146656 68944 3778064 0 0 308 2052 3312 850 38 17 19 24
2 0 0 202104 68952 3778140 0 0 28 90 2617 700 44 13 33 5
9 0 0 188960 68956 3778200 0 0 8 0 2226 475 59 17 6 2
3 0 0 166364 68956 3778252 0 0 0 21 2288 386 65 19 1 0
E, finalmente, saída do Apache server-status
:
Server uptime: 31 days 2 hours 18 minutes 31 seconds
Total accesses: 60102946 - Total Traffic: 974.5 GB
CPU Usage: u209.62 s75.19 cu0 cs0 - .0106% CPU load
22.4 requests/sec - 380.3 kB/second - 17.0 kB/request
107 requests currently being processed, 6 idle workers
C.KKKW..KWWKKWKW.KKKCKK..KKK.KKKK.KK._WK.K.K.KKKKK.K.R.KK..C.C.K
K.C.K..WK_K..KKW_CK.WK..W.KKKWKCKCKW.W_KKKKK.KKWKKKW._KKK.CKK...
KK_KWKKKWKCKCWKK.KKKCK..........................................
................................................................
Da minha experiência limitada, tiro as seguintes conclusões / perguntas:
Podemos estar permitindo
KeepAlive
pedidos demaisEu vejo algum tempo gasto esperando E / S no vmstat, embora não seja consistente e nem muito (eu acho?), Por isso não tenho certeza se isso é uma grande preocupação ou não, tenho menos experiência com o vmstat
Também no vmstat, vejo em algumas iterações vários processos aguardando para serem atendidos, que é o que eu atribuo ao atraso inicial do carregamento da página em nosso servidor da Web, possivelmente erroneamente
Servimos uma mistura de conteúdo estático (75% ou superior) e conteúdo do script, e o conteúdo do script geralmente é bastante intensivo em processador, portanto, é importante encontrar o equilíbrio certo entre os dois; a longo prazo, queremos mudar a estática para outro lugar para otimizar os dois servidores, mas nosso software não está pronto para isso hoje
Fico feliz em fornecer informações adicionais, se alguém tiver alguma idéia, a outra observação é que esta é uma instalação de produção de alta disponibilidade, por isso tenho receio de fazer ajustes após ajustes, e é por isso que não brinquei com coisas como o KeepAlive
valor ainda.
fonte
Respostas:
Começarei admitindo que não gosto muito de executar coisas nas nuvens - mas com base na minha experiência em outro lugar, diria que essa configuração de servidor da web reflete um volume de tráfego bastante baixo. O fato de a fila de execução ser tão grande sugere que simplesmente não há CPU suficiente disponível para lidar com isso. O que mais há na fila de execução?
O KeepPlive ainda melhora o desempenho, os navegadores modernos são muito inteligentes em saber quando canalizar e quando executar solicitações em paralelo, embora um tempo limite de 5 segundos ainda seja bastante alto e você tenha MUITOS servidores aguardando - a menos que você ' Se você tiver grandes problemas de latência, recomendo aumentar para 2-3. Isso deve diminuir um pouco a fila de execução.
Se você ainda não possui o mod_deflate instalado no servidor da Web - recomendo que faça isso - e adicione o ob_gzhandler () aos seus scripts PHP. Você pode fazer isso como uma pré-adição automática:
(sim, a copressão usa mais CPU - mas você deve economizar a CPU em geral, tirando os servidores da fila de execução mais rapidamente / lidando com menos pacotes TCP - e, como bônus, seu site também é mais rápido).
Eu recomendo definir um limite superior no MaxRequestsPerChild - digamos algo como 500. Isso apenas permite alguma rotatividade nos processos, caso você tenha um vazamento de memória em algum lugar. Seus processos httpd parecem ENORMES - verifique se você removeu todos os módulos apache de que não precisa e verifique se está fornecendo conteúdo estático com boas informações de armazenamento em cache.
Se você ainda estiver tendo problemas, provavelmente o problema está no código PHP (se você usar o fastCGI, isso deve ser evidente sem grandes penalidades de desempenho).
atualizar
Se o conteúdo estático não variar muito entre as páginas, também vale a pena experimentar:
nos scripts PHP também.
fonte
Você deve considerar a instalação de um proxy reverso assíncrono, porque vários processos no estado W também são bastante altos. Seus processos Apache parecem gastar muito tempo enviando conteúdo para diminuir a velocidade de bloqueio de clientes na rede. O Nginx ou o lighttpd como interface para o servidor Apache pode reduzir drasticamente vários processos no estado W. E sim, você deve limitar uma série de solicitações de manutenção de atividade. Provavelmente vale a pena tentar desativar a manutenção de atividade.
BTW, 107 processos Apache são altos demais para 22 rps; pude atender 100-120 rps usando apenas 5 processos Apache. Provavelmente, o próximo passo é criar um perfil do seu aplicativo.
fonte
Você tem duas linhas em seu vmstat que mostram que o tempo de espera da CPU é bastante alto e, em torno delas, você faz um número razoável de gravações (io-bo) e alternância de contexto. Eu examinaria o que está escrevendo blocos e como eliminar essa espera. Eu acho que a maior melhoria pode ser encontrada na melhoria da IO do disco. Verifique syslog - defina-o para escrever assíncrono. Verifique se o cache de gravação do seu controlador está funcionando (verifique - você pode ter uma bateria com defeito).
O Keepalive não está causando seu problema de desempenho, economiza tempo na configuração da conexão se você não estiver executando um cache na frente. Você pode bater um pouco no MaxSpareServers para que, em uma crise, não esteja esperando todos os garfos.
fonte
considere desativar a manutenção de atividade como primeira tentativa ...
com 107 pedidos processados, manteria o MaxSpareServers superior ao que você definiu ...
IMHO a longo prazo nginx como proxy reverso para conteúdo estático deve ser levado em consideração
fonte
Primeira sugestão: desative os keepalives. Eu só precisei disso quando consegui identificar uma situação específica em que o desempenho aumentou, mas, em geral, as solicitações / s diminuíram com o Keepalive ativado.
Segunda sugestão: defina um MaxRequestsPerChild. Eu echo o symcbean aqui, ele ajudará na rolagem do processo no caso de um vazamento de memória. 500 é um bom ponto de partida.
Terceira sugestão: aumente o MaxClients. Um cálculo aproximado para isso é (memória física - memória usada pelo processo não httpd) / tamanho de cada processo httpd. Dependendo de como o httpd foi compilado, esse número chega a 255. Uso 250 nos meus servidores públicos para lidar com o rastreamento de sistemas do google / yahoo / MS.
Quarta sugestão: Aumente o MaxSpareServers: algo como 4-5x MinSpareServers.
Se essas sugestões falharem, eu examinaria o balanceamento de carga com proxy reverso ou memcache para DB.
fonte