5.19. Nginx 0.8.x + PHP 5.2.13(FastCGI)搭建胜过Apache十倍的Web服务器

http://blog.zyan.cc/nginx_php_v6

5.19.1. Nginx PHP服务器环境搭建

CentOS 7 默认的 PHP 版本是 5.3,可以使用 Remi 扩展源安装 PHP 5.6 和 PHP-FPM。

yum install -y epel-release               # 安装EPEL扩展源

yum provides php   #自带的只有5.4版本
rpm -Uvh https://mirror.webtatic.com/yum/el7/epel-release.rpm         #更新源
rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm
yum remove php-common -y     #移除系统自带的php-common
yum install -y php56w php56w-opcache php56w-xml php56w-mcrypt php56w-gd php56w-devel php56w-mysql php56w-intl php56w-mbstring         #安装依赖包
php -v                    #版本变为5.6
yum provides php-fpm      #因为我是准备搭建lnmp,所以安装php-fpm,这里会提示多个安装源,选择5.6版本的安装就可以了
yum install php56w-fpm-5.6.31-1.w7.x86_64 -y

systemctl enable php-fpm
systemctl start php-fpm           # 启动PHP-FPM服务

在 Nginx 的 conf 文件夹中创建文件 fscgi.conf,用于编辑 FastCGI 的全局配置,配置内容如下:

# 缓冲区配置
fastcgi_buffering on;             # 默认启用缓冲区
fastcgi_buffers 8 64k;            # 若响应数据大小小于512KB,则会分配8个64KB缓冲区为其缓
                                  # 冲;若大于512KB,则超出的部分会存储到临时文件中
fastcgi_buffer_size 64k;          # 读取FastCGI服务器响应数据第一部分的缓冲区大小为64KB,
                                  # 通常包含响应头信息
fastcgi_busy_buffers_size 128K;   # 繁忙时向客户端发送响应的缓冲区大小为128KB
fastcgi_limit_rate 0;             # 默认不做限制
fastcgi_max_temp_file_size 1024M; # 临时文件中大小为1024MB
fastcgi_temp_file_write_size 64k; # 每次写入临时文件的数据大小为64KB
# fastcgi_temp_path使用默认配置

# 请求处理
fastcgi_request_buffering on;     # 默认启用读取整个请求体到缓冲区后再向FastCGI服务器发送请求
fastcgi_pass_request_body on;     # 默认将客户端请求体传递给FastCGI服务器
fastcgi_pass_request_headers on;  # 默认将客户端请求头传递给FastCGI服务器

# FastCGI连接配置
fastcgi_connect_timeout 60s;      # 默认Nginx与FastCGI服务器建立连接的超时时间为60s
fastcgi_keep_conn on;             # 启用保持连接
fastcgi_ignore_client_abort on;   # 当客户端关闭连接时,同时关闭与FastCGI服务器的连接
fastcgi_read_timeout 60s;         # 默认连续两个从FastCGI服务器接收数据的读操作之间的间隔
                                  # 时间为60s
fastcgi_send_timeout 60s;         # 默认连续两个发送到FastCGI服务器的写操作之间的间隔时间
                                  # 为60s
fastcgi_socket_keepalive on;      # FastCGI的连接启用so-keepalive socket选项

# 响应处理
fastcgi_force_ranges on ;         # 强制启用byte-range请求支持
fastcgi_hide_header X-Powered-By; # 隐藏PHP版本字段
# fastcgi_pass_header无必须传递的特殊头字段属性

fastcgi_ignore_headers X-Accel-Redirect X-Accel-Expires \
                       X-Accel-Limit-Rate X-Accel-Buffering \
                       X-Accel-Charset Expires \
                       Cache-Control Set-Cookie Vary;
                                  # 禁止Nginx处理从FastCGI获取响应的头属性字段

# 异常处理
fastcgi_intercept_errors on;      # 在FastCGI响应数据中响应码大于等于300时重定向给Nginx
fastcgi_next_upstream   error timeout invalid_header \
                        http_500 http_503 http_403 \
                        http_404 http_429;  # 当出现指定的条件时,将用户请求传递给upstream
                                            # 中的下一个服务器
fastcgi_next_upstream_timeout 0;            # 不限制将用户请求传递给upstream中的下一个
                                            # 服务器的超时时间
fastcgi_next_upstream_tries 0;              # 不限制将用户请求传递给upstream中的下一个
                                            # 服务器的尝试次数

5.19.2. 启动多个php-fpm进程

php-fpm.conf文件.默认只配置了一个 php-fpm pool 就是/etc/php-fpm.d/www.conf

[root@localhost php-fpm.d]# cat /etc/php-fpm.conf |grep -v ";"|grep -v "^$"
include=/etc/php-fpm.d/*.conf
[global]
pid = /var/run/php-fpm/php-fpm.pid
error_log = /var/log/php-fpm/error.log
daemonize = yes

在此我新增加了2个 php-fpm pool。总共3个php-fpm pool对应9000、9001、9002三个端口。

[root@localhost php-fpm.d]# tree
.
├── www1.conf
├── www2.conf
└── www.conf

www.conf

[root@localhost php-fpm.d]# cat www.conf |grep -v "^;"|grep -v "^$"
[www]
listen = 127.0.0.1:9000

listen.allowed_clients = 127.0.0.1
user = apache
group = apache
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
slowlog = /var/log/php-fpm/www-slow.log
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
php_value[session.save_handler] = files
php_value[session.save_path]    = /var/lib/php/session
php_value[soap.wsdl_cache_dir]  = /var/lib/php/wsdlcache

www1.conf

[root@localhost php-fpm.d]# cat www1.conf |grep -v "^;"|grep -v "^$"
[www1]
listen = 127.0.0.1:9001

listen.allowed_clients = 127.0.0.1
user = apache
group = apache
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
slowlog = /var/log/php-fpm/www-slow.log

php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
php_value[session.save_handler] = files
php_value[session.save_path]    = /var/lib/php/session
php_value[soap.wsdl_cache_dir]  = /var/lib/php/wsdlcache

www2.conf

[root@localhost php-fpm.d]# cat www2.conf |grep -v "^;"|grep -v "^$"
[www2]
listen = 127.0.0.1:9002

listen.allowed_clients = 127.0.0.1
user = apache
group = apache
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
slowlog = /var/log/php-fpm/www-slow.log

php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
php_value[session.save_handler] = files
php_value[session.save_path]    = /var/lib/php/session
php_value[soap.wsdl_cache_dir]  = /var/lib/php/wsdlcache

这里可以参考下面文章:

https://www.cnblogs.com/pzk7788/p/10341113.html

https://blog.51cto.com/8844414/2161558

查看php-fpm进程信息

[root@localhost php-fpm.d]# ps aux|grep php-fpm
root      84991  0.0  2.5 577232 25404 ?        Ss   15:37   0:00 php-fpm: master process (/etc/php-fpm.conf)
apache    84993  0.0  0.6 577112  6348 ?        S    15:37   0:00 php-fpm: pool www
apache    84994  0.0  0.6 577112  6348 ?        S    15:37   0:00 php-fpm: pool www
apache    84995  0.0  0.6 577112  6348 ?        S    15:37   0:00 php-fpm: pool www
apache    84996  0.0  0.6 577112  6348 ?        S    15:37   0:00 php-fpm: pool www
apache    84997  0.0  0.6 577112  6348 ?        S    15:37   0:00 php-fpm: pool www
apache    84998  0.0  0.6 577112  6348 ?        S    15:37   0:00 php-fpm: pool www1
apache    84999  0.0  0.6 577112  6348 ?        S    15:37   0:00 php-fpm: pool www1
apache    85000  0.0  0.6 577112  6348 ?        S    15:37   0:00 php-fpm: pool www1
apache    85001  0.0  0.6 577112  6348 ?        S    15:37   0:00 php-fpm: pool www1
apache    85002  0.0  0.6 577112  6348 ?        S    15:37   0:00 php-fpm: pool www1
apache    85003  0.0  0.6 577112  6348 ?        S    15:37   0:00 php-fpm: pool www2
apache    85004  0.0  0.6 577112  6348 ?        S    15:37   0:00 php-fpm: pool www2
apache    85005  0.0  0.6 577112  6348 ?        S    15:37   0:00 php-fpm: pool www2
apache    85006  0.0  0.6 577112  6348 ?        S    15:37   0:00 php-fpm: pool www2
apache    85007  0.0  0.6 577112  6352 ?        S    15:37   0:00 php-fpm: pool www2
root      85685  0.0  0.0 112824   976 pts/0    R+   15:49   0:00 grep --color=auto php-fpm

查看端口使用情况

[root@localhost php-fpm.d]# netstat -tunpl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:9000          0.0.0.0:*               LISTEN      84991/php-fpm: mast
tcp        0      0 127.0.0.1:9001          0.0.0.0:*               LISTEN      84991/php-fpm: mast
tcp        0      0 127.0.0.1:9002          0.0.0.0:*               LISTEN      84991/php-fpm: mast
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      1/systemd
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      84561/nginx: master
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      84561/nginx: master

5.19.3. Nginx基于FastCGI实现负载均衡

Nginx 支持后端多个 FastCGI 服务器的负载均衡,负载均衡有两种方式:一种是通过域名解析多个 FastCGI 服务器,该方式通过所有域名地址轮询(round-robin)的方式实现负载;另一种是通过配置 Nginx 的 upstream 模块实现负载。

本节通过后一种方式实现负载均衡场景的搭建。Nginx 的 FastCGI 模块支持对后端 PHP 解析数据的缓存,对于动态数据的缓存可以在实际应用场景中提升动态网站的访问速度。

安装 PHP-FPM 后,如果把 PHP 代码部署在与 Nginx 不同的服务器上,需要修改 PHP-FPM 服务器中的 /etc/php-fpm.d/www.conf配置。

# PHP-FPM绑定本机所有IP
sed -i "s/^listen =.*/listen = 0.0.0.0:9000/g" /etc/php-fpm.d/www.conf

# 允许任何主机访问PHP-FPM服务
sed -i "s/^listen.allowed_clients/;listen.allowed_clients/g" /etc/php-fpm.d/www.conf

Nginx 配置样例如下:

fastcgi_3worker.conf

[root@localhost conf.d]# cat fastcgi_3worker.conf
upstream fscgi_server {
    ip_hash;                               # session会话保持
    server 127.0.0.1:9000;                 # PHP-FPM服务器IP
    server 127.0.0.1:9001;                 # PHP-FPM服务器IP
    server 127.0.0.1:9002;                 # PHP-FPM服务器IP

}


fastcgi_cache_path /usr/local/nginx/nginx-cache1
                            levels=1:2
                            keys_zone=fscgi_hdd1:100m
                            max_size=10g
                            use_temp_path=off
                            inactive=60m;    # 设置缓存存储路径1,缓存的共享内存名称和大小
                                             # 100MB,无效缓存的判断时间为1小时

fastcgi_cache_path /usr/local/nginx/nginx-cache2
                            levels=1:2
                            keys_zone=fscgi_hdd2:100m
                            max_size=10g
                            use_temp_path=off
                            inactive=60m;   # 设置缓存存储路径2,缓存的共享内存名称和大小
                                            # 100MB,无效缓存的判断时间为1小时

split_clients $request_uri $fscgi_cache {
              50%           "fscgi_hdd1";  # 50%请求的缓存存储在第一个磁盘上
              50%           "fscgi_hdd2";  # 50%请求的缓存存储在第二个磁盘上
}

server {
    listen 8080;
    root /opt/nginx-web/phpweb;
    index index.php;
    include        /usr/local/nginx/conf/fastcgi.conf;             # 引入默认配置文件

    location ~ \.(gif|jpg|png|htm|html|css|js|flv|ico|swf)(.*) {  # 静态资源文件过期时间
                                                                  # 为12小时
        expires      12h;
    }

    set $no_cache 0;
    if ($query_string != "") {              # URI无参数的数据不进行缓存
        set $no_cache 1;
    }

    location ~ \.php(.*)$ {
        root /opt/nginx-web/phpweb;

        fastcgi_cache $fscgi_cache;        # 启用fastcgi_cache_path设置的$fscgi_cache
                                           # 的共享内存区域做缓存
        fastcgi_cache_key ${request_method}://$host$request_uri; # 设置缓存的关键字
        fastcgi_cache_lock on;             # 启用缓存锁
        fastcgi_cache_lock_age 5s;         # 启用缓存锁时,添加缓存请求的处理时间为5s
        fastcgi_cache_lock_timeout 5s;     # 等待缓存锁超时时间为5s
        fastcgi_cache_methods GET HEAD;    # 默认对GET及HEAD方法的请求进行缓存
        fastcgi_cache_min_uses 1;          # 响应数据被请求一次就将被缓存

        fastcgi_no_cache $no_cache;        # $no_cache时对当前请求不进行缓存
        fastcgi_cache_bypass $no_cache;    # $no_cache时对当前请求不进行缓存

        fastcgi_cache_use_stale error timeout invalid_header
                                updating http_500 http_503
                                http_403 http_404 http_429;        # 当出现指定的条件时,使用
                                                                   # 已经过期的缓存响应数据
        fastcgi_cache_background_update on; # 允许使用过期的响应数据时,启用后台子请求用于
                                            # 更新过期缓存,并将过期的缓存响应数据返回给客户端

        fastcgi_cache_revalidate on;       # 当缓存过期时,向后端服务器发起包含If-
                                           # Modified-Since和If-None-Match HTTP消息
                                           # 头字段的服务端校验
        fastcgi_cache_valid 200 301 302 10h; # 200 301 302状态码的响应缓存10小时
        fastcgi_cache_valid any 1m;        # 其他状态码的响应缓存1分钟

        add_header X-Cache-Status $upstream_cache_status;   # 查看缓存命中状态

        fastcgi_pass   fscgi_server;
        fastcgi_index  index.php;
        fastcgi_split_path_info       ^(.+\.php)(.*)$;      # 获取$fastcgi_path_info变量值
        fastcgi_param PATH_INFO       $fastcgi_path_info;   # 赋值给参数PATH_INFO
        include         /usr/local/nginx/conf/fastcgi.conf;                        # 引入默认参数文件
    }

    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
}