为什么要对首页的轮播图进行优化
电商平台首页的轮播图同样需要调用后台接口去查询数据库,但是当并发量较大的时候会给服务器带来很大的压力,查询速度会大大的降低,为了提升用户的体验,因此我们必须要对轮播图模块进行优化。
优化方案
第一种优化方案肯定是使用Redis缓存,这种方式使用起来十分简单,也是大多数人的用法,通过去查询数据库取到数据,然后把从数据库取到的数据缓存到Redis的缓存中,这样做确实可以提高用户的体验感,但是用户可能还是感觉界面的响应时间有点长,能不能再进一步提高响应速度和并发性能呢?当然可以。
第二种优化方案就是使用Openresty整合Lua脚本访问Redis,直接将数据返回给前端界面,简单分析就是第一种方案虽然确实可以提升响应速度,但是它任然需要经过tomcat服务器,而使用第二种方案,根本就不需要经过tomcat服务器,直接在Nginx服务器中使用Lua脚本完成对MySQL和Redis的读写,这样做可以让前台的响应时间达到1~2秒,大大提高用户的体验感。
开发步骤:
1、缓存预热
使用Lua脚本读取MySQL中的轮播图数据,保存到Redis缓存中。
(1)编写一个ad_update.lua脚本,然后将ad_update.lua保存到openresty/nginx/conf/lua目录下
-- 获得uri中的sid参数值
local uri_args = ngx.req.get_uri_args()
local sid = uri_args["sid"]
-- 连接mysql
local mysql = require "resty.mysql"
local db = mysql:new()
db:set_timeout(1000)
local ok, err = db:connect{
host = "127.0.0.1",
port = 3306,
database = "edu_ad",
user = "root",
password = "123456",
charset = "utf8"
}
if not ok then
ngx.say("failed to connect: ", err)
return
end
ngx.say("connected to mysql.")
-- 按区域编号查询轮播图表
local res, err = db:query("select * from promotion_ad where space_id="..sid)
if not res then
ngx.say("bad result: ", err)
return
end
db:close()
-- 结果转换为json
local cjson = require "cjson"
ngx.say("res->",cjson.encode(res))
-- 连接redis
local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(2000)
local ok,err = red:connect("127.0.0.1",6379)
if not ok then
ngx.say("connect error: ", err)
return
end
-- 保存到reids
red:set("ad_space_"..sid,cjson.encode(res))
red:close()
ngx.say("updated redis")
(2)配置nginx.conf
server {
listen 8089;
default_type 'applicaiton/json;charset=utf8';
charset utf-8;
location /ad_update{
default_type text/html;
content_by_lua_file conf/lua/ad_update.lua;
}
}
2、缓存读取
缓存分为两级缓存,一级缓存是nginx内部缓存,二级是redis缓存,先读取内部缓存,如果没有再读取redis缓存。
(1)编写一个ad_load.lua脚本,然后将ad_load.lua保存到openresty/nginx/conf/lua目录下。
-- 获得sid参数
local uri_args = ngx.req.get_uri_args()
local sid = uri_args["sid"]
-- 读取内部缓存
local cache = ngx.shared.dis_cache:get('ad_space_'..sid)
if cache == nil then
-- 内部缓存没有读取redis
local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(2000)
local ok, err = red:connect("127.0.0.1", 6379)
local res = red:get('ad_space_'..sid)
ngx.say(res)
red:close()
-- 保存到内部缓存
ngx.shared.dis_cache:set('ad_space_'..sid, res, 10*60)
else
ngx.say(cache)
end
(2)配置nginx.conf
server {
listen 8089;
default_type 'applicaiton/json;charset=utf8';
charset utf-8;
location /ad_update{
default_type text/html;
content_by_lua_file conf/lua/ad_update.lua;
}
location /ad_load{
default_type text/html;
content_by_lua_file conf/lua/ad_load.lua;
}
}
(3)在nginx.conf文件里,在http模块跟server平级的地方加内部缓存配置:
lua_shared_dict dis_cache 5m;
3、把前端的访问路径改变成刚才配置的路径
可能会出现跨域的问题,因为是在虚拟机上面配置的,但是idea是在本地,解决方案从nginx服务进行反向代理到windows的路径。
配置nginx.conf
server {
listen 8089;
default_type 'applicaiton/json;charset=utf8';
charset utf-8;
location /ad_update{
default_type text/html;
content_by_lua_file conf/lua/ad_update.lua;
}
location /ad_load{
default_type text/html;
content_by_lua_file conf/lua/ad_load.lua;
}
location / {
root html;
index index.html index.htm;
proxy_pass http://192.168.110.27:8080;
}
}