![使用 nginx 和 php5-fpm,100 个并发用户时服务器崩溃(504 网关超时)](https://linux22.com/image/684732/%E4%BD%BF%E7%94%A8%20nginx%20%E5%92%8C%20php5-fpm%EF%BC%8C100%20%E4%B8%AA%E5%B9%B6%E5%8F%91%E7%94%A8%E6%88%B7%E6%97%B6%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%B4%A9%E6%BA%83%EF%BC%88504%20%E7%BD%91%E5%85%B3%E8%B6%85%E6%97%B6%EF%BC%89.png)
我们有一台 VPS 服务器,专用于一个网站。它每天似乎都运行良好(例如 20-50 个并发用户),但一旦并发用户达到 90 多个左右,服务器就会开始崩溃/超时。它将开始显示 nginx 的 504 网关超时错误。
今年早些时候,我们遇到了一些问题,加载一些数据量很大的页面需要大约 7 秒的时间,我们通过优化 mysql 查询和利用 myqsl 缓存成功解决了 90% 的问题。然而,这似乎并没有起到什么帮助作用!
当我说数据量大时,它正在通过框架从数据库加载大约 5000 条记录。
该服务器运行的是 Ubuntu 15.10,有 4 个 CPU 和 4GB 内存。Mysql 位于自己的服务器上,内存为 1GB。即使有 100 个用户,mysql 服务器的利用率似乎也不超过 30%。
Mysql 配置为 64mbquery_cache_size
和 6mbquery_cache_limit
我们安装了 APC,但总体来说似乎没什么区别
这是我们的 nginx.conf
user www-data;
worker_processes 4;
pid /run/nginx.pid;
events {
worker_connections 1024;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 15;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
client_body_buffer_size 32k;
client_header_buffer_size 8k;
large_client_header_buffers 8 64k;
#client_body_buffer_size 10K;
#client_header_buffer_size 1k;
client_max_body_size 12m;
#large_client_header_buffers 2 1k;
fastcgi_cache_path /etc/nginx/cache levels=1:2 keys_zone=microcache:100m inactive=10m max_size=1024m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
#access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
gzip_disable "msie6";
gzip_comp_level 3;
gzip_vary on;
gzip_proxied any;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript text/x-js;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
这是服务器块
server {
listen 80 default;
server_name www.website.com;
root /var/www/website.com/httpdocs;
index index.php index.html index.htm;
location / {
try_files $uri @handler;
}
error_page 404 /assets/error-404.html;
error_page 500 /assets/error-500.html;
location @handler {
expires off;
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
# fastcgi caching
#Cache everything by default
set $no_cache 0;
if ($request_method !~ ^(GET|HEAD)$) {
set $no_cache "1";
}
#Don't cache the following URLs
if ($request_uri ~* "/(admin/|member/)")
{
set $no_cache 1;
}
#fastcgi_no_cache $no_cache;
#fastcgi_cache_bypass $no_cache;
#fastcgi_cache microcache;
#fastcgi_cache_key $scheme$host$request_uri$request_method;
#fastcgi_cache_valid 200 301 302 10m;
#fastcgi_cache_use_stale updating error timeout invalid_header http_500;
#fastcgi_pass_header Set-Cookie;
#fastcgi_pass_header Cookie;
#fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
fastcgi_param SCRIPT_FILENAME $document_root/framework/main.php;
fastcgi_param SCRIPT_NAME /framework/main.php;
fastcgi_param QUERY_STRING url=$uri&$args;
fastcgi_buffer_size 32k;
fastcgi_buffers 4 32k;
fastcgi_busy_buffers_size 64k;
}
}
这是pool.d/www.conf 的详细信息
pm = dynamic
pm.max_children = 30
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 4
pm.max_requests = 500
PHP 设置为 128mb 内存,但每个进程通常约占 70mb
我没能得到顶部虽然有 100 个用户,但通常状态如下:
total used free shared buffers cached
Mem: 3951 3793 157 114 273 2918
-/+ buffers/cache: 602 3348
Swap: 0 0 0
你会看到我对 nginx 的 fastcgi_cache 做了一些实验,这使得巨大的性能差异(加载时间为 50 - 100 毫秒),但是网站有很多用户功能(上传、修改等),在启用此功能后无法使用。
我想重新审视 fastcgi_cache,但我觉得即使没有它我们也一定能够在当前服务器上获得更好的结果?!
已经与此斗争了一段时间了,所以任何帮助都将非常有帮助。
答案1
你设置pm.max_children
成了30,也就是说同一时间只能有30个并发的PHP脚本在运行。
当更多用户访问您的网站时,没有任何免费的 PHP 进程来满足请求。nginx
等待一段时间,然后返回504 Gateway Time-out
错误。
您似乎有足够的可用内存,因为您的cached
列显示 2.9 GB 的可用内存。
您应该使用命令检查 PHP 进程的平均内存使用情况top
。我们感兴趣的内存使用情况是该RES
列。用该数字除以 2GB,您将得到一个安全的数字pm.max_children
。
pm.start_servers
您还应该考虑提高、pm.min_spare_servers
和的值pm.max_spare_servers
。
备用服务器是可以立即处理请求的进程。否则,PHP 进程管理器需要单独启动一个进程,这需要一些时间。