2015年9月18日 星期五

Linux、nginx、php-fpm 連線數優化

nginx + php-fpm,連線數一多會發生,502 Bad Gateway 或 504 Gateway Time-out 等問題。
  • 502 Bad Gateway:nginx 連不到 php-fpm。可以增加 php-fpm 連線數量。或將 nginx 連 php-fpm 等待連接的時間設長一點(fastcgi_connect_timeout)。
  • 504 Gateway Time-out:php-fpm 執行時間,超過 nginx 允許的接收時間。可以將 nginx 接收時間設長一點(fastcgi_read_timeout)。
影響連線數限制的設定主要有三個部分:linux 系統的限制、nginx 的限制、php-fpm 的限制。
修改時,須視執行情況調整,若設的太大,系統硬體負擔太大,會執行的很慢,甚至崩潰。

[修改 Linux 作業系統設定]
  1. 增加主機間連接可用的連線數。
    服務端(Server)增加額外的IP、PORT提供服務。
    請求端(local)增加可用的port範圍。(不夠會出現Cannot assign requested address錯誤)
    例如:php-fpm 訪問另一台 Redis Server 的 6379 PORT。
    若 php-fpm 的作業系統,local端可用PORT範圍設定為 65531~65535=>5個
    當Redis Server提供1個IP做服務,則 php-fpm 連到 Redis 的連線數,可達 (65531~65535)=>5個連線
    當Redis Server提供2個IP做服務,則 php-fpm 連到 Redis 的連線數,可達 (65531~65535)*2個IP=>10個連線
    服務端若可提供額外的PORT,也是同增加額外IP一樣可增加可用連線數。
  2. TIME-WAIT狀態的sockets
    快速回收(不建議使用)、重用
$ vi /etc/sysctl.conf
#socket監聽(listen)的backlog上限
net.core.somaxconn = 65535

#SYN的backlog最大數量
net.ipv4.tcp_max_syn_backlog = 819200

#當網絡卡接收的packets快過kernel處理速度時的最大backlog
net.core.netdev_max_backlog = 819200

#增加local端可用的port範圍(首選)
net.ipv4.ip_local_port_range = 2000 65535

#若開啟SYN Cookie,可防範一些SYN攻擊(SYN Flood)
net.ipv4.tcp_syncookies = 0

#TIME-WAIT狀態的sockets快速回收,某些架構下時間戳判斷不可靠,不建議開啟tcp_tw_recycle。NAT下有問題。
#LINUX新版4.12核心,已去除此參數。
#sysctl: cannot stat /proc/sys/net/ipv4/tcp_tw_recycle: No such file or directory
#net.ipv4.tcp_tw_recycle = 1

#TIME-WAIT狀態的sockets重用。(tcp_timestamps也須開啟)
net.ipv4.tcp_tw_reuse = 1

#不重開機,立即套用設定
$ sysctl -p
#查看設定後的效果
$ cat /proc/sys/net/core/somaxconn
65535
$ cat /proc/sys/net/ipv4/tcp_max_syn_backlog
819200
$ cat /proc/sys/net/core/netdev_max_backlog
819200
$ cat /proc/sys/net/ipv4/ip_local_port_range
2000    65535
$ cat /proc/sys/net/ipv4/tcp_syncookies
0
$ cat /proc/sys/net/ipv4/tcp_timestamps
1
#不建議使用
#$ cat /proc/sys/net/ipv4/tcp_tw_recycle
#1
$ cat /proc/sys/net/ipv4/tcp_tw_reuse
1


[Nginx virtual host 設定]
server {
    #修改 backlog,多個 virtual host,backlog 只須在其中一個設定
    listen 80 backlog=1024;
    ....
}
重啟後,查看 backlog 設定是否生效。
這邊要注意的是,backlog 這個值不是越大越好,
若程式很耗費資源,當 backlog 太大時,可能耗盡 Server 資源,造成網站卡住所有連線反應都很慢,
這個設定值會受 linux 系統 net.core.somaxconn 設定的限制。
$ ss -nlt
State   Recv-Q Send-Q   Local Address:Port    Peer Address:Port
LISTEN    0     1024                *:80                 *:*
[Nginx 全域設定]
user  nginx;
worker_processes  8; #一般設定為 CPU 核心數

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    use epoll;
    worker_connections  65535;#每個 worker process 能同時接受的連線數
}
worker_rlimit_nofile 65535; #worker processes 能打開的檔案數限制

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    tcp_nopush     on;

    keepalive_timeout  65;

    server_names_hash_bucket_size 128;
    client_header_buffer_size 32k;
    large_client_header_buffers 4 32k;
    client_max_body_size 8m;

    server_tokens  off;
    client_body_buffer_size  512k;

    #fastcgi
    #適當調整 fastcgi_connect_timeout、fastcgi_send_timeout、fastcgi_read_timeout 設定值
    fastcgi_connect_timeout 300; #太短可能發生 502 Bad Gateway
    fastcgi_send_timeout 300;
    fastcgi_read_timeout 300; #太短可能發生 504 Gateway Time-out
    fastcgi_buffer_size 64k;
    fastcgi_buffers 4 64k;
    fastcgi_busy_buffers_size 128k;
    fastcgi_temp_file_write_size 128k;
    fastcgi_intercept_errors on;

    #gzip
    gzip  off;
    gzip_min_length  1k;
    gzip_buffers 32  4k;
    gzip_http_version  1.0;
    gzip_comp_level  2;
    gzip_types  text/css text/xml application/javascript application/atom+xml application/rss+xml text/plain application/json;
    gzip_vary  on;

    include /etc/nginx/conf.d/*.conf;
}


[php-fpm 設定]
常駐的 process 數越多,系統越不用開開關關 process,會較節省 CPU。
但 process 數越多,使用的記憶體也會越大,所以,須視CPU與記憶體使用狀況,取一個平衡。
若設的太小,在 php-fpm.log 會記錄相關的訊息。
例如:WARNING: [pool www] server reached pm.max_children setting (50), consider raising it
listen.backlog = 65535
pm.max_children = 800
pm.start_servers = 200
pm.min_spare_servers = 100
pm.max_spare_servers = 800
pm.max_requests = 4000
rlimit_files = 51200


參考:
Need to increase nginx throughput to an upstream unix socket — linux kernel tuning?
怎样优化FastCGI与Nginx的搭配
nginx下关于PHP-FPM在高负载下的优化配置
Nginx Connection 不夠用 的參數調整
Nginx 502错误触发条件与解决办法汇总
https://trac.nginx.org/nginx/ticket/193
解决nginx莫名奇妙的“Resource temporarily unavailable”
nginx優化突破十萬並行連線數
nginx+php-fpm性能参数优化原则
nginx 并发数问题思考:worker_connections,worker_processes与 max clients
被抛弃的tcp_recycle_ITPUB博客 不要在linux上启用net.ipv4.tcp_tw_recycle参数 – CFC4N的博客
ip-sysctl.txt « networking « Documentation - kernel/git/torvalds/linux.git - Linux kernel source tree
Linux之TCPIP内核参数优化 - 最初的幸福ever - 博客园

沒有留言:

張貼留言