## 原理
主要使用了 `nginx` 的 `memcached_module` 模块,直接从 `Memcache` 服务器中读取并输出。
如若不存在,则执行相应程序,并将结果写入 `Memcahce`。
结构图:
主要流程是:
用户的请求进来,`Nginx` 向 `Memcache` 获取数据,如若成功,则直接返回给客服端。
如若失败,则 `Nginx` 会报 `not found` 错误,这个时候,需要 `rewirte` 执行相关应用程序,
在页面渲染结束后,将结果写入 `Memcache` 。那么下次请求,将直接从 `Memcache` 获取。
## 具体实现
**### Nginx 的配置**
upstream memcacheds {
server 127.0.0.1:11211;
}
server {
... # 这里的配置不变
location @rewrite {
rewrite ^/(.*)$ /index.php?/$1 last;
}
set $memcached_key 0; # 初始化一下$memcached_key
location ~ /(articles) {
set $memcached_key $host$uri; # 用url作为标识
add_header X-IMJCW-Key $memcached_key; # 加到header里,方便管理
default_type text/html;
memcached_connect_timeout 1s;
memcached_read_timeout 2s;
memcached_send_timeout 2s;
memcached_pass memcacheds;
memcached_gzip_flag 2;
error_page 404 502 504 = @rewrite;
}
... # 这里的配置不变
location ~ \.php$ {
... # 这里的配置不变
fastcgi_param X-MEMCACHE-KEY $memcached_key; # 设置参数,为程序是否需要缓存页面做判断
... # 这里的配置不变
}
... # 这里的配置不变
}
### PHP代码
<?php
// 初始化一下 HTML,这里就不动态生成了
$html = 'Hello World';
// 因为缓存的是页面,所以判断一下请求方式是否是 GET
// 同时判断 $_SERVER 里是否存在 X-MEMCACHE-KEY,并且不为空
if ($_SERVER['REQUEST_METHOD'] != 'GET' || !isset($_SERVER['X-MEMCACHE-KEY'])
|| !$_SERVER['X-MEMCACHE-KEY']) {
echo $html;
exit();
}
// 获取 X-MEMCACHE-KEY
$memcachedKey = $_SERVER['X-MEMCACHE-KEY'];
// 连接 Memcached
$memcached = new \Memcached();
$memcached->addServer('127.0.0.1', '11211', false);
// 存储
$memcached->set($memcachedKey, $html);
// 留个证据
header('X-IMJCW: miss');
header('X-IMJCW-Key: ' . $xMemcacheKey);
echo $html;
## 示例
`Tips:` 这里的示例不是由上述代码执行输出的,逻辑是一样的。
第一次访问页面:
第二次访问页面:
## 页面输出乱码的问题
在实际应用中,我发现效果并没有我想象的那么美好,主要原因是:页面输出乱码了。
经过多方面查询和向同事的请教,最终得出的结论是:
由于存储到 `Memcache` 里的数据太大,以至于压缩了一遍后,还是很大,于是又压缩…就这样,
输出的时候是压缩后的数据,结果造成了页面乱码的问题。
至于解决方案,有两个:
**一、关闭压缩功能**
<?php
// 获取 X-MEMCACHE-KEY
$memcachedKey = $_SERVER['X-MEMCACHE-KEY'];
// 连接 Memcached
$memcached = new \Memcached();
$memcached->addServer('127.0.0.1', '11211', false);
$memcached->setOption(\Memcached::OPT_COMPRESSION, false);
// 存储
$memcached->set($memcachedKey, $html);
**二、修改 `PHP` 配置,修改 `Memcache` 压缩阈值**
有则修改,无则添加。
[memcached]
memcached.compression_threshold = 1048576
修改完成以后,需要重启 `php-fpm`。