nginx+memcache增長全站緩存系統

項目背景:html

    當生產產生異常流量而又沒法快速定位流量來源,爲減小數據庫負載,經過全局緩存預熱,以及快速切緩存開關,來控制全站流量導入緩存,減小異常狀況下對數據庫的壓力。java

 

整體實現爲nginx+memcache+Luanginx

 

1 首先查看一下nginx版本:git

 

  [root@squid1 sbin]# /usr/local/nginx/sbin/nginx -vgithub

Tengine version: Tengine/2.1.2 (nginx/1.6.2)redis

 

此處nginx使用的是tengine版,nginx版本必須1.6.0以上。不是則到 http://tengine.taobao.org 下載tengine最新版本。算法

 

2 安裝Lua環境數據庫

 

  到官網http://luajit.org/download.html 下載安裝包到本地並解壓緩存

  tar –zxvf /usr/local/src/LuaJIT-2.0.4.tar.gz服務器

  cd LuaJIT-2.0.4

  make&&make install

  查看是否成功:

  [root@puppetmaster LuaJIT-2.0.4]# ls /usr/local/lib

libluajit-5.1.a  libluajit-5.1.so  libluajit-5.1.so.2  libluajit-5.1.so.2.0.4  lua  pkgconfig

 

[root@puppetmaster LuaJIT-2.0.4]# ls /usr/local/include/luajit-2.0

lauxlib.h  luaconf.h  lua.h  lua.hpp  luajit.h  lualib.h

 

編輯/etc/profile文件添加環境變量:

export LUAJIT_LIB=/usr/local/lib

export LUAJIT_INC=/usr/local/include/luajit-2.0

export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH

 

3 下載nginx所需模塊源碼包到/usr/local/src下,並解壓

      

 https://github.com/simpl/ngx_devel_kit (nginx開發環境模塊)

https://github.com/openresty/set-misc-nginx-module (nginx變量函數,算法模塊)

https://github.com/openresty/srcache-nginx-module (緩存http請求,響應定製模塊)

https://github.com/openresty/memc-nginx-module (memcached緩存模塊)

https://github.com/openresty/lua-nginx-module (lua腳本開發框架模塊)

 

 4  tengine再編譯

      Tengine的dso_tool是動態加載的工具,用法爲:

         /usr/local/nginx/sbin/dso_tool --add-module=/usr/local/src/memc-nginx-module-master

可是並非全部模塊均可以動態加載,因此這裏用再編譯靜態加載。

 

編譯前查看一下如今程序的編譯參數:

[root@puppetmaster sbin]# /usr/local/nginx/sbin/nginx –V

 

tar -zxvf /usr/local/src/tengine-2.1.2.tar.gz

cd /usr/local/src/tengine-2.1.2

在以前編譯參數上再將下載的nginx模塊參數添加上編譯:

./configure --prefix=/usr/local/nginx --user=nginx --group=nginx

--with-http_concat_module

--with-http_addition_module

--with-http_dav_module

--with-http_gzip_static_module

--with-http_image_filter_module

--with-http_realip_module

--with-http_stub_status_module

--with-http_ssl_module

--with-http_sub_module

--with-ipv6

--with-file-aio

--with-sha1=/usr/include/openssl

--with-md5=/usr/include/openssl

--with-mail

--with-mail_ssl_module

--with-http_xslt_module

--with-http_geoip_module

--with-http_flv_module

--with-http_mp4_module

--with-http_gzip_static_module

--with-http_random_index_module

--with-http_secure_link_module

--with-http_degradation_module

--with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic'

--with-ld-opt=-Wl,-E

--add-module=/usr/local/src/ngx_devel_kit-master --add-module=/usr/local/src/set-misc-nginx-module-master --add-module=/usr/local/src/srcache-nginx-module-master --add-module=/usr/local/src/memc-nginx-module-master --add-module=/usr/local/src/lua-nginx-module-master

 

    make

    make install

        

         tengine的再編譯並不會將原來自建的配置文件如nginx.conf刪除。

         能夠查看一下是否已將模塊編譯進去

         [root@puppetmaster sbin]# /usr/local/nginx/sbin/nginx –V

 

 5    將lua源碼並上傳到nginx服務器

        /data/nfsroot/client/ngx_lua/

   

 6    新建nginx的配置文件cache.conf用於nginx調用各個模塊

         Vim /usr/local/nginx/conf/cache.conf

         set $cache_fetch_skip 1;

   set $cache_store_skip 1;

   set $cmd_key $host$request_uri;

   srcache_response_cache_control off;

   rewrite_by_lua_file /data/nfsroot/client/ngx_lua/cache_config.lua;

   srcache_methods GET; #GET POST

   srcache_fetch_skip $cache_fetch_skip;

   srcache_store_skip $cache_store_skip;

   srcache_store_statuses 200 201 301 302; #200 201 301 302 500

   srcache_fetch GET /memc $cmd_key;

   srcache_store PUT /memc $cmd_key;

   add_header X-Cached-From $srcache_fetch_status;

 

 7    修改配置文件nginx.cof

       添加upstream,主機爲memcache服務器

     upstream memc_server1 {

     server 192.168.0.1:12000;

     keepalive 512;

   }

 

    upstream memc_server2 {

      server 192.168.0.2:12000;

      keepalive 512;

    }

 

    upstream_list memc_servers memc_server1 memc_server2;

 

在所須要的虛擬主機下添加:如www.hello.com

location /memc {

#容許內網訪問

internal;

memc_connect_timeout 100ms;

memc_send_timeout 100ms;

memc_read_timeout 100ms;

set $memc_key $host$request_uri;

#一致性hash算法和java客戶端相似

set_hashed_upstream $memc_backends memc_servers $memc_key;

#設置緩存時間 10分鐘

set $memc_exptime 600;

memc_pass $memc_backends;

}

 

在所須要緩存的應用下添加配置文件路徑,如:

location /local/{

                include /usr/local/nginx/conf/cache.conf;

                proxy_pass   http://hello_servers/hello/route/;

}

 

 

 8    pkill nginx

       /usr/local/nginx/sbin/nginx -c /etc/nginx/conf/nginx.conf

 

主要原理:

經過lua 腳本控制緩存的存開關和取開關

/data/nfsroot/client/ngx_lua/cache_config.lua;

ngx.var.cache_fetch_skip=0 標示抓取緩存

ngx.var.cache_store_skip=0 標示緩存被代理的緩存

ngx.var.cache_fetch_skip=1 跳過GET緩存

ngx.var.cache_store_skip=1 跳過PUT緩存

通常咱們只須要設置成這樣既可

ngx.var.cache_fetch_skip=1 標示抓取緩存 須要的時候 修改成0 reload nginx 全站緩存開啓,抵禦流量

ngx.var.cache_store_skip=0 預熱到緩存

 

 

附lua源碼

[root@squid1 client]# tree ngx_lua
ngx_lua
├── cache_config.lua
├── module
│   ├── limit_share.lua
│   ├── mySqlClient.lua
│   ├── redisClient.lua
│   └── share.lua
├── README.md
└── test.lua

cache_config.lua

1 ngx.var.cache_fetch_skip=1
2 ngx.var.cache_store_skip=0

limit_share.lua

 1 local _M = {}
 2 local lrucache = require "lrucache"
 3 local c = lrucache.new(600)  -- allow up to 200 items in the cache
 4 if not c then
 5     return error("failed to create the cache: " .. (err or "unknown"))
 6 end
 7 --開啓全站緩存
 8 c:set("full_cache",0)
 9 c:set("CACHE_POST",0)
10 function _M.go()
11     c:set("dog", 32)
12     c:set("cat", 56)
13     -- ngx.say("dog: ", c:get("dog"))
14     -- ngx.say("cat: ", c:get("cat"))
15 
16     -- c:set("dog", { age = 10 }, 0.1)  -- expire in 0.1 sec
17     -- c:delete("dog")
18 end
19 
20 function _M.getC()
21 return c
22 end
23 
24 return _M

mySqlClient.lua

redisClient.lua

 1 local redis = require("redis")
 2 local _Redis ={}
 3 function _Redis:client()
 4 
 5     local red = redis:new()
 6 
 7     red:set_timeout(1000) -- 1 sec
 8 
 9 
10         local ok, err = red:connect("192.168.59.103", 6379)
11             if not ok then
12                  ngx.say("failed to connect to redis: ", err)
13             else
14                  ngx.ctx.redis=red
15             end
16 
17         return ngx.ctx.redis
18 end
19 
20 --- 關閉鏈接
21 function _Redis:close()
22     if ngx.ctx.redis then
23         ngx.ctx.redis:set_keepalive(10000, 100)
24         ngx.ctx.redis = nil
25     end
26 end
27 
28 return _Redis

share.lua

 1 local _M = {}
 2 local lrucache = require "lrucache"
 3 local c = lrucache.new(200)  -- allow up to 200 items in the cache
 4 if not c then
 5     return error("failed to create the cache: " .. (err or "unknown"))
 6 end
 7 
 8 function _M.go()
 9    
10     -- ngx.say("dog: ", c:get("dog"))
11     -- ngx.say("cat: ", c:get("cat"))
12 
13     -- c:set("dog", { age = 10 }, 0.1)  -- expire in 0.1 sec
14     -- c:delete("dog")
15 end
16 
17 function _M.check(args)
18         ngx.say(args)
19         return c:get(args)
20 end
21 
22 function _M.getC()
23         if ngx.ctx.c then
24         return ngx.ctx.c
25     end
26          
27          ngx.ctx.c=c
28         return ngx.ctx.c
29 end
30 
31 return _M
相關文章
相關標籤/搜索