如何在您的VPS上使用Nginx设置FastCGI缓存

来自菜鸟教程
跳转至:导航、​搜索

序幕


Nginx 包含一个 FastCGI 模块,该模块具有用于缓存从 PHP 后端提供的动态内容的指令。 设置此设置消除了对额外页面缓存解决方案的需要,例如反向代理(想想 Varnish)或特定于应用程序的插件。 也可以根据请求方法、URL、cookie 或任何其他服务器变量将内容从缓存中排除。

在您的 VPS 上启用 FastCGI 缓存


本文假设您已经在您的 Droplet 上使用 PHP 设置和配置了 Nginx。 编辑必须启用缓存的 Virtual Host 配置文件。

nano /etc/nginx/sites-enabled/vhost

将以下行添加到 server { } 指令之外的文件顶部:

fastcgi_cache_path /etc/nginx/cache levels=1:2 keys_zone=MYAPP:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";

“fastcgi_cache_path”指令指定缓存的位置(/etc/nginx/cache)、大小(100m)、内存区域名称(MYAPP)、子目录级别和inactive`计时器。

该位置可以是硬盘上的任何位置; 但是,大小必须小于 Droplet 的 RAM + Swap,否则您将收到“无法分配内存”的错误消息。 我们将查看清除部分中的“级别”选项——如果在“非活动”选项指定的特定时间(此处为 60 分钟)内未访问缓存,则 Nginx 将其删除。

“fastcgi_cache_key”指令指定缓存文件名将如何散列。 Nginx 根据该指令使用 MD5 对访问的文件进行加密。

接下来,将传递 PHP 请求的 location 指令移动到 php5-fpm。 在“location ~ .php$ { }”中添加以下行。

fastcgi_cache MYAPP;
fastcgi_cache_valid 200 60m;

“fastcgi_cache”指令引用我们在“fastcgi_cache_path”指令中指定的内存区域名称,并将缓存存储在该区域中。

默认情况下,Nginx 将缓存对象存储由以下任何标头指定的持续时间:X-Accel-Expires/Expires/Cache-Control.

如果这些标头丢失,“fastcgi_cache_valid”指令用于指定默认缓存生命周期。 在我们上面输入的语句中,仅缓存状态代码为 200 的响应。 也可以指定其他响应代码。

做一个配置测试

service nginx configtest

如果一切正常,请重新加载 Nginx

service nginx reload

完整的 vhost 文件将如下所示:

fastcgi_cache_path /etc/nginx/cache levels=1:2 keys_zone=MYAPP:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";

server {
    listen   80;
    
    root /usr/share/nginx/html;
    index index.php index.html index.htm;

    server_name example.com;

    location / {
        try_files $uri $uri/ /index.html;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_cache MYAPP;
        fastcgi_cache_valid 200 60m;
    }
}

接下来我们将做一个测试,看看缓存是否有效。

在您的 VPS 上测试 FastCGI 缓存


创建一个输出 UNIX 时间戳的 PHP 文件。

 /usr/share/nginx/html/time.php

插入

<?php
echo time();
?>

使用 curl 或您的网络浏览器多次请求此文件。

root@droplet:~# curl http://localhost/time.php;echo
1382986152
root@droplet:~# curl http://localhost/time.php;echo
1382986152
root@droplet:~# curl http://localhost/time.php;echo
1382986152

如果缓存工作正常,您应该在所有请求上看到与缓存响应相同的时间戳。

执行缓存位置的 递归 列表以查找此请求的缓存。

root@droplet:~# ls -lR /etc/nginx/cache/
/etc/nginx/cache/:
total 0
drwx------ 3 www-data www-data 60 Oct 28 18:53 e

/etc/nginx/cache/e:
total 0
drwx------ 2 www-data www-data 60 Oct 28 18:53 18

/etc/nginx/cache/e/18:
total 4
-rw------- 1 www-data www-data 117 Oct 28 18:53 b777c8adab3ec92cd43756226caf618e

命名约定将在清除部分解释。

我们还可以让 Nginx 在响应中添加一个“X-Cache”标头,指示缓存是否丢失或命中。

server { } 指令上方添加以下内容:

add_header X-Cache $upstream_cache_status;

重新加载 Nginx 服务并使用 curl 执行详细请求以查看新标头。

root@droplet:~# curl -v http://localhost/time.php
* About to connect() to localhost port 80 (#0)
*   Trying 127.0.0.1...
* connected
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /time.php HTTP/1.1
> User-Agent: curl/7.26.0
> Host: localhost
> Accept: */*
>
* HTTP 1.1 or later with persistent connection, pipelining supported
< HTTP/1.1 200 OK
< Server: nginx
< Date: Tue, 29 Oct 2013 11:24:04 GMT
< Content-Type: text/html
< Transfer-Encoding: chunked
< Connection: keep-alive
< X-Cache: HIT
<
* Connection #0 to host localhost left intact
1383045828* Closing connection #0

设置缓存例外


不应缓存某些动态内容,例如需要身份验证的页面。 可以根据“request_uri”、“request_method”和“http_cookie”等服务器变量将此类内容排除在缓存之外。

这是必须在 server{ } 上下文中使用的示例配置。

#Cache everything by default
set $no_cache 0;

#Don't cache POST requests
if ($request_method = POST)
{
    set $no_cache 1;
}

#Don't cache if the URL contains a query string
if ($query_string != "")
{
    set $no_cache 1;
}

#Don't cache the following URLs
if ($request_uri ~* "/(administrator/|login.php)")
{
    set $no_cache 1;
}

#Don't cache if there is a cookie called PHPSESSID
if ($http_cookie = "PHPSESSID")
{
    set $no_cache 1;
}

要将“$no_cache”变量应用于适当的指令,请将以下行放在 location ~ .php$ { }

fastcgi_cache_bypass $no_cache;
fastcgi_no_cache $no_cache;

“fasctcgi_cache_bypass”指令忽略与我们之前设置的条件相关的请求的现有缓存。 如果满足指定条件,“fastcgi_no_cache”指令根本不会缓存请求。

清除缓存


缓存的命名约定基于我们为“fastcgi_cache_key”指令设置的变量。

fastcgi_cache_key "$scheme$request_method$host$request_uri";

根据这些变量,当我们请求“http://localhost/time.php”时,实际值如下:

fastcgi_cache_key "httpGETlocalhost/time.php";

将此字符串通过 MD5 散列 将输出以下字符串:

b777c8adab3ec92cd43756226caf618e

这将形成缓存的文件名,就像我们输入“levels=1:2”的子目录一样。 因此,目录的第一级将命名为该 MD5 字符串最后一个字符 e1 字符; 第二级将具有第一级之后的最后 2 个字符,即 18。 因此,这个缓存的整个目录结构如下:

/etc/nginx/cache/e/18/b777c8adab3ec92cd43756226caf618e

基于这种缓存命名格式,您可以使用您喜欢的语言开发一个清除脚本。 对于本教程,我将提供一个简单的 PHP 脚本来清除 __POST__ed URL 的缓存。

/usr/share/nginx/html/purge.php

插入

<?php
$cache_path = '/etc/nginx/cache/';
$url = parse_url($_POST['url']);
if(!$url)
{
    echo 'Invalid URL entered';
    die();
}
$scheme = $url['scheme'];
$host = $url['host'];
$requesturi = $url['path'];
$hash = md5($scheme.'GET'.$host.$requesturi);
var_dump(unlink($cache_path . substr($hash, -1) . '/' . substr($hash,-3,2) . '/' . $hash));
?>

使用要清除的 URL 向此文件发送 POST 请求。

curl -d 'url=http://www.example.com/time.php' http://localhost/purge.php

该脚本将根据缓存是否被清除而输出 truefalse。 确保从缓存中排除此脚本并限制访问。

提交者:http: [[“%3Ca|//jesin.tk/]] [[“%3C/a|”>杰辛A]]