解决方案: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/
二、首页数据缓存实现思路
缓存预热与二级缓存查询
步骤一: 编写lua脚本实现缓存预热(将mysql里的数据查询出来存入redis)
步骤二: 编写lua脚本实现二级缓存读取
缓存预热
实现思路:
定义请求:用于查询数据库中的数据更新到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