PHP `Nginx` 代理与 `FastCGI` 缓存配置优化

各位观众老爷,大家好!我是今天的主讲人,咱们今天聊聊PHP在Nginx环境下玩转代理和FastCGI缓存,让你的网站速度嗖嗖嗖往上涨!准备好了吗?咱们这就开始!

一、Nginx代理:门卫大爷的妙用

想象一下,Nginx就像你家小区门口的门卫大爷,它负责接收所有进来的请求,然后决定把这些请求分发给谁处理。这就是所谓的“反向代理”。

1. 为什么要用代理?

  • 负载均衡: 如果你家有多个PHP服务器(想象成多个辛勤工作的程序员),Nginx可以把请求均匀地分配给他们,避免某个程序员累死,其他人闲死。
  • 安全: 隐藏你的真实服务器IP地址,让坏人没法直接攻击你的PHP服务器。
  • 缓存: Nginx可以缓存一些静态资源(图片、CSS、JS),减轻PHP服务器的压力。
  • 动静分离: 让Nginx处理静态资源,PHP处理动态请求,各司其职,效率更高。

2. 如何配置Nginx代理?

咱们先来看一个简单的Nginx配置:

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://php_upstream;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

upstream php_upstream {
    server 192.168.1.101:9000;
    server 192.168.1.102:9000;
}
  • listen 80;: 监听80端口,也就是HTTP请求的默认端口。
  • server_name example.com;: 你的域名。
  • location / { ... }: 匹配所有请求。
  • proxy_pass http://php_upstream;: 把请求转发到名为php_upstream的upstream块。
  • proxy_set_header ...: 设置一些HTTP头信息,让PHP服务器知道客户端的真实IP地址等信息。这个非常重要,不然你的PHP程序可能拿不到正确的客户端IP。
  • upstream php_upstream { ... }: 定义一个upstream块,包含多个PHP服务器的地址和端口。

解释一下这些proxy_set_header的含义:

Header 作用
Host 传递原始的Host请求头,让PHP知道用户访问的是哪个域名。
X-Real-IP 传递客户端的真实IP地址。 Nginx收到请求时知道客户端IP,但是转发给PHP之后,PHP看到的IP就是Nginx的IP了。这个头就是用来把客户端真实IP传递给PHP的。
X-Forwarded-For 如果客户端经过了多个代理服务器,这个头会包含所有代理服务器的IP地址,用逗号分隔。$proxy_add_x_forwarded_for会把当前的客户端IP添加到已有的X-Forwarded-For头中。
X-Forwarded-Proto 传递客户端使用的协议(HTTP或HTTPS)。如果你的Nginx配置了SSL,并且希望PHP知道用户是通过HTTPS访问的,这个头就很有用。

二、FastCGI缓存:给PHP穿上防弹衣

FastCGI缓存就像一个盾牌,它可以把PHP生成的页面缓存起来,下次用户访问相同的页面时,直接从缓存中读取,而不需要再次执行PHP代码。这样可以大大减轻PHP服务器的压力,提高网站的响应速度。

1. 为什么要用FastCGI缓存?

  • 性能提升: 显著提高网站的响应速度,尤其是在访问量大的时候。
  • 减轻服务器压力: 减少PHP的执行次数,降低CPU和内存的使用率。
  • 提高用户体验: 更快的页面加载速度,让用户感觉更流畅。

2. 如何配置FastCGI缓存?

fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=php_cache:100m inactive=60m max_size=1g;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout invalid_header http_500 http_502 http_503 http_504;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;

server {
    listen 80;
    server_name example.com;
    root /var/www/example.com;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ .php$ {
        fastcgi_pass unix:/run/php/php7.4-fpm.sock; # 你的PHP-FPM socket路径
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        fastcgi_cache php_cache;
        fastcgi_cache_valid 200 301 302 60m; # 缓存HTTP状态码为200, 301, 302 的页面60分钟
        fastcgi_cache_valid any 10m;        # 缓存所有其他状态码的页面10分钟 (可以根据需要调整)
        fastcgi_cache_min_uses 1;          # 页面至少被访问一次才会被缓存
        fastcgi_cache_bypass $skip_cache;  # 如果$skip_cache为真,则绕过缓存
        fastcgi_no_cache $skip_cache;     # 如果$skip_cache为真,则不使用缓存
    }

    # 禁止访问 .ht 文件
    location ~ /.ht {
        deny all;
    }
}

咱们来逐行解释一下这些配置:

  • fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=php_cache:100m inactive=60m max_size=1g;: 定义FastCGI缓存的路径、层级、缓存区名称、过期时间、最大容量。

    • /var/cache/nginx: 缓存文件存放的目录。
    • levels=1:2: 设置目录层级,可以提高缓存文件的查找速度。
    • keys_zone=php_cache:100m: 定义一个名为php_cache的缓存区,大小为100MB。这个缓存区用来存储缓存键和元数据。
    • inactive=60m: 如果一个缓存文件在60分钟内没有被访问,就会被删除。
    • max_size=1g: 缓存目录的最大容量为1GB。
  • fastcgi_cache_key "$scheme$request_method$host$request_uri";: 定义缓存键的生成规则。这里使用了协议、请求方法、主机名和URI作为缓存键。这意味着只有完全相同的请求才会被认为是相同的页面,从而命中缓存。
  • fastcgi_cache_use_stale error timeout invalid_header http_500 http_502 http_503 http_504;: 在服务器出错、超时或者返回错误状态码时,可以使用过期的缓存。这可以提高网站的可用性,即使后端服务器出现问题,用户仍然可以访问到缓存的页面。
  • fastcgi_ignore_headers Cache-Control Expires Set-Cookie;: 忽略来自PHP的Cache-ControlExpiresSet-Cookie头信息。因为Nginx自己会管理缓存,所以不需要PHP来控制。
  • fastcgi_cache php_cache;: 启用名为php_cache的缓存区。
  • fastcgi_cache_valid 200 301 302 60m;: 缓存HTTP状态码为200、301、302的页面60分钟。
  • fastcgi_cache_valid any 10m;: 缓存所有其他状态码的页面10分钟。
  • fastcgi_cache_min_uses 1;: 页面至少被访问一次才会被缓存。
  • fastcgi_cache_bypass $skip_cache;: 如果$skip_cache变量为真,则绕过缓存。
  • fastcgi_no_cache $skip_cache;: 如果$skip_cache变量为真,则不使用缓存。

3. 如何控制缓存?

有时候,你可能需要控制哪些页面应该被缓存,哪些页面不应该被缓存。比如,用户登录后的页面就不应该被缓存。你可以通过设置$skip_cache变量来实现:

<?php
// 在你的PHP代码中
if (isset($_SESSION['user_id'])) {
    header('X-Accel-Expires: 0'); // 禁用缓存
    header('Cache-Control: no-cache, no-store, must-revalidate');
    header('Pragma: no-cache');
}
?>

然后在Nginx配置中:

map $request_uri $skip_cache {
    default 0;
    ~*"/wp-admin/|/xmlrpc.php|/wp-.*.php|/feed/|index.php|sitemap(_index)?.xml" 1; # WordPress常见的不缓存的URL
    ~*"/private/" 1; #  以/private/开头的URL不缓存
    ~*"?nocache=1" 1; # URL中包含?nocache=1时不缓存
    if ($http_cookie ~* "wordpress_logged_in_|wp-postpass_") {
        set $skip_cache 1;  # 如果用户已登录,则不缓存
    }
}
  • map $request_uri $skip_cache { ... }: 定义一个map块,根据$request_uri变量的值来设置$skip_cache变量的值。
  • default 0;: 默认情况下,$skip_cache的值为0,表示启用缓存。
  • ~*"/wp-admin/|/xmlrpc.php|/wp-.*.php|/feed/|index.php|sitemap(_index)?.xml" 1;: 如果请求的URI匹配这些正则表达式,则$skip_cache的值为1,表示不缓存。 这里针对WordPress常见的URL进行了排除。
  • ~*"/private/" 1;: 如果URL包含/private/,则跳过缓存。可以自定义任何你想要排除的URL。
  • ~*"?nocache=1" 1;: 如果URL中包含?nocache=1,则跳过缓存。
  • if ($http_cookie ~* "wordpress_logged_in_|wp-postpass_") { set $skip_cache 1; }: 如果用户已登录(通过Cookie判断),则跳过缓存。

三、优化技巧:让缓存飞起来

  1. 合理设置缓存时间: 缓存时间太短,缓存效果不明显;缓存时间太长,可能会导致用户看到过时的内容。根据你的网站内容更新频率,合理设置缓存时间。
  2. 区分静态资源和动态页面: 静态资源(图片、CSS、JS)可以缓存更长时间,动态页面应该缓存较短时间或者不缓存。
  3. 使用CDN: CDN(内容分发网络)可以把你的网站内容缓存到全球各地的服务器上,让用户从离他们最近的服务器上访问,提高访问速度。
  4. 监控缓存命中率: 通过Nginx的日志或者监控工具,可以查看缓存命中率。如果缓存命中率太低,说明缓存配置可能需要调整。
  5. 清理缓存: 有时候,你需要手动清理缓存,比如在网站更新或者修改了配置之后。你可以通过删除缓存目录中的文件来清理缓存。

四、常见问题:手把手教你排雷

  1. 缓存未生效: 检查Nginx配置是否正确,缓存目录是否存在,权限是否正确,PHP代码是否设置了禁用缓存的头信息。
  2. 用户看到过时的内容: 缩短缓存时间,或者手动清理缓存。
  3. 缓存命中率低: 检查缓存键的生成规则是否合理,是否有很多不同的URL访问相同的页面。
  4. 服务器CPU占用率高: 检查是否缓存了大量的动态页面,或者缓存时间太短,导致缓存频繁更新。

五、总结:让你的网站速度起飞!

通过合理配置Nginx代理和FastCGI缓存,可以让你的PHP网站速度得到显著提升,减轻服务器压力,提高用户体验。记住,没有一劳永逸的配置,需要根据你的网站情况不断调整和优化。

希望今天的讲座对你有所帮助!如果有什么问题,欢迎提问。 祝大家编程愉快,网站速度飞起!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注