zoukankan      html  css  js  c++  java
  • openresty使用redis作本地缓存

    一,为什么要使用redis作本地缓存?

        1,使用缓存通常会有三层

          当使用openresty作为web服务器时,我们更看重是的它可以通过lua编程的扩展能力,就openresty而言,它可以实现的功能非常多,

          提高响应速度是web服务中非常重要的功能,

         使用缓存通常会有三层:

                   本地缓存:存在于本地机器上,直接通过nginx访问,避免网络io;

                   redis cluster:存储更多的供lua访问的数据,也是通过nginx访问直接返回,相比前一层缓存,增加了网络io,但仍然避免了对业务系统的访问;

                   业务缓存:供运行在tomcat/php-fpm/go http中内的业务代码访问。

          可以比较得到本地缓存是响应速度最快的,通常可以在10ms内对请求进行响应。

          我们看到的很多经过优化的BAT等大厂的站点都能在极短时间内响应请求,就是经过了层层优化的结果。

        2,这里会提供一个例子:使用redis做商品详情页的cache:

          流程:当用户访问时,

                   先从redis中获取cache内容,

                   如果redis中不存在此value,则会改为访问后端业务系统获取cache

          说明:在生产环境中,为方便更新,通常会采用redis的主从架构,

                  每台业务nginx上所配备的redis的数据能得到实时更新

    说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest

             对应的源码可以访问这里获取: https://github.com/liuhongdi/

     说明:作者:刘宏缔 邮箱: 371125307@qq.com

    二,nginx的配置文件:

        upstream backenditem {
           server 127.0.0.1:8000;
        }
    
        server {
           listen 8000;
           server_name 8000.test.com;
           
           location / {
                default_type 'text/html';
                content_by_lua_block {ngx.say("hello world,this is path backend from 8000:uri:"..ngx.var.request_uri)}
           }      
        }
    
        server {
             listen 82;
             server_name test.com;
             location ~ /backenditem/(.*) {
                 rewrite /backenditem(/.*) $1 break;
                 proxy_next_upstream error timeout;
                 proxy_pass http://backenditem;
             }
             location /item {
                 default_type text/html;
                 content_by_lua_file /data/luacache/webroot/item_redis_cache.lua;
             }
           
            location / {
                 default_type 'text/html';
                 content_by_lua_block {ngx.say("default path:uri:"..ngx.var.request_uri)}
            }
        }

      说明:1,端口8000的server是一个demo,生产环境中,它应该是使用tomcat/php-fpm/django之类的业务系统

               2,location ~ /backenditem/(.*) :负责upstream到后端业务系统,

                   注意这里要做一次 rewrite /backenditem(/.*) $1 break;   ,作用是去掉用来标识要跳转到后端的backenditem字串

               3,content_by_lua_file    此处用绝对路径指定了lua代码的程序文件

    三,lua程序文件:   item_redis_cache.lua

    --指定要访问的lua包所在的路径
    package.path = package.path..";/data/luacache/webroot/config/?.lua;/data/luacache/webroot/lib/?.lua"
    local config = require "config_constant"
    local readhttp = require "read_http"
    local returnjson = require "return_json"
    --redis连接池工厂
    local redis_factory = require('redis_factory')(config.redisConfig) 
    --获取redis的连接实例
    local ok, redis_a = redis_factory:spawn('redis_a')
    
    --用于接收前端数据的对象
    local args=nil
    --获取前端的请求方式 并获取传递的参数   
    local request_method = ngx.var.request_method
    --判断是get请求还是post请求并分别拿出相应的数据
    if "GET" == request_method then
            args = ngx.req.get_uri_args()
    elseif "POST" == request_method then
            ngx.req.read_body()
            args = ngx.req.get_post_args()
            --兼容请求使用post请求,但是传参以get方式传造成的无法获取到数据的bug
            if (args == nil or args.data == null) then
                    args = ngx.req.get_uri_args()
            end
    end
    
    --ngx.log(ngx.ERR,"args.key:",args.key)
    
    if args.itemid == nil or args.itemid=="" then
    
        local json = returnjson.getjson("1",'key not exist or key is empty',"")
        --ngx.log(ngx.ERR,"json:",json)
        ngx.say(json)
    
    else
            
        --获取前端传递的itemid
        local itemid = args.itemid
    
        --在redis中获取itemid对应的值
        local va = redis_a:get(itemid)
    
        if va == ngx.null or va == nil then
    
              --ngx.log(ngx.ERR, "redis not found content, back to http, itemid : ", itemid) 
              local url="/backenditem/item"
              va = readhttp.read(url,itemid)
              ngx.print(returnjson.getjson(0,itemid,va)) 
        else 
                --响应前端
             ngx.say(returnjson.getjson(0,itemid,va))
        end
    
    end

    四,lua访问redis的配置文件: config_constant.lua

    config = {}
    
    config.redisConfig = {
        redis_a = { -- your connection name 
            --ip
            host = '127.0.0.1',
            --端口
            port = 6379,
            --密码
            pass = '',
            --超时时间,如果是测试环境debug的话,这个值可以给长一点;如果是正式环境,可以设置为200
            timeout = 120000,
            --redis的库
            database = 0,
        },
    }
    return config

    五,lua程序文件:read_http.lua:用来从后端业务系统得到response

    local read_http = {}
    function read_http.read(url,id)
         local resp = ngx.location.capture(url, {
              method = ngx.HTTP_GET,
              args = {id = id}
          })
          if not resp then
              ngx.log(ngx.ERR, "request error :", err)
              return
          end
          if resp.status ~= 200 then
              ngx.log(ngx.ERR, "request error, status :", resp.status)
              return
          end
          return resp.body
    end
    
    return read_http

    六,lua程序:return_json.lua :返回json字串

    local return_json = {}
    function return_json.getjson(status,msg,data)
          local json = '{"status":"'..status..'","msg":"'..msg..'","data":"'..data..'"}'
          return json
    end
    
    return return_json

    七,此项目的github地址:

      https://github.com/liuhongdi/luacache

    八,测试效果:

          1,当有商品存在于redis中的返回 :如图

         

         2,当商品不存在于redis中的返回:   如图

        3,当参数错误时的返回 :如图

        

    九,文中涉及到的各平台的版本查看:

         

    [root@localhost luacache]# cat /etc/redhat-release 
    CentOS Linux release 8.1.1911 (Core)
    [root@localhost luacache]# /usr/local/openresty/bin/openresty -V
    nginx version: openresty/1.15.8.2
    built by gcc 8.2.1 20180905 (Red Hat 8.2.1-3) (GCC) 
    built with OpenSSL 1.1.0k  28 May 2019
    TLS SNI support enabled
    [root@localhost luacache]# /usr/local/soft/redis5/bin/redis-server --version
    Redis server v=5.0.7 sha=00000000:0 malloc=libc bits=64 build=8e31d2ed9a4c9593
  • 相关阅读:
    cocos creator 场景如何透明,多个canvas层级显示
    c/c++导出lua绑定
    c++自动导出lua绑定
    获取Sprite上某一个点的透明度
    cocos2d-x lua中实现异步加载纹理
    keystore找回密码
    xcode 制作静态库文件(.a)
    Ajax学习笔记之一----------第一个Ajax Demo[转载]
    lua调用java java调用lua[转载]
    WPF中模板选择和DataContext的一些使用
  • 原文地址:https://www.cnblogs.com/architectforest/p/12287395.html
Copyright © 2011-2022 走看看