使用Nginx的proxy_cache功能緩存MT Tags

This is a sitelog of www.kcpon.com.

一直以來,本站的 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 配置之完整篇