使用Nginx的proxy_cache功能缓存MT Tags

This is a sitelog of Easun.org.

一直以来,本站的 MT tag search 都使用的自己写的 Perl 脚本来缓存 后台 mt-search.cgi 的结果。 前台伪静态成 tag/key 模式。

详细介绍在这里:

  1. MT归档页面变更以及Tags搜索页面cache机制的变更
  2. 本站使用的文本缓存Tag搜索的Perl脚本

用这个自写脚本运行5年了。运行良好且节约大量资源。

今年web服务器平台变成 nginx, 突发奇想,是否可以废掉这个脚本,使用 nginxproxy_cache 缓存功能来完成这个功能? 因为 MT后台其实是通过 PSGI 反代完成的。

研究了一番,成功解决了这个问题。
当然,为了兼容原来的 路径 和 简化 nginxRewrite, 自己修改了 Movable TypeAPP/Search.pmAPP/Search/TagSearch.pm 文件。 主要的意图是 分解 tag=Key/ntag=key&page=n

MT修改如下:

APP/Search.pm
修改

perlsub init_request {
....
my $page = $q->param('page') ? $q->param('page') : 1;
....
}

为:

perlsub init_request {
....
 my $tag_page = 1; 
 if ($q->param('tag') )
 {
 my $path_info =  $q->param('tag');
    $path_info =~s{^/}{};
    $path_info =~s{/}{;}g;

   (my $tag, $tag_page, my $r) = split ';', $path_info;  
   $tag_page  = 1 if ($tag_page !~ /^[0-9]+$/);
   $tag_page = 1 if ($tag_page  == 0);
 }

 my $page = $q->param('page') ? $q->param('page') : $tag_page;
....
}

APP/Search/TagSearch.pm
修改

perlsub search_terms {
....
 my $search_string = $q->param('tag') || $q->param('search');
....
}

为:

perlsub search_terms {
....
 my $path_info =  $q->param('tag');
 if ( $path_info )
 {
  $path_info =~s{^/}{};
  $path_info =~s{/}{;}g; 
  (my $tag, my $tag_page, my $r) = split ';', $path_info; 
   $path_info = $tag; 
 }   
 my $search_string = $path_info || $q->param('search');
....
}

nginx 相关配置为:

http 段,一般在nginx.conf中

nginxhttp {
 .....    
   # 代理全局配置
   proxy_connect_timeout 5;
   proxy_read_timeout   60;
   proxy_send_timeout   5;
   proxy_buffer_size 16k;
   proxy_buffers4 64k;
   proxy_busy_buffers_size 128k;
   proxy_temp_file_write_size 128k;
   proxy_temp_path   /usr/share/nginx/cache/temp;
   # 临时文件目录
   proxy_cache_path  /usr/share/nginx/cache/path levels=1:2 keys_zone=cache_one:5m inactive=7d max_size=1g;
   # 5m为内存占用,1g为最大硬盘占用,cache_one为缓存区名字,如果修改则下文的配置亦要相应修改。
   #---- 
 .....
}

server 段,一般在conf.d\youweb.conf中

nginx # set proxy for Tags
 location ^~ /blog/tag/ {

 index index.html;
 proxy_cache_key "$scheme://$host$request_uri";
 #缓存key规则,用于自动清除缓存。

 proxy_cache cache_one; 
 #缓存区名称,与前面定义的相同

 proxy_cache_revalidate on;
 proxy_cache_lock on;

 proxy_set_header   X-Real-IP  $remote_addr;
 proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;


 proxy_cache_use_stale invalid_header error timeout updating http_500 http_502  http_503 http_504;
 #当后端出现错误、更新中,超时、502状态时启用过期缓存。

 proxy_http_version1.1;
 add_header X-Cache-Status $upstream_cache_status;

 proxy_cache_valid  200 304 1d;
 proxy_cache_valid 301 3d;
 proxy_cache_valid any 10s;
 proxy_ignore_headers  Set-Cookie Cache-Control Vary;
 proxy_hide_header Cache-Control;
 proxy_hide_header Set-Cookie;
 proxy_hide_header X-Powered-By;


 if (!-e $request_filename){ 
    rewrite ^(.*)/blog/tag/(.+)$  $1/cgi-bin/mt/mt-search.cgi?IncludeBlogs=2&limit=20&tag=$2  break;
    proxy_pass   http://starman; 
    #指定后端ip,可以加端口
    expires     1d;
 }

 }    

保证 /usr/share/nginx/cache/temp/usr/share/nginx/cache/path 这两个保存 cache 的目录存在且可读写。 重启 nginx 即可生效。

本次修改最大程度的兼容了原来的流程, 并无需再次修改后台搜索模板。具体效果可以参考本站 Tags。

参考资料

1.动态PHP电商网站伪静态的 Nginx反向代理Cache缓存终极设置
2.Jerry Qu: 本博客 Nginx 配置之完整篇