Posted on: December 28, 2023 08:03 PM
Posted by: Renato
Categories: laravelphp PHP Dicas developer 100DaysOfCode phpfpm nginx
Views: 681
Resolvendo o erro ‘Server Reached pm.max_children’ em PHP-FPM
Os servidores da Web funcionam sem problemas até que não o sejam, e um dos erros que você pode encontrar ao usar o PHP-FPM (FastCGI Process Manager) é o erro “server atingido pm.max_children configuração”. Quando você vê essa mensagem de erro, geralmente significa que seu servidor está ficando sem processos filhos que lidam com solicitações PHP recebidas.
Neste artigo, vamos aprofundar o que é esse erro, por que isso acontece e como efetivamente resolvê-lo.
Entendendo o PHP-FPM
PHP-FPM é uma implementação alternativa do PHP FastCGI com alguns recursos adicionais úteis para sites com alto tráfego. É significativamente mais rápido do que os métodos tradicionais baseados em CGI em ambientes PHP multiusuários.
O PHP-FPM mantém pools (trabalhadores que podem responder a solicitações PHP) para conseguir isso. O parâmetro pm.max_children é uma configuração no PHP-FPM que determina o número máximo de processos filhos que serão criados para processar solicitações PHP.
O que causa o erro “Servo Alcandeu pm.max_children”?
Esse erro é causado quando o limite máximo de processos filhos, especificado na configuração pm.max_children, é atingido. Quando o servidor fica sobrecarregado com mais solicitações PHP do que pode lidar com o número atual de processos filhos, esse limite é atingido.
Isso geralmente acontece devido a uma das seguintes razões:
- Tráfego alto: Se o seu site tiver um aumento repentino no tráfego, ele poderá esgotar os processos infantis disponíveis.
- Pedidos de Recursos: Certas solicitações PHP, como aquelas envolvendo uploads de arquivos grandes, interações de banco de dados ou cálculos complexos, podem levar muito tempo para concluir, amarrando processos filhos.
- Configurações mal configuradas : Se a configuração pm.max_children estiver definida muito baixa em relação aos recursos e tráfego do servidor, isso pode facilmente levar a esse erro.
Como resolver o erro
Agora que entendemos as causas, vamos olhar para os passos para resolver esse problema.
1. Verifique os logs de erro do servidor
O primeiro passo para diagnosticar esse erro é verificar os logs de erros do servidor. Esses registros fornecem informações valiosas sobre erros do sistema e podem ajudar a identificar a causa do problema.
2. Analise o uso atual
Em seguida, analise o uso atual de seus pools PHP-FPM. Isso pode ser feito usando o comando ps em sistemas baseados em UNIX:
ps aux | grep .php-fpm.
Este comando irá mostrar-lhe o número de processos PHP-FPM ativos.
3. Ajuste o pm.max_children Setting
Se você achar que sua configuração pm.max_children atual é realmente muito baixa, a solução mais simples é aumentar esse valor. Isso permite que seu servidor gere mais processos filhos para lidar com solicitações PHP recebidas.
No entanto, seja cauteloso para não definir esse valor muito alto. Cada processo de criança consome memória do sistema. Se o pm.max_children estiver muito alto, seu servidor pode ficar sem memória e começar a trocar, o que degradará significativamente o desempenho. Uma boa regra é definir pm.max_children de tal forma que a memória máxima consumida pelo PHP-FPM não exceda 70-80% da RAM do seu servidor.
Veja como você calcula um valor razoável do pm.max_children:
4. Ajuste outras configurações do PHP-FPM
Existem outras configurações PHP-FPM que você pode ajustar para otimizar o desempenho do seu servidor:
- pm.start_servers : O número de processos filhos criados na inicialização.
- pm.min_spare_servers : O número mínimo desejado de processos de servidor ocioso.
- pm.max_spare_servers : O número máximo desejado de processos de servidor ocioso.
- pm.max_requests : O número de solicitações que cada processo de criança deve ser executado antes de respawning.
Essas configurações estão inter-relacionadas, e ajustá-las pode ajudar a equilibrar o uso e o desempenho da memória.
5. Otimize sua aplicação PHP
Se o erro persistir, pode haver alguma otimização necessária em seu aplicativo PHP. Roteiros lentos, vazamentos de memória ou operações pesadas em recursos podem ser responsáveis por sobrecarregar seu servidor. O perfil do seu aplicativo pode ajudar a identificar gargalos que podem ser otimizados.
Conclusão
Compreender e configurar adequadamente as configurações do PHP-FPM é crucial para manter o desempenho ideal do servidor e garantir uma experiência suave para os usuários finais. É essencial monitorar o desempenho do servidor e os logs de erros regularmente e ajustar as configurações conforme necessário.
Ao seguir as etapas descritas neste artigo, você deve ser capaz de resolver o erro “server chegou a pm.max_children”. No entanto, lembre-se de que cada ambiente de servidor é único, e essas soluções podem precisar ser adaptadas para se adequar à sua situação específica.
## Anotações minhas:
# PHP FPM
## Logs FPM
cd /usr/local/etc/php-fpm.d/
vim www.conf
catch_workers_output = yes
php_admin_value[error_log] = /var/log/fpm-php.www.log
php_admin_flag[log_errors] = on
## What is PM.MAX_CHILDREN and PM.MAX_REQUESTS?
## www.conf
[php-fpm-pool-settings]
pm = dynamic
pm.max_children = 25
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 498
## What is PM.MAX_CHILDREN and PM.MAX_REQUESTS?
pm.max_children = 70
pm.start_servers = 20
pm.min_spare_servers = 20
pm.max_spare_servers = 35
pm.max_requests = 5000 ## => 0
https://www.php.net/manual/en/install.fpm.configuration.php
pm.max_requests:
The number of requests each child process should execute before respawning. This can be useful to work around memory leaks in 3rd party libraries. For endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS. Default value: 0.
pm.max_children:
The number of child processes to be created when pm is set to static and the maximum number of child processes to be created when pm is set to dynamic. This option is mandatory.
This option sets the limit on the number of simultaneous requests that will be served. Equivalent to the ApacheMaxClients directive with mpm_prefork and to the PHP_FCGI_CHILDREN environment variable in the original PHP FastCGI.
The RSS column shows non-swapped physical memory usage by PHP-FPM processes in kilo Bytes.
If on an average each PHP-FPM process takes ~85MB of RAM on your server, appropriate value for pm.max_children can be calculated as:
pm.max_children = Total RAM dedicated to the web server / Max child process size
The server has 8GB of RAM, so:
pm.max_children = 6144MB / 85MB = 72
You need to take into account any other services running on the machine while calculating memory usage.
Then change the settings as follow:
pm.start_servers = 20
pm.min_spare_servers = 20
pm.max_spare_servers = 35
pm.max_requests = 500
> I have done some investigations and I have found this to calculate and adjust pm.max_children value
https://myshell.co.uk/blog/2012/07/adjusting-child-processes-for-php-fpm-nginx/
but for example :
I have 8Gb on my server
I'm hosting 30 websites
php-fpm average process size around 40mb
php-fpm max process size around 80mb
I want to allocate 5Gb max of my memory to php-fpm processes
If I apply this :
pm.max_children = Total RAM dedicated to the web server / Max child process size
So in my case :
pm.max_children = 5120 / 80 = 64
But If I add pm.max_children = 64 on each php-fpm website conf files, this means every website can use 64 children process X size of 1 process (ex 40mb) = 2560Mb
And If we imagine, at the same time, all the 30 website have reach the pm.max_children value, we will have : 2560Mb (max per website) x 30 websites = 76 800 Mb
Am I correct?
Si yes, this means when many websites are hosted on the same server, we have to divide the result of the calcul pm.max_children = 5120 / 80 = 64 by the number of websites hosted (here 30).
So 64 / 30 = 2,1 and pm.max_children = 2 per website
### Results:
[Available RAM for PHP] / [Average Process Size] = [max_children]
pm.max_children = [max_children]
pm.start_servers = [25% of max_children]
pm.min_spare_servers = [25% of max_children]
pm.max_spare_servers = [75% of max_children]
## PHP-FPM Process Calculator
- https://spot13.com/pmcalculator/
Thanks
## php.ini
memory_limit "128M" => 1024M
## nginx
http {
...
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=webcache:1000m inactive=1y max_size=1000m;
proxy_temp_path /var/cache/nginx/tmp;
proxy_cache_min_uses 1;
...
server {
...
location / {
add_header X-Cache-Status $upstream_cache_status;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_cache webcache;
proxy_cache_valid any 15s;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_pass http://localhost:8080;
A partir do NGINX 1.9.5 é bem fácil habilitar o HTTP/2. Você só vai precisar configurar os certificados no seu servidor e habilitar o HTTP/2.
server {
listen 443 ssl http2;
ssl_certificate server.crt;
ssl_certificate_key server.key
...
}
nginx -t
nginx -s reload
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml;
gzip_disable "MSIE [1-6]\.";
,
user www-data;
worker_processes auto;
# error_log logs/error.log;
# pid logs/nginx.pid;
worker_rlimit_nofile 8192;
events {
worker_connections 4096;
}
http {
include /etc/nginx/mime.types;
# include /etc/nginx/proxy.conf;
# include /etc/nginx/fastcgi.conf;
# index index.html index.htm index.php;
default_type application/octet-stream;
fastcgi_read_timeout 300;
proxy_read_timeout 300;
log_format main '$remote_addr - $remote_user [$time_local] $status '
'"$request" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# access_log logs/access.log main;
sendfile on;
tcp_nopush on;
server_names_hash_bucket_size 128;
client_max_body_size 128M;
include /etc/nginx/conf.d/*.conf;
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml;
gzip_disable "MSIE [1-6]\.";
}
-----------------------------------------------------
Na prática - Nginx.conf
Abaixo será apresentado as principais variaveis do arquivo /etc/nginx/nginx.conf e as configurações que recomendamos
work_connections 5000 – Essa variável é responsável para atribuir o numero de requisições para o servidor web
work_rlimit_nofile 12000 – Essa variável é responsável pelo numero de arquivos que podem estar abertos no sistema operacional
gzip_static on – GZIP é um recurso que já vem habilitado nos nossos ambientes, ele é responsável por compactar os arquivos da aplicação
sendfile on
multi_accept on
ese epoli
keepalive – Já vem habilitado habilitado nos nossos ambientes
Desabilitar os logs se caso desejar, comentando as linhas acess_log e error_log
------------------------------------------
# php
Cache de domínio (usar com cuidado), se desejar ter cache(no exemplo abaixo, de 30 dias, nessas extensões de arquivo), adicionar a linha): location~*\.(?:ico|css|js|json|gif|jpe?g|png|woff2)$ {espires 7d;}
# Na prática - php.ini e php-fpm.conf
No arquivo /etc/php.ini recomendamos manter as configurações que já estão otimizadas, se desejar apenas ajudar o uso de memoria na variável memory_limit.
No arquivo /etc/php-fpm.conf que é responsável por executar as requisições do php, recomendamos as configurações abaixo:
Conceitos do pm = static, dynamic e ondemand (Essa variável e responsável por definir a forma que será executado o php, para a nossa plataforma recomendamos a dynamic)
pm.max_children = 2 (Essa variável é responsável pela quantidade de processos php serão executados simultaneamente, sugerimos utilizar 1 por core, no comando ssh /proc/cpuinfo é apresentado quantos cores o servidor possui)
pm.process_idle_timeout = 10s (Essa variável é definida como padrão, recomendamos não alterar ela)
om.max_requests = 5000 (Essa variável é definida como padrão, recomendamos não alterar ela)
-----------------------------------------------------------------------------------------------------------
# adicionado nginx
http {
...
fastcgi_buffers 8 16k;
fastcgi_buffer_size 32k;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
...
}
sudo free -m
Fui e tentei executá-lo manualmente de /usr/sbin/php-fpm <- foi aqui que vi que havia um problema com o APC e, depois de procurar um pouco online, vi isso simplesmente removendo o "M" em /etc /php5/conf.d/apc.ini para a propriedade: apc.shm_size=128 resolveu o problema.
Tenho certeza de que isso é uma má ideia. No arquivo php.ini estas são as regras As opções disponíveis são K (para Kilobytes), M (para Megabytes) e G (para Gigabytes; disponível desde o PHP 5.1.0), estas não diferenciam maiúsculas de minúsculas. Qualquer outra coisa assume bytes .. Estou recebendo isso do site php aqui. Ele diz que isso se refere apenas ao arquivo php.ini, mas aposto que isso altera o valor completamente. Pode ter sido que o seu foi definido muito alto. Talvez configurá-lo para `48M` ou inferior teria sido uma boa ideia.
# ----------------------------------------------------------------------------------------------------------------------------------
echo "[2023-12-28 22:06:53] lumen.INFO: Jesus Vive!" >> storage/logs/lumen-2023-12-28.log
Fontes:
- https://www.edufukunari.com.br/how-to-solve-php-fpm-server-reached-max-children/
- https://stackoverflow.com/questions/29608292/what-is-pm-max-children-and-pm-max-requests
- https://absam.io/blog/melhor-performance-com-php-fpm/
- https://www.kinamo.be/en/knowledge-base/determining-the-correct-number-of-child-processes-for-php-fpm-on-nginx
- https://geekflare.com/php-fpm-optimization/
- https://docs.rockylinux.org/guides/web/php/
- https://spot13.com/pmcalculator/
Donate to Site
Renato
Developer