使用OpenResty实现Nginx层面的多级缓存查询响应

OpenResty概述

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

OpenResty® 通过汇聚各种设计精良的 Nginx 模块(主要由 OpenResty 团队自主开发),从而将 Nginx 有效地变成一个强大的通用 Web 应用平台。这样,Web 开发人员和系统工程师可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,快速构造出足以胜任 10K 乃至 1000K 以上单机并发连接的高性能 Web 应用系统。

OpenResty® 的目标是让你的Web服务直接跑在 Nginx 服务内部,充分利用 Nginx 的非阻塞 I/O 模型,不仅仅对 HTTP 客户端请求,甚至于对远程后端诸如 MySQL、PostgreSQL、Memcached 以及 Redis 等都进行一致的高性能响应。

以上介绍来自官网:http://openresty.org/cn/

由Lua 粘合的Nginx生态环境 - 天涯逐梦 - 博客园 是OpenResty作者章亦春在2012年厦门TechClub沙龙上发表的一次关于OpenResty技术介绍的演讲听录。

下面这个网址则是章亦春用 Perl 生成的一个简单 git 动画,可能就是在这次大会上当作幻灯片使用:

http://agentzh.org/misc/slides/ngx-openresty-ecosystem

安装

添加仓库执行命令

yum install yum-utils
yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo

执行安装

yum install openresty

安装成功后 会在默认的目录如下:

/usr/local/openresty

OpenResty默认已经集成了nginx,在目录:/usr/local/openresty/nginx 下。

在nginx层面实现多级缓存查询

使用OpenResty实现Nginx层面的多级缓存查询响应

为什么要这样做:

在Nginx层面响应请求,不用再转发给后端服务器,减少后端服务器的压力

步骤

nginx.conf中定义lua缓存命名空间及其大小:

user  root root;
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    #定义Nginx缓存模块,模块名字叫dis_cache,容量大小128M
    lua_shared_dict dis_cache 128m;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       80;
        #监听的域名
        server_name  localhost;

        #表示所有以 localhost/read_content的请求都由该配置处理
        location /read_content {
            #content_by_lua_file:所有请求都交给指定的lua脚本处理(/root/lua/read_content.lua)
            content_by_lua_file /root/lua/read_content.lua;
        }
    }
}

lua脚本:

ngx.header.content_type="application/json;charset=utf8"
local uri_args = ngx.req.get_uri_args()
local id = uri_args["id"]
--获取本地缓存
local cache_ngx = ngx.shared.dis_cache
--根据ID 获取本地缓存数据
local contentCache = cache_ngx:get('content_cache_'..id)

-- 如果nginx缓存中没有,读取redis缓存
if contentCache == "" or contentCache == nil then
    local redis = require("resty.redis");
    local red = redis:new()
    red:set_timeout(2000)
    red:connect("192.168.176.129", 6379)
    local rescontent=red:get("content_"..id)

    -- 如果redis缓存中没有,读取mysql数据库
    if ngx.null == rescontent then
        local cjson = require("cjson")
        local mysql = require("resty.mysql")
        local db = mysql:new()
        db:set_timeout(2000)
        local props = {
            host = "192.168.176.129",
            port = 3306,
            database = "changgou_content",
            user = "root",
            password = "123456"
        }
        local res = db:connect(props)
        local select_sql = "select url,pic from tb_content where status ='1' and category_id="..id.." order by sort_order";
        res = db:query(select_sql)
        local responsejson = cjson.encode(res)
        -- 写入redis缓存
        red:set("content_"..id,responsejson)
        ngx.say(responsejson);
        db:close()
    -- 如果redis缓存中存在数据,响应数据并写入nginx缓存
    else
        cache_ngx:set('content_cache_'..id, rescontent, 10*60);
        ngx.say(rescontent)
    end
    red:close()
-- 如果nginx缓存中存在直接响应
else
    ngx.say(contentCache)
end

原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/%e4%bd%bf%e7%94%a8openresty%e5%ae%9e%e7%8e%b0nginx%e5%b1%82%e9%9d%a2%e7%9a%84%e5%a4%9a%e7%ba%a7%e7%bc%93%e5%ad%98%e6%9f%a5%e8%af%a2%e5%93%8d%e5%ba%94/