页面静态化缓存应用(OpenResty+nginx_srcache+redis)

Posted 数睿技术

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了页面静态化缓存应用(OpenResty+nginx_srcache+redis)相关的知识,希望对你有一定的参考价值。

页面静态化缓存应用(OpenResty+nginx_srcache+redis)

介绍

OpenResty是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

srcache-nginx-module模块为前淘宝工程师agentzh(章亦春)开发,srcache为location增加了透明的基于subrequest的缓存层。配合lua使用将页面缓存写入redis集群,这样可以大大减轻真实后端服务的压力,提高访问性能!

工作流程

SRCache工作原理

页面静态化缓存应用(OpenResty+nginx_srcache+redis)

一个请求进来首先从srcache_fetch 指令进行缓存查找,查到返回到缓存,否则,进入下个指令srcache_store将缓存数据插入到redis。

压力测试的结果

用压力测试工具Apache JMeter测试了一下。模拟10个用户每个用户1000请求,10*1000=10000个请求。 没加缓存,平均每个请求处理时间2.7秒

页面静态化缓存应用(OpenResty+nginx_srcache+redis)

加了缓存之后,平均每个请求处理时间413 毫秒,访问速度提高6.6倍。

页面静态化缓存应用(OpenResty+nginx_srcache+redis)

srcache缓存管理界面

这样,我们就可以通过管理页面来操作那些url需要缓存和缓存时间,要想清除缓存只要在缓存的具体url中增加/clearcache即可。 只是简单实现了其功能,还有许多需要完善的地方,不过这样的应用,对于提高页面访问速度效果应该还是可以的

判断页面是否缓存

代码示例

nginx配置文件
 
   
   
 
  1. lua_package_path "/usr/local/nginx/conf/lualib/?.lua"; lua_package_cpath "/usr/local/nginx/conf/lualib/?.so;";

  2. lua_shared_dict limit 10m;

  3. init_by_lua_file  /usr/local/nginx/conf/lua/config.lua;

  4. server {

  5.    listen 80;

  6.    server_name www.awfjplh.com;

  7.    root /path/to/root;

  8.    index index.html index.htm index.php;

  9.    location / {

  10.        try_files $uri $uri/ /index.php$is_args$args;

  11.    }

  12.    location ~ \.php$ {

  13.            srcache_ignore_content_encoding on;

  14.            srcache_methods GET HEAD POST;

  15.            srcache_store_pass_header Set-Cookie;

  16.            srcache_response_cache_control off;

  17.            set $cache_key "";

  18.            set $cache_expire "";

  19.            set $cache_fetch_skip 1;

  20.            set $cache_store_skip 1;

  21.            set $cache_url '';

  22.            rewrite_by_lua_file /usr/local/nginx/conf/lua/rewrite.lua;

  23.            srcache_fetch_skip $cache_fetch_skip;

  24.            srcache_store_skip $cache_store_skip;

  25.            srcache_fetch GET /cache/content key=$cache_key;

  26.            srcache_store PUT /cache/content key=$cache_key&expire=$cache_expire;

  27.            add_header X-SRCache-Fetch-Status $srcache_fetch_status;

  28.            add_header X-SRCache-Store-Status $srcache_store_status;

  29.            add_header srcache_fetch_skip $cache_fetch_skip;

  30.            add_header srcache_store_skip $cache_store_skip;

  31.            add_header cache_key $cache_key;

  32.            add_header cache_expire $cache_expire;

  33.            add_header cache_url $cache_url;

  34.            proxy_set_header Host $host;

  35.            proxy_set_header X-Real-Ip $remote_addr;

  36.            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

  37.            proxy_pass       http://hhpp33;

  38.        }

  39.        #写入redis

  40.        location  /cache/content {

  41.            internal;

  42.            content_by_lua_file /usr/local/nginx/conf/lua/content.lua;

  43.        }

  44.        #用于清除缓存

  45.        location ~ /clearcache(/.*) {

  46.            content_by_lua_file /usr/local/nginx/conf/lua/clear_cache.lua;

  47.        }

  48. }

config.lua文件
 
   
   
 
  1. --redis群集配置参数

  2. redis_cluster_config = {

  3.    name = "redis_cluster",

  4.    serv_list = {

  5.        { ip = "192.168.8.2", port = 3001 },

  6.        { ip = "192.168.8.3", port = 3004 },

  7.        { ip = "192.168.8.4", port = 3002 },

  8.        { ip = "192.168.8.5", port = 3003 },

  9.        { ip = "192.168.8.6", port = 3005 },

  10.        { ip = "192.168.8.7", port = 3006 },

  11.        { ip = "192.168.8.8", port = 3011 },

  12.        { ip = "192.168.8.9", port = 3012 },

  13.    },

  14.    keepalive_timeout = 60000,              --redis connection pool idle timeout

  15.    keepalive_cons = 1000,                  --redis connection pool size

  16.    connection_timout = 1000,               --timeout while connecting

  17.    max_redirection = 5                     --maximum retry attempts for redirection

  18. }

  19. --redis加载群集模块

  20. redis_cluster = require "rediscluster"

  21. --加载cjson模块

  22. cjson = require "cjson"

rewrite.lua文件
 
   
   
 
  1. local request_uri_without_args = ngx.re.sub(ngx.var.request_uri, "\\?.*", "")

  2. local red = redis_cluster:new(redis_cluster_config)

  3. local res, flags, err = red:get('config:srcache:url')

  4. local version, flags, err = red:get('config:srcache:version')

  5. local suffix = '1';

  6. if(version ~= ngx.null ) then

  7.    suffix = version

  8. end

  9. if res ~= ngx.null then

  10.    cache_url_list = cjson.decode(res)

  11.    if not ngx.var.cookie_w_info then

  12.        for i, v in ipairs(cache_url_list) do

  13.            ngx.var.cache_url = v["status"]

  14.            local s = string.find(request_uri_without_args, v["url"])

  15.            if s and v["status"] == 1 then

  16.                local key = { ngx.var.request_method, " ", ngx.var.scheme, "://", ngx.var.host, request_uri_without_args, }

  17.                key = table.concat(key)

  18.                key = 'srcache:' .. ngx.md5(key)..':'..suffix

  19.                ngx.var.cache_key = key

  20.                ngx.var.cache_expire = v["expire"]

  21.                ngx.var.cache_fetch_skip = 0

  22.                ngx.var.cache_store_skip = 0

  23.                break

  24.            end

  25.        end

  26.    end

  27. end

content.lua文件
 
   
   
 
  1. local red = redis_cluster:new(redis_cluster_config)

  2. local method = ngx.req.get_method()

  3. if method == "GET" then

  4.    local key = ngx.var.arg_key

  5.    local res, flags, err = red:get(key)

  6.    red:close()

  7.    if err then

  8.        ngx.say(ngx.ERR, err)

  9.        ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE)

  10.    end

  11.    if res == nil and flags == nil and err == nil then

  12.        ngx.exit(ngx.HTTP_NOT_FOUND)

  13.    end

  14.    ngx.print(res)

  15. elseif method == "PUT" then

  16.    local value = ngx.req.get_body_data()

  17.    local expire = ngx.var.arg_expire or 60

  18.    local key = ngx.var.arg_key

  19.    local ok, err = red:set(key, value)

  20.    red:close()

  21.    if not ok then

  22.        ngx.say(ngx.ERR, err)

  23.        ngx.say(ngx.ERR, key .. value)

  24.        ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE)

  25.    end

  26.    red:expire(key,expire)

  27. else

  28.    ngx.exit(ngx.HTTP_NOT_ALLOWED)

  29. end

clear_cache.lua文件
 
   
   
 
  1. ngx.header.content_type = 'application/json;charset=utf-8'

  2. ngx.header.Access_Control_allow_Credentials = 'true'

  3. ngx.header.Access_Control_allow_Origin = '*'

  4. local red = redis_cluster:new(redis_cluster_config)

  5. local request_uri_without_args = ngx.re.sub(ngx.var.request_uri, "\\?.*", "")

  6. request_uri_without_args = ngx.re.gsub(request_uri_without_args, "/clearcache", "")

  7. local key = { ngx.var.request_method, " ", ngx.var.scheme, "://", ngx.var.host, request_uri_without_args, }

  8. local args = ngx.req.get_uri_args()

  9. local query = ngx.encode_args(args)

  10. local version, flags, err = red:get('config:srcache:version')

  11. local suffix = '1';

  12. if(version ~= ngx.null ) then

  13.    suffix = version

  14. end

  15. if query ~= "" then

  16.    key[#key + 1] = "?"

  17.    key[#key + 1] = query

  18. end

  19. local arr = { status = 0, msg = "" }

  20. key = table.concat(key)

  21. key = 'srcache:' .. ngx.md5(key)..':'..suffix

  22. ok, err = red:exists(key)

  23. if ok ~= 1 then

  24.    red:close()

  25.    ngx.say(cjson.encode(arr))

  26.    return

  27. end

  28. ok, err = red:del(key)

  29. if not ok then

  30.    red:close()

  31.    arr['msg'] = '缓存删除失败'

  32.    ngx.say(cjson.encode(arr))

  33.    return

  34. end

  35. red:close()

  36. arr['status'] = 1

  37. arr['msg'] = '缓存删除成功'

  38. ngx.say(cjson.encode(arr));


以上是关于页面静态化缓存应用(OpenResty+nginx_srcache+redis)的主要内容,如果未能解决你的问题,请参考以下文章

用Openresty结合lua提高应用本地缓存效率

Nginx配置缓存服务器

重识Nginx - 01 Nginx 主要应用场景及版本概述

网页静态化

Lua+Redis+OpenResty实现电商详情页

Lua+Redis+OpenResty实现电商详情页