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>")
            ';
        }
    }


}
相关文章
相关标签/搜索