Nginx cache初體驗

前言

你們都知道cache對於網站性能的重要性,提升用戶響應速度,減輕後端壓力,節省資源等等。一談到cache實際上是個很大話題,從前端瀏覽器到最終響應請求的服務器可能要通過不少次跳轉,每次跳轉通過的服務器都有機會提供cache。單從成本上而言,越靠近用戶的cache越經濟,實際狀況中都須要根據當前線上的業務部署狀況,開發成本收益比,可維護性等因素考慮採起在哪一個地方cache,如何cache。粗線條一點根據cache的位置,通常會有瀏覽器,web服務器,CDN和應用服務器cache等。這裏我結合最近本身完成的nginx服務器上的cache工做,談一下nginx提供了哪些實用的cache服務。php


Nginx承擔反向代理服務器的工做,通常它處理的業務都是比較通用的處理,或者說通常不會處理很個性化的請求。好比安全,解壓縮功能對全部請求都是通用的,這是nginx能夠搞定的,它通常不會終結業務類的處理,而是將他們交給後面的應用服務器。正是由於Nginx的這種特性,若是在nginx節點上作cache,通常cache的是整個http請求的response。天然cache的key也通常從http請求的url和參數得來。目前我接觸到兩種nginx cache方式:html

  • 本地文件系統cache (proxy_cache )前端

  • 集中的內存cache (srcache-nginx-module)node

Proxy_cache

這是Nginx原生的ngx_http_proxy_module自帶的cache解決方案。http response的內容以文件的形式存在了本地的文件系統,同時開了一個share memory冗餘存key值能夠快速判斷是否cache命中。通常會這麼部署。
clipboard.png
如何配置nginx使能proxy cache,能夠參考NGINX CONTENT CACHINGA Guide to Caching with NGINX
由於這個方案是本地文件系統存cache,能夠比較容易理解具備如下缺點:nginx

  1. cache冗餘,不一樣的nginx node間分別存cache。git

  2. cache一致性,由於是冗餘的,各個節點間cache的失效時間是不一樣步的。github

  3. cache訪問速度慢,讀磁盤天然會慢一些。web

  4. cache效率低,由於各個node各有本身的cache不共享,即便某個node cache裏存了某個請求,若是另外的nginx node來處理請求仍是cache miss。redis

基於上面的問題,有更好的方案,好比agentzhang的srcache-nginx-module模塊。後端

srcache-nginx-module

這個模塊旨在構建一個cache中間層,cache的存儲介質是集中的,通常使用memcached或者redis。這樣解決了冗餘,也就解決了上面的各類問題,同時速度也快不少。對比着,它是這樣部署的。另外集中的cache存儲能夠選擇redis或者memcached(memc-nginx-module提供API),memcached集羣方案須要nginx配置配合解決。

clipboard.png

順便感謝agentzhang將Lua引入到nginx。nginx出色的擴展性已經很靈活了,lua-nginx-module將腳本語言處理文本的便捷性直接引入nginx,使得開發人員能夠方便的在http request/response處理的各個階段都能嵌入定製的功能。好比我能夠很方便的使用lua模塊在rewrite階段根據url和args生成定製的cache key--刨除一些參數(好比不影響response結果的那些參數)。附上兩篇不錯的lua-nginx-module的資料:
lua-nginx-module
OpenResty最佳實踐
使用memc-nginx和srcache-nginx模塊構建高效透明的緩存機制

另外附上本身的nginx.conf以備後查。

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
error_log  logs/error.log  info;

pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;
    #
    # cache server 1
    upstream memcache1 {
        server 127.0.0.1:11211;
        #keepalive 512 single;
    }
    # cache server 2
    #upstream memcache2 {
    #    server 127.0.0.1:11211;
    #}
    upstream_list memcache_servers memcache1;

    server {
        listen       8080;
        server_name  localhost;
        #memc-nginx-module
        location /memc {
            internal;
            memc_connect_timeout 100ms;
            memc_send_timeout 100ms;
            memc_read_timeout 100ms;
            set $memc_key $query_string;
            set $memc_exptime 30;
            set_hashed_upstream $backend memcache_servers  $memc_key;
            memc_pass $backend;
        }
        location /s {
            # key gerneration for cache
        set $args_for_key '';
            rewrite_by_lua '
               ngx.var.args_for_key = string.gsub(ngx.var.args, "queryid=%d+","queryid=0")
            ';
            #echo $args_for_key;
            srcache_fetch GET /memc $uri$args_for_key;
            srcache_store PUT /memc $uri$args_for_key;
            proxy_pass http://192.168.1.100:8000;
        }
        location / {
            root   /var/www;
            index  index.html index.htm index.php;
        }
        
        
    }
    server {
        listen 8081;
        location / {
            default_type text/html;
            content_by_lua '
                ngx.say("<p>hello, world</p>")
            ';
        }
    }


}
相關文章
相關標籤/搜索