解决方案:OpenResty 网站首页数据缓存


关键词

  • Web 应用服务器,封装Nginx,集成LUA脚本
  • lua脚本实现缓存预热
  • lua脚本实现二级缓存读取
  • openresty本地缓存

需求: 将网站首页进行独立部署到Nginx中

实现的思路 : Nginx+Lua(OpenResty成熟的产品)

一、OpenResty

OpenResty(又称:ngx_openresty) 是一个基于 NGINX 的可伸缩的 Web平台,由中国人章亦春发起,提供了很多高质量的第三方模块。

OpenResty 是一个强大的 Web 应用服务器,Web 开发人员可以使用 Lua脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,更主要的是在性能方面,OpenResty可以 快速构造出足以胜任 10K 以上并发连接响应的超高性能Web 应用系统

360,UPYUN,阿里云,新浪,腾讯网,去哪儿网,酷狗音乐等都是OpenResty 的深度用户。

OpenResty 简单理解成 就相当于封装了Nginx,并且集成了LUA脚本,开发人员只需要简单的其提供了模块就可以实现相关的逻辑,而不再像之前,还需要在nginx中自己编写lua的脚本,再进行调用了。

OpenResty安装

linux安装openresty:

1.添加仓库执行命令

yum install yum-utils 

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

2.执行安装

yum install openresty

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

/usr/local/openresty

安装nginx

默认已经安装好了nginx,在目录:/usr/local/openresty/nginx 下

修改/usr/local/openresty/nginx/conf/nginx.conf ,将配置文件使用的根设置为root,目的就是将来要使用lua脚本的时候 ,直接可以加载在root下的lua脚本。

#user nobody; 配置文件第一行原来为这样, 现改为下面的配置
user root root;

测试访问 http://47.103.77.82/

opentelemetry 储存_openresty

二、首页数据缓存实现思路

缓存预热与二级缓存查询

步骤一: 编写lua脚本实现缓存预热(将mysql里的数据查询出来存入redis)

opentelemetry 储存_nginx_02

步骤二: 编写lua脚本实现二级缓存读取

opentelemetry 储存_lua_03

缓存预热

实现思路:

定义请求:用于查询数据库中的数据更新到redis中。
(1)连接mysql ,读取数据列表,转换为json字符串。
(2)连接redis,将数据列表json字符串存入redis 。

在/root/lua目录下创建data_update.lua ,实现连接mysql 查询数据 并存储到redis中。

ngx.header.content_type="application/json;charset=utf8"
local cjson = require("cjson")
local mysql = require("resty.mysql")
local uri_args = ngx.req.get_uri_args()

local db = mysql:new()
db:set_timeout(1000)  
local props = {  
    host = "ip地址",  
    port = 3306,  
    database = "dabing_business",  
    user = "用户名",  
    password = "密码"  
}  

local res = db:connect(props)  
local select_sql = "select * from tb_data "  
res = db:query(select_sql)  
db:close()  

local redis = require("resty.redis")
local red = redis:new()
red:set_timeout(2000)

local ip ="ip地址"
local port = 6379
red:connect(ip,port)

red:set("data_"..data,cjson.encode(res))
red:close()

ngx.say("{\"flag\":true,\"data\":\""..data.."\"}")

通过http可以访问上述的脚本:

修改/usr/local/openresty/nginx/conf/nginx.conf文件:

代码如下:

#user nobody;
user root root;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid    logs/nginx.pid;
events {
  worker_connections 1024;
}
http {
  include    mime.types;
  default_type application/octet-stream;
  sendfile    on;
  #tcp_nopush   on;
  #keepalive_timeout 0;
  keepalive_timeout 65;
  #gzip on;
  server {
    listen    80;
    server_name localhost;
    charset utf-8;
    # access_log logs/host.access.log main;
    
   # 添加,通过http可以访问上述的脚本
   location /data_update {
      content_by_lua_file /root/lua/data_update.lua;
   }
   
    # redirect server error pages to the static page/50x.html
    #
    error_page  500 502 503 504 /50x.html;
    location = /50x.html {
      root  html;
   }    
 }
}

重新启动nginx

测试:http://IP地址/data_update

缓存读取

实现思路:

定义请求,用户根据广告分类的ID 获取广告的列表。通过lua脚本直接从redis中获取数据即可。

定义请求:

请求:/data_read
参数:position
返回值:json

在/root/lua目录下创建data_read.lua

--设置响应头类型
ngx.header.content_type="application/json;charset=utf8"
--获取请求中的参数ID
local uri_args = ngx.req.get_uri_args();
--引入redis库
local redis = require("resty.redis");
--创建redis对象
local red = redis:new()
--设置超时时间
red:set_timeout(2000)
--连接
local ok, err = red:connect("IP地址", 6379)
--获取key的值
local rescontent=red:get("data_"..data)
--输出到返回响应中
ngx.say(rescontent)
--关闭连接
red:close()

在/usr/local/openresty/nginx/conf/nginx.conf中server下添加配置

location /data_read {
  content_by_lua_file /root/lua/data_read.lua;
}

测试 http://IP地址/data_read

加入openresty本地缓存

如上的方式没有问题,但是如果请求都到redis,redis压力也很大,所以我们一般采用多级缓存的方式来减少下游系统的服务压力。

先查询openresty本地缓存 如果没有再查询redis中的数据

  • 修改/root/lua目录下data_read文件, 内容如下:
--设置响应头类型
ngx.header.content_type="application/json;charset=utf8"
--获取请求中的参数ID
local uri_args = ngx.req.get_uri_args();


--获取本地缓存
local cache_ngx = ngx.shared.dis_cache;
--根据ID 获取本地缓存数据
local dataCache = cache_ngx:get('data_cache_');
-----------------------略


--将redis中获取到的数据存入nginx本地缓存
cache_ngx:set('data_cache_', rescontent, 10*60);

else
 --nginx本地缓存中获取到数据直接输出
 ngx.say(dataCache)
end

可以手动清理本地缓存:

  • my_cache : flush_all(),这是不释放内存,而是标记过期。
  • my_cache : flush_expired(),清除过期。最多清除可选参数
  • max_count,如果不指定参数或者指定参数为0,不设限制。

修改nginx配置文件vi /usr/local/openresty/nginx/conf/nginx.conf ,http节点下添加配置:

#包含redis初始化模块
lua_shared_dict dis_cache 5m;  #共享内存开启

在缓存中没有数据的时候,可以编写相应提示

--将redis中获取到的数据存入nginx本地缓存
local succ,err = cache_ngx:set('data_cache_', rescontent, 10*60);
if not succ then
    ngx.say("set faile ,err:"..err.."建议增加本地共享内存空间");
end