Estamos vendo enormes problemas de desempenho em um aplicativo da Web e estamos tentando encontrar o gargalo. Eu não sou um administrador de sistemas, então há algumas coisas que eu não entendo muito bem. Algumas investigações básicas mostram que a CPU está ociosa, muita memória disponível, sem troca, sem E/S, mas com uma carga média alta.
A pilha de software neste servidor se parece com isso:
- Solaris 10
- Java 1.6
- WebLogic 10.3.5 (8 domínios)
Os aplicativos executados neste servidor conversam com um banco de dados Oracle em um servidor diferente.
Este servidor tem 32 GB de RAM e 10 CPUs (eu acho).
Running prstat -Z
dá algo assim:
PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/NLWP
3836 ducm0101 2119M 2074M cpu348 58 0 8:41:56 0.5% java/225
24196 ducm0101 1974M 1910M sleep 59 0 4:04:33 0.4% java/209
6765 ducm0102 1580M 1513M cpu330 1 0 1:21:48 0.1% java/291
16922 ducm0102 2115M 1961M sleep 58 0 6:37:08 0.0% java/193
18048 root 3048K 2440K sleep 59 0 0:06:02 0.0% sa_comm/4
26619 ducm0101 2588M 2368M sleep 59 0 8:21:17 0.0% java/231
19904 ducm0104 1713M 1390M sleep 59 0 1:15:29 0.0% java/151
27809 ducm0102 1547M 1426M sleep 59 0 0:38:19 0.0% java/186
2409 root 15M 11M sleep 59 0 0:00:00 0.0% pkgserv/3
27204 root 58M 54M sleep 59 0 9:11:38 0.0% stat_daemon/1
27256 root 12M 8312K sleep 59 0 7:16:40 0.0% kux_vmstat/1
29367 root 297M 286M sleep 59 0 11:02:13 0.0% dsmc/2
22128 root 13M 6768K sleep 59 0 0:10:51 0.0% sendmail/1
22133 smmsp 13M 1144K sleep 59 0 0:01:22 0.0% sendmail/1
22003 root 5896K 240K sleep 59 0 0:00:01 0.0% automountd/2
22074 root 4776K 1992K sleep 59 0 0:00:19 0.0% sshd/1
22005 root 6184K 2728K sleep 59 0 0:00:31 0.0% automountd/2
27201 root 6248K 344K sleep 59 0 0:00:01 0.0% mount_stat/1
20964 root 2912K 160K sleep 59 0 0:00:01 0.0% ttymon/1
20947 root 1784K 864K sleep 59 0 0:02:22 0.0% utmpd/1
20900 root 3048K 608K sleep 59 0 0:00:03 0.0% ttymon/1
20979 root 77M 18M sleep 59 0 0:14:13 0.0% inetd/4
20849 daemon 2856K 864K sleep 59 0 0:00:03 0.0% lockd/2
17794 root 80M 1232K sleep 59 0 0:06:19 0.0% svc.startd/12
17645 root 3080K 728K sleep 59 0 0:00:12 0.0% init/1
17849 root 13M 6800K sleep 59 0 0:13:04 0.0% svc.configd/15
20213 root 84M 81M sleep 59 0 0:47:17 0.0% nscd/46
20871 root 2568K 600K sleep 59 0 0:00:04 0.0% sac/1
3683 ducm0101 1904K 1640K sleep 56 0 0:00:00 0.0% startWebLogic.s/1
23937 ducm0101 1904K 1640K sleep 59 0 0:00:00 0.0% startWebLogic.s/1
20766 daemon 5328K 1536K sleep 59 0 0:00:36 0.0% nfsmapid/3
20141 daemon 5968K 3520K sleep 59 0 0:01:14 0.0% kcfd/4
20093 ducm0101 2000K 376K sleep 59 0 0:00:01 0.0% pfksh/1
20797 daemon 3256K 240K sleep 59 0 0:00:01 0.0% statd/1
6181 root 4864K 2872K sleep 59 0 0:01:34 0.0% syslogd/17
7220 ducm0104 1268M 1101M sleep 59 0 0:36:35 0.0% java/138
27597 ducm0102 1904K 1640K sleep 59 0 0:00:00 0.0% startWebLogic.s/1
27867 root 37M 4568K sleep 59 0 0:13:56 0.0% kcawd/7
12685 ducm0101 4080K 208K sleep 59 0 0:00:01 0.0% vncconfig/1
ZONEID NPROC SWAP RSS MEMORY TIME CPU ZONE
42 135 22G 19G 59% 87:27:59 1.2% dsuniucm01
Total: 135 processes, 3167 lwps, load averages: 54.48, 62.50, 63.11
Eu entendo que a CPU está principalmente ociosa, mas a média de carga é alta, o que é bastante estranho para mim. A memória não parece ser um problema.
Running vmstat 15
dá algo assim:
kthr memory page disk faults cpu
r b w swap free re mf pi po fr de sr s0 s1 s4 sd in sy cs us sy id
0 0 0 32531400 105702272 317 1052 126 0 0 0 0 13 13 -0 8 9602 107680 10964 1 1 98
0 0 0 15053368 95930224 411 2323 0 0 0 0 0 0 0 0 0 23207 47679 29958 3 2 95
0 0 0 14498568 95801960 3072 3583 0 2 2 0 0 3 3 0 21 22648 66367 28587 4 4 92
0 0 0 14343008 95656752 3080 2857 0 0 0 0 0 3 3 0 18 22338 44374 29085 3 4 94
0 0 0 14646016 95485472 1726 3306 0 0 0 0 0 0 0 0 0 24702 47499 33034 3 3 94
Eu entendo que a CPU está quase ociosa, nenhum processo está esperando na fila para ser executado, pouca troca está acontecendo.
Correr iostat 15
dá isso:
tty sd0 sd1 sd4 ssd0 cpu
tin tout kps tps serv kps tps serv kps tps serv kps tps serv us sy wt id
0 676 324 13 8 322 13 8 0 0 0 159 8 0 1 1 0 98
1 1385 0 0 0 0 0 0 0 0 0 0 0 0 3 4 0 94
0 584 89 6 24 89 6 25 0 0 0 332 19 0 2 1 0 97
0 296 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 97
1 1290 43 5 24 43 5 22 0 0 0 297 20 1 3 3 0 94
A execução netstat -i 15
fornece o seguinte:
input aggr26 output input (Total) output
packets errs packets errs colls packets errs packets errs colls
1500233798 0 1489316495 0 0 3608008314 0 3586173708 0 0
10646 0 10234 0 0 26206 0 25382 0 0
11227 0 10670 0 0 28562 0 27448 0 0
10353 0 9998 0 0 29117 0 28418 0 0
11443 0 12003 0 0 30385 0 31494 0 0
o que estou perdendo?
Com algumas investigações adicionais, parece que o problema de desempenho é principalmente devido a um alto número de chamadas de rede entre dois sistemas (Oracle SSXA e UCM). As chamadas são rápidas, mas abundantes e serializadas, daí o baixo uso da CPU (principalmente aguardando E/S), a alta média de carga (muitas chamadas aguardando para serem processadas) e principalmente os longos tempos de resposta (por acúmulo de pequenos tempos de resposta).
Obrigado pela sua visão sobre este problema!
Quando você diz 'média de carga alta', suponho que você queira dizer que prstat mostra 'média de carga' na parte inferior dos números de saída de
Esses números são semelhantes aos que o top fornece e provavelmente significam o tamanho médio da fila do processo em execução. Esta não é a porcentagem de tempo do processador sendo usado, mas quantas 'coisas' estão assediando a CPU pelo tempo de execução. É certo que eles parecem bastante altos, mas tudo depende do aplicativo que você está executando; os processos podem não estar fazendo muita coisa assim que obtêm seu slot. Veja aqui uma boa explicação sobre top.
Não estou familiarizado com o WebLogic, mas notei que, geralmente, com o Apache Tomcat, muitos threads Java podem ser gerados simultaneamente para o que parece não ter muitas solicitações. Pode ser isso que está causando esses altos números de carga média. Certifique-se de estar usando pool de conexões onde apropriado para se conectar ao back-end e considere aumentar o número de threads ociosos disponíveis para seu aplicativo para lidar com conexões (não tenho certeza de como fazer isso no WebLogic; o Tomcat tem um pool de threads por conector ou um pool de threads de executor geral). Se você não fizer isso, novos threads podem estar sendo gerados para processar solicitações.
Quanto ao desempenho, você precisa definir qual parte do seu aplicativo está sofrendo. É o processamento que está acontecendo no lado WebLogic/Java das coisas, o acesso ao banco de dados, pesquisas de DNS (se estão sendo feitas por algum motivo ...), problemas de rede ou algo no sistema operacional.
99% do tempo será o seu código e como ele fala com o banco de dados que está segurando as coisas. Em seguida, será a configuração do aplicativo da web. Após este ponto, você estará trabalhando para extrair os últimos milissegundos do seu aplicativo ou procurando fornecer maior simultaneidade com o mesmo hardware. Para esse ajuste de desempenho mais refinado, você precisa de métricas.
Para Java, sugiro instalar o Java Melody . Ele pode fornecer muitas informações sobre o que seu programa está fazendo e ajudar a diminuir onde ele está gastando tempo. Eu usei apenas com o Tomcat, mas deve funcionar bem com qualquer coisa de contêiner/servlet Java EE.
Existem várias maneiras de ajustar o Java, então dê uma olhada em suas diretrizes de desempenho (tenho certeza que você provavelmente tem) e verifique se você está configurando o tamanho de heap correto etc. adequado para o seu programa. O Java Melody pode ajudá-lo a rastrear o tamanho do heap do Java que você está consumindo, bem como o quanto o coletor de lixo está trabalhando/com que frequência ele está interrompendo seu programa para limpar objetos.
Espero que tenha sido útil. Se você fornecer mais informações, talvez eu possa atualizar esta resposta e aprimorá-la de acordo com suas necessidades.
Como uma nota lateral, a média de carga também inclui coisas esperando por atividade de disco (ou seja, assediando o disco), bem como aquelas esperando por cpu, é uma soma de ambos ... então você pode ter problemas em um ou outro.
Veja http://en.wikipedia.org/wiki/Load_(computing) "Linux também inclui [em sua média de carga] processos em estados de suspensão ininterruptos (geralmente aguardando atividade de disco)"
Como uma observação lateral, o problema específico que encontrei foi que eu tinha alta média de carga, mas também muita CPU ociosa e baixo uso de disco.
Parece que, pelo menos no meu caso, às vezes os threads/processos que aguardam E/S aparecem na média de carga, mas não causam um aumento na coluna "await". Mas eles ainda são limitados por E/S.
Você pode dizer que este é o caso com o código a seguir, se você executá-lo em jruby (apenas 100 threads com muita E/S cada):
O que fornece uma saída superior como esta:
Então você pode ver que ele tem muita CPU ociosa, 0,0%wa, mas uma média de carga muito alta.
iostat da mesma forma mostra o disco como basicamente ocioso:
veja também http://linuxgazette.net/141/misc/lg/tracking_load_average_issues.html
Como uma observação adicional, isso também parece implicar que (pelo menos neste caso - executando o CentOS) a média de carga inclui cada thread separadamente no total.
Teve o mesmo problema hoje. Após algumas pesquisas e diagnósticos percebi que meu pequeno VPS estava ficando sem disco .
No tipo shell/prompt (Linux/Unix)
para ver o disco livre em sua máquina. Se você estiver ficando sem disco, esse pode ser o problema/questão.
Outra ferramenta útil que ajudará nessa situação é o nmon.
Inclui uma variedade de maneiras de visualizar os mesmos dados apresentados pelas outras ferramentas, em um pequeno pacote.
Se este for um conteúdo que não pode ser armazenado em cache, recomendo colocar vários servidores atrás de um balanceador de carga, como haproxy no modo tcp, para distribuir a carga.
Apenas para adicionar a isso, algumas ferramentas específicas do Solaris que não foram mencionadas e que são úteis na depuração de tais problemas são "intrstat", "mpstat" e "lockstat". Tendo experimentado um problema semelhante antes em um host executando algumas cargas pesadas de ETL, o mpstat revelou uma grande quantidade de interrupções lidando com muitas E/S que indicavam o problema.
Na época, em um T4-4 com mpstat, vimos vcpus entregando mais de 30.000 interrupções em um curto ciclo de monitoramento, após o qual o desempenho começou a sofrer. Nesse caso, a única solução alternativa foi usar mais CPU, no entanto, o trabalho foi realizado posteriormente para melhorar o código.
Brendan Gregg escreveu muito sobre desempenho, principalmente sobre E/S ao longo dos anos, e vale a pena pesquisar se você quiser saber mais.