Como escalar ainda mais (2+ MM de posts, +80 mil por mês)

Gostaria de aproveitar sua experiência sobre como continuar escalando nosso hardware.

Aqui estão nossos dados de referência:

2,2 milhões de posts crescendo atualmente ~80 mil por mês
35 mil usuários, crescendo ~1,5 mil por mês

Estamos rodando em uma VM Hetzner com 8 núcleos exclusivos e 32G de RAM. Começamos a ver limitações em dezembro com as conexões de worker do Nginx primeiro e as aumentamos de 768 padrão para 1536. Atingimos essa fronteira novamente ontem e as aumentamos para 3072 agora. Após essas mudanças, as coisas estão funcionando bem novamente, mas estamos perto de um limite de utilização de 100% do servidor.

db_work_mem está definido para 80MB, db_shared_buffers para 8192MB. Não estamos usando toda a memória disponível, mas não tenho certeza se há espaço para usar mais e obter benefícios. Opiniões?

#~\u003e free -m

              total        used        free      shared  buff/cache   available
Mem:          31360        6105        1241        8423       24013       16412

A próxima opção fácil de escalonamento com Hetzner seria 16 núcleos e 64 GB de RAM, o que é bom para nós em termos de custos, mas me pergunto se ainda faria sentido escalar verticalmente. Eu estava pensando se separar o aplicativo e o banco de dados em servidores diferentes não faria muito mais sentido ou se introduz muito mais dificuldades.

Quem já fez isso? Quais são suas experiências?

Por que você está buscando escalar? As métricas de tempo de resposta da sua API estão se degradando?

A qual recurso você está se referindo aqui? CPU? Espaço em disco? Memória?

2 curtidas

Quantas visualizações de página você está tendo?

Ignore todos os conselhos que você encontrar na internet e defina para 40-50% da sua memória.

Você pode compartilhar alguma saída do sar?

2 curtidas

Porque estou planejando com antecedência. Podemos não precisar escalar agora, mas olhando para o crescimento que vemos e a crescente necessidade de recursos que vimos no passado, estou apenas planejando com antecedência agora para pensar em possíveis próximos passos.

Principalmente CPU - após a atualização de hoje, estamos voltando de uma Carga de ~8-9 em horários de pico para o que parece ser ~6 agora.

12 milhões por mês, crescimento de 6,5 milhões por mês um ano atrás.

Voltarei à saída do sar mais tarde, não a estava executando.

Você vai querer investigar o que exatamente está usando essa CPU. Pode ser:

  • Trabalhadores da web Unicorn
  • PostgreSQL
  • Sidekiq, como trabalhos em segundo plano de otimização de imagem
  • Redis
  • nginx (improvável)

Dependendo do culpado, podemos sugerir maneiras de descarregar isso.

5 curtidas

Olhando o tempo de CPU, eu diria que são principalmente workers do unicorn:

1 curtida

Talvez abandonar a coisa da CPU dedicada e usar esta oferta aqui?

Parece algo mais apropriado para suas necessidades.

2 curtidas

Eu já estava pensando nessa opção. Usamos as CPUs não dedicadas anteriormente e a “atualização” para as dedicadas não nos trouxe muitos avanços.

1 curtida

Não tenho certeza se a CPU é o seu gargalo. Você tem alguma saída do sar para compartilhar enquanto isso?

Sim, tenho, mas ainda não nos horários de pico. Terei isso até amanhã.

O uso da CPU foi definitivamente reduzido desde que aumentei as conexões de worker ontem - não tenho certeza de quanto, no entanto.

12:00:01 AM     CPU     %user     %nice   %system   %iowait    %steal     %idle

08:45:01 AM     all     40.22      2.21      7.44      0.27      0.00     49.86
08:55:01 AM     all     42.84      2.89      8.02      0.16      0.00     46.09
09:05:01 AM     all     38.81      0.86      7.68      0.12      0.00     52.53
09:15:01 AM     all     38.80      0.70      7.66      0.10      0.00     52.73
09:25:01 AM     all     38.71      2.14      7.88      0.12      0.00     51.16
09:35:01 AM     all     38.74      0.84      7.86      0.09      0.00     52.47
09:45:01 AM     all     40.31      1.07      7.95      0.10      0.00     50.57
09:55:01 AM     all     40.03      1.37      7.90      0.08      0.00     50.62
10:05:01 AM     all     39.00      1.29      7.90      0.09      0.00     51.72
10:15:01 AM     all     40.26      2.68      8.07      0.09      0.00     48.91
10:25:01 AM     all     41.59      0.93      8.31      0.08      0.00     49.09
10:35:01 AM     all     40.39      1.55      8.25      0.07      0.00     49.73
10:45:01 AM     all     45.44      2.37      9.08      0.08      0.00     43.03
10:55:01 AM     all     50.56      2.20      9.23      0.06      0.00     37.95
11:05:01 AM     all     41.82      1.54      8.55      0.08      0.00     48.02
11:15:01 AM     all     38.74      1.54      8.11      0.10      0.00     51.50
11:25:01 AM     all     45.41      1.59      9.27      0.19      0.00     43.55
11:35:01 AM     all     38.45      1.78      8.20      0.11      0.00     51.45
11:45:01 AM     all     41.03      1.60      8.48      0.14      0.00     48.75
11:55:01 AM     all     40.65      1.17      8.36      0.15      0.00     49.67
12:05:01 PM     all     40.03      1.29      8.40      0.13      0.00     50.15
12:15:01 PM     all     40.47      1.10      8.19      0.11      0.00     50.13
1 curtida

Quais estatísticas úteis do sar devem ser consideradas?

Suspeitei que o Postgres não estava recebendo memória suficiente, o que resultaria em um %iowait alto.
Mas, como a saída do sar acima não indica um sistema sobrecarregado, teremos que esperar por novas estatísticas.

Estou tentando ajudar outra pessoa com problemas de desempenho. Aumentamos o tamanho do buffer do postgres. Acho que ajudou um pouco, mas o mini profiler ainda mostra mais de 300ms. O uso da CPU é de cerca de 30% para 16 cpus.

1 curtida

Parece que isso não vai mudar. Observei durante duas noites e não obtive nenhum uso de CPU mais alto. Sua suposição sobre o Postgres pode estar correta.

Em relação ao mini profiler: quais são os números que queremos atingir? Estamos em torno de 300ms agora. Estivemos em cerca de 500ms antes.

3 curtidas

Acho que se alcançarmos abaixo de 50 ms em todos os casos, independentemente dos horários de pico de tráfego, eu chamaria isso de tempo de resposta rápido do servidor. O resto do site será mais rápido, pois tudo depende do tempo de resposta inicial do servidor.

E será super ideal se permanecer abaixo de 50 ms para todos os usuários geográficos e se mantiver consistente. No momento, ele fica pulando e é principalmente mais alto, e esse parece ser o grande problema para ser lento.

Como uma pequena revisão dos últimos dias, as coisas continuaram tranquilas, exceto por cerca de meia hora esta tarde. Não estive no servidor nesse horário, mas tivemos Timeouts do Backend relatados no log do nginx. sar mostra uma utilização de sistema ligeiramente maior, mas nenhuma carga geral de CPU alta. Não tenho certeza do que foi, mas aparentemente impediu o bom funcionamento do unicorn/redis/postgres.

03:55:01 PM     all     34.99      1.87      6.67      0.12      0.00     56.35
04:05:01 PM     all     33.99      0.35      6.52      0.31      0.00     58.82
04:15:01 PM     all     35.24      1.17      7.14      0.13      0.00     56.31
04:25:02 PM     all     36.45      0.63      7.15      0.13      0.00     55.65

> 04:35:01 PM     all     39.09      0.71     16.78      0.11      0.00     43.32
> 04:45:01 PM     all     35.53      0.95     20.16      0.08      0.00     43.27
> 04:55:01 PM     all     41.64      4.29     15.44      0.24      0.00     38.39
05:05:01 PM     all     36.75      2.47      7.78      0.13      0.00     52.87
05:15:01 PM     all     35.96      1.29      7.81      0.10      0.00     54.85
05:25:01 PM     all     38.69      1.35      8.00      0.09      0.00     51.87
05:35:01 PM     all     37.01      4.53      7.92      0.07      0.00     50.46

São as linhas marcadas com >.

Não consigo ver nenhum tráfego alto naquele momento, então estou meio sem saber o que foi, mas realmente aconteceu apenas naquela meia hora.

No geral, ao olhar o tempo de CPU, o Redis assumiu a liderança e geralmente usa uma boa parte da CPU. Não tenho certeza se há algo que possa ser feito a respeito. Geralmente fica em torno de 20-25%, chegando a 35% aqui e ali.

1721566 uuidd      20   0 2035M 1458M  1952 S 16.1  4.6 16h22:37 /usr/bin/redis-server *:6379
1721578 www-data   20   0  108M 69100 12516 S  6.7  0.2  6h32:27 nginx: worker process
2853756 1000       20   0 1355M  444M 19356 R 63.7  1.4  2h38:10 unicorn worker[0] -E production -c config/unicorn.conf.rb
2854380 1000       20   0 1267M  409M 18768 S 41.6  1.3  2h19:45 unicorn worker[4] -E production -c config/unicorn.conf.rb
1721598 1000       20   0  592M  285M  5192 S  1.3  0.9  2h08:53 unicorn master -E production -c config/unicorn.conf.rb
    575 root       20   0 1747M 20468  5040 S  0.7  0.1  2h01:02 /usr/bin/containerd
2854731 1000       20   0 1280M  399M 17880 S 36.9  1.3  1h57:52 unicorn worker[7] -E production -c config/unicorn.conf.rb
1721841 1000       20   0  592M  285M  5192 S  0.7  0.9  1h49:49 unicorn master -E production -c config/unicorn.conf.rb
2855284 1000       20   0 1287M  425M 18396 S 18.8  1.4  1h35:02 unicorn worker[3] -E production -c config/unicorn.conf.rb
2856414 1000       20   0 1223M  391M 19268 S 13.4  1.2  1h14:50 unicorn worker[2] -E production -c config/unicorn.conf.rb
2856478 1000       20   0 1207M  401M 21120 S  5.4  1.3 58:42.50 unicorn worker[5] -E production -c config/unicorn.conf.rb
2856503 1000       20   0 1215M  389M 18980 S  4.7  1.2 47:22.95 unicorn worker[1] -E production -c config/unicorn.conf.rb
1721581 www-data   20   0 69888 28636 13368 S  0.0  0.1 44:49.50 nginx: worker process
2857467 1000       20   0 1199M  385M 18112 S  4.0  1.2 39:23.87 unicorn worker[6] -E production -c config/unicorn.conf.rb
1721594 _apt       20   0 8479M 20036 18128 S  1.3  0.1 32:55.29 postgres: 13/main: walwriter
    580 root       20   0 1747M 20468  5040 S  0.0  0.1 32:15.27 /usr/bin/containerd

A carga geral está em média 5 a longo prazo, mas ainda a vejo subindo para 8 ou 9 de vez em quando.

2 curtidas

Em relação ao mini profiler. Eu estava falando sobre o tempo de carregamento geral. O tempo de resposta do servidor (solicitação inicial) geralmente fica abaixo de 10 ms da nossa parte. Às vezes, um pouco acima, mas eu não vi > 20 ms nas minhas últimas verificações. O tempo de carregamento geral chega a 800 ms às vezes, muito raramente acima de 1000 ms.

Olhando apenas para uma região geográfica, pois não temos um número significativo de usuários fora dessa região.

Recomendo dar uma olhada em DISCOURSE_ENABLE_PERFORMANCE_HTTP_HEADERS, que também deve fornecer insights sobre onde você pode melhorar o desempenho.

4 curtidas