Nginx反向代理实现动静分离

2018-04-18|Categories: Cluster, Linux|Tags: |

本文属于Nginx系列的第三篇,前两篇分别是:

什么是动静分离

动静分离是将网站静态资源(HTML,JavaScript,CSS,图片等文件)与后台应用(Java,PHP,Python等)分开部署,提高用户访问静态代码的速度,降低对后台应用访问。

测试环境

IP 域名 用途 服务器应用程序 安装命令
172.16.125.71 c.com 反向代理服务器 Nginx (EPEL repo) yum install nginx
172.16.125.72 后端服务器,
处理动态资源
httpd, mod_php yum install httpd php
172.16.125.73 后端服务器,
提供静态资源
httpd, php-fpm yum install httpd php-fpm
172.16.125.1 客户端

域名解析

以下操作在172.16.125.1机器上执行:

echo '172.16.125.71 www.c.com c.com' >> /etc/hosts

准备动态资源(php脚本)

以下操作在172.16.125.72机器上执行:

echo '<?php echo "<h1>172.16.125.72</h1>"; phpinfo(); ?>' > /var/www/html/index.php

以下操作在172.16.125.73机器上执行:

mkdir -p /data/fcgi/
echo '<?php echo "172.16.125.73 with FastCGI <br>"."\n"; echo time(); ?>' > /data/fcgi/index.php

准备静态资源(图片)

以下操作在172.16.125.73机器上执行:

cp /usr/share/pixmaps/faces/sky.jpg /var/www/html/

通过ngx_http_proxy_module实现

以下操作在172.16.125.71机器上执行:

location ~* \.php$ {
    proxy_pass         http://172.16.125.72;
    # proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
}

location ~* \.(html?|js|css|txt|ico|jpe?g|png|gif)$ {
    proxy_pass         http://172.16.125.73;
    # proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
}

此处只记录关键的配置,其它相关配置已在《初识Nginx》《Nginx常用配置》记录,不再赘述。

以下操作在172.16.125.1机器上执行:

curl --noproxy '*' -kLsI c.com/sky.jpg
curl --noproxy '*' -kLsI c.com/index.php

实际上,对于php脚本这种动态内容,通常会使用Nginx的ngx_http_fastcgi_module模块来处理。

通过ngx_http_fastcgi_module实现

为什么使用FastCGI代理

Nginx中的FastCGI代理通常用于为不直接处理客户端请求的应用程序服务器转换客户端请求。FastCGI是基于早期CGI(通用网关接口)的协议,旨在通过不将每个请求作为单独的进程运行来提高性能。它用于有效地与处理动态内容请求的服务器进行交互。

Nginx中FastCGI代理的主要用途之一是PHP处理。与Apache可以直接使用mod_php模块处理PHP处理不同,Nginx必须依靠单独的PHP处理器来处理PHP请求。大多数情况下,这个处理是通过php-fpm完成的,这是一款经过广泛测试可与Nginx合作的PHP处理器。

https://www.digitalocean.com/community/tutorials/understanding-and-implementing-fastcgi-proxying-in-nginx#why-use-fastcgi-proxying

如何配置FastCGI代理PHP动态页面

以下操作在172.16.125.73机器上执行:

# 1. 让php-fpm监听来自所有地址的请求
# 2. 允许任意IP客户端的连接(适合nginx与php-fpm不在同一台机)
# 3. 启用访问日志,便于排错
sed -i.bak -r -e 's/^(listen = )127.0.0.1:(9000)/\1\2/'                 \
                -e 's/^(listen.allowed_clients = 127.0.0.1)/;\1/'       \
                -e '$a access.log = /var/log/php-fpm/www-access.log'    \
                /etc/php-fpm.d/www.conf

systemctl restart php-fpm

以下操作在172.16.125.71机器上执行:

location ~* \.php$ {
    fastcgi_pass   172.16.125.73:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME /data/fcgi$fastcgi_script_name;
    include        fastcgi_params;
}

查看FastCGI服务器状态

以下操作在172.16.125.73机器上执行:

# 1. 启用php-fpm内置的`/status`页面
# 2. 启用php-fpm内置的`/ping`页面
sed -r -e 's@^;(pm.status_path = /status)@\1@'  \
        -e 's@^;(ping.path = /ping)@\1@'        \
        /etc/php-fpm.d/www.conf
        
systemctl restart php-fpm

以下操作在172.16.125.71机器上执行:

location ~* ^/(status|ping)$ {
    fastcgi_pass    172.16.125.73:9000;
    fastcgi_param   SCRIPT_FILENAME $fastcgi_script_name;
    include         fastcgi_params;
}

以下操作在172.16.125.1机器上执行:

$ curl --noproxy '*' -Lk c.com/ping
pong
$ curl --noproxy '*' -Lk c.com/status
pool:                 www
process manager:      ondemand
start time:           08/Apr/2018:18:45:30 +0800
start since:          945392
accepted conn:        55
listen queue:         0
max listen queue:     0
listen queue len:     128
idle processes:       0
active processes:     1
total processes:      1
max active processes: 1
max children reached: 0
slow requests:        0

启用FastCGI代理缓存

以下操作在172.16.125.71机器上执行:

fastcgi_cache_path      /data/nginx/fcgi_cache levels=1:2
                        keys_zone=fcgi_cache:10m
                        inactive=3m max_size=1g;
fastcgi_cache_key       $scheme$request_method$host$request_uri;
fastcgi_cache           fcgi_cache;
fastcgi_cache_valid     200 301 302 3m;
fastcgi_cache_valid     any 1m;

add_header      X-Cache-Status $upstream_cache_status;
# `$upstream_addr`表示后端服务器地址,只应该用于测试环境
add_header      X-Cache-From $upstream_addr;
mkdir -p /data/nginx/fcgi_cache

以下操作在172.16.125.1机器上执行:

第一次:

$ curl --noproxy '*' -LksI c.com/index.php
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.12.2
Date: Thu, 19 Apr 2018 09:13:40 GMT
Content-Type: text/html
Content-Length: 161
Connection: keep-alive
Location: https://c.com/index.php

HTTP/1.1 200 OK
Server: nginx
Date: Thu, 19 Apr 2018 09:13:40 GMT
Content-Type: text/html
Connection: keep-alive
Vary: Accept-Encoding
X-Powered-By: PHP/5.4.16
X-Cache-Status: MISS
X-Cache-From: 172.16.125.73:9000

从输出的最后两行可以看到,响应的内容直接来自后端服务器172.16.125.73:9000,因为前端代理服务器上还没有缓存,所以缓存未命中(MISS)。

第二次:

$ curl --noproxy '*' -LksI c.com/index.php
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.12.2
Date: Thu, 19 Apr 2018 09:14:19 GMT
Content-Type: text/html
Content-Length: 161
Connection: keep-alive
Location: https://c.com/index.php

HTTP/1.1 200 OK
Server: nginx
Date: Thu, 19 Apr 2018 09:14:19 GMT
Content-Type: text/html
Connection: keep-alive
Vary: Accept-Encoding
X-Powered-By: PHP/5.4.16
X-Cache-Status: HIT

缓存已命中(HIT)。

Leave A Comment