项目--查询优化之多级缓存

nginx proxy cache 缓存
 

  • nginx 反向代理前置
  • 依靠文件系统存索引级的文件
    • nginx讲一个请求当做一个 文件存储在本地,当下一个请求来时,看本地有没有一个文件,来决定proxycache是否启用
  • 依靠内存缓存文件地址
    • 缓存的内容是以文件存在磁盘中。但是缓存的key是存储在内存中,其值是文件在磁盘上的地址。

nginx.conf

 

    #申明一个cache缓存节点的内容
    proxy_cache_path /uar/local/openresty/nginx/tmp_cache levels=1:2 keys_zone=tmp_cache:100m inactive=7d max_size=10g;    

levels说明对应文件的级别,可以在temp_cache目录下,将getid=6的url作为文件名,也可以做二级目录,减少磁盘寻址时间。将url做hash,取最后一位做一级目录,取倒数二位做二级目录。100m空间放key,inactive文件存储七天,文件系统最多10g。超过10g采用淘汰算法。
 

        location / {
                proxy_pass http://backend_server;

                proxy_cache tmp_cache;
                proxy_cache_key $uri;
                proxy_cache_valid 200 206 304 302 7d;

                proxy_set_header Host $http_host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_http_version 1.1;
                proxy_set_header Connection "";
        }

其实读取的还是本地磁盘文件。

 

所以回滚配置;


nginx lua

lua协程机制

             协程机制,线程空间站中的一个执行单元,有自己独立的运行空间,基于用户态模拟出来的运行空间。

nginx协程机制

niginx lua 插载点

OpenResty


协程机制

  • 依附于线程的内存模型,切换开销小
  • 遇阻塞及归还执行权,代码同步
  • 无需加锁

lua协程

  • Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
    > function foo (a)
    >> print("foo函数输出",a)
    >> return coroutine.yield(2 * a)
    >> end
    >
    > co = coroutine.create(function(a,b)
    >> print("第一次协程执行输出", a, b)
    >> local r = foo(a + 1)
    >>
    >> print("第二次协程执行输出", r)
    >> local r,s=coroutine.yield(a+b, a-b)
    >>
    >> print("第三次协程执行输出",r,s)
    >> return b,"结束协程"
    >> end)
    >
    >
    > print("main", coroutine.resume(co,1,10))
    第一次协程执行输出      1       10
    foo函数输出     2
    main    true    4
    > print("main",coroutine.resume(co,"r"))
    第二次协程执行输出      r
    main    true    11      -9
    > print("main",coroutine.resume(co,"x","y"))
    第三次协程执行输出      x       y
    main    true    10      结束协程
    >
    > print("main",coroutine.resume(co,"x","y"))
    main    false   cannot resume dead coroutine
    >
    
    
    
    
    
    

    ngInx的每一个 Worker进程都是在epol或 kqueue这种事件模型之上,封装成协程。

nginx协程机制

ngInX每个工作进程创建一个lua虚拟机
工作进程内的所有协程共享同一个vm
每个外部请求由一个lua协程处理,之间数据隔离
lua代码调用io等异步接口时,协程被挂起,上下文数据

自动保存,不阻塞工作进程
io异步操作完成后还原协程上下文,代码继续执行

nginx处理阶段

NGX_HTTP_ POST READ PHASE=0,/读取请求头
NGX_HTTP_ ServEr RewriTe PhasE, //执行rewrite ->rewrite handler
NGX_HTTP_ Find_ CONFIG PHASE,/根据uri替换 location
NGX_HTTP_ REWRITE_ PHASE//根据替换结果继续执行 rewrite--》 rewrite handler
NGX_HTTP_ Post RewriTe Phase,/行 rewrite后处理
NGX_HTTP_ PreacCess_ PHASE,/八认证预处理请求限制,连接限制→ limit conn hander
limit_req_ handler
NGX_HTTP_ AccesS PhasE,//认证处理→ auth basic handler, access handler
NGX_HTTP_ POST_ACCESS_ PHASE,//认证后处理,认证不通过,丢包
NGX_HTTP_ Try FileS Phase,∥尝试try标签
NGX_HTTP_ ConteNt Phase,∥内容处理→ static handler
NGX_HTTP_ Log Phase//日志处理→ g_handler

nginx lua插载点

                           

 init_by_lua:系统启动时调用
init_worker_by_lua: worker进程启动时调用
set _ by_lua: ngInx变量用复杂 lua return
rewrite_ by_lua:重写url规则
access_by_ua:权限验证阶段
content_by_lua:内容输出节点


openresty实践

  • openresty hello world
  • shared dic:共享内存字典,所有 worker进程可见,lru淘汰
  • openresty redis支持

 

在openresty目录下新建lua文件夹,编写staticitem.lua         
内容是ngx.say("hello static item lua");

在 nginx.conf配置中       
 location /staticitem/get{
                default_type "text/html";
                content_by_lua_file ../lua/staticitem.lua;

        }

当浏览器访问  ..../staticitem/get 时,输出hello static item lua.这句话
在openresty目录下新建lua文件夹,编写helloworld.lua         
内容是ngx.exec(".item/get?id=6");

在 nginx.conf配置中       
 location /helloworld{
                
                content_by_lua_file ../lua/helloworld.lua;

        }


当浏览器访问  ..../helloworld 时,会跳转连接

、、

itemsharedic.lua


function get_from_cache(key)
        local cache_ngx = ngx.shared.my_cache
        local value = cache_ngx.get(key)
        return value
end

function set_to_cache(key, value, exptime)
        if not exptime then
                exptime = 0
        end
        local cache_ngx = ngx.shared.my_cache
        local succ,err,forcible = cache_ngx:set(key,value,exptime)
        return succ
end


local args = ngx.req.get_uri_args()
local id = args["id"]
local item_model get_from_cache("item_"..id)
if item_model == nil then
        local resp = ngx.location.capture("/item/get?id="..id)
        item_model = resp.body
        set_to_cache("item_"..id,item_model,1*60)
end
ngx.say(item_model)
~                                                                                                                                                                             
~                         

nginx.conf中 

lua_shared_dict my_cache 128m



        location /luaitem/get{
                default_type "application/json";
                content_by_lua_file ../lua/itemsharedic.lua;

        }


 nginx内存保存了热点数据,但是对于一些非热点,但是访问量大的,需要使用openresty的redis支持

 

编写 itemredis.lua


local args = ngx.req.get_uri_args()
local id = args["id"]
local redis = require "resty.redis"
local cache = redis:new()
local ok,err = cache:connect("127.0.0.1", 6379)
local item_model = cache:get("item_"..id)
if item_model == ngx.null or item_model == nil then
        local resp = ngx.location.capture("/item/get?id="..id)
        item_model = resp.body
end
~                                                                                                                                                                             
~                                                                                                                                                                             
~                          

 

        location /luaitem/get{
                default_type "application/json";
                content_by_lua_file ../lua/itemredis.lua;

        }

总结:share dic热点本地缓存 和tomcat使用guava本地缓存,都可以是QPS,PS上3500+,响应时间100ms以内的高性能。

但是这些热点数据吃内存,更新不方便。如果数据不是很热,但是涉及更新的时候,使用openresty对redis的支持,或者tomcat对redis的支持。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值