您的位置:首页 > 数据库 > Memcache

nginx+memcache增加全站缓存系统

2016-03-01 16:07 633 查看
项目背景:

当生产产生异常流量而又无法快速定位流量来源,为减少数据库负载,通过全局缓存预热,以及快速切缓存开关,来控制全站流量导入缓存,减少异常情况下对数据库的压力。

总体实现为nginx+memcache+Lua

1 首先查看一下nginx版本:

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

Tengine version: Tengine/2.1.2 (nginx/1.6.2)

此处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

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


limit_share.lua

local _M = {}
local lrucache = require "lrucache"
local c = lrucache.new(600)  -- allow up to 200 items in the cache
if not c then
return error("failed to create the cache: " .. (err or "unknown"))
end
--开启全站缓存
c:set("full_cache",0)
c:set("CACHE_POST",0)
function _M.go()
c:set("dog", 32)
c:set("cat", 56)
-- ngx.say("dog: ", c:get("dog"))
-- ngx.say("cat: ", c:get("cat"))

-- c:set("dog", { age = 10 }, 0.1)  -- expire in 0.1 sec
-- c:delete("dog")
end

function _M.getC()
return c
end

return _M


mySqlClient.lua

redisClient.lua

local redis = require("redis")
local _Redis ={}
function _Redis:client()

local red = redis:new()

red:set_timeout(1000) -- 1 sec

local ok, err = red:connect("192.168.59.103", 6379)
if not ok then
ngx.say("failed to connect to redis: ", err)
else
ngx.ctx.redis=red
end

return ngx.ctx.redis
end

--- 关闭连接
function _Redis:close()
if ngx.ctx.redis then
ngx.ctx.redis:set_keepalive(10000, 100)
ngx.ctx.redis = nil
end
end

return _Redis


share.lua

local _M = {}
local lrucache = require "lrucache"
local c = lrucache.new(200)  -- allow up to 200 items in the cache
if not c then
return error("failed to create the cache: " .. (err or "unknown"))
end

function _M.go()

-- ngx.say("dog: ", c:get("dog"))
-- ngx.say("cat: ", c:get("cat"))

-- c:set("dog", { age = 10 }, 0.1)  -- expire in 0.1 sec
-- c:delete("dog")
end

function _M.check(args)
ngx.say(args)
return c:get(args)
end

function _M.getC()
if ngx.ctx.c then
return ngx.ctx.c
end

ngx.ctx.c=c
return ngx.ctx.c
end

return _M
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: