Lua+Redis+OpenResty实现电商详情页
Posted 恒哥~Bingo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Lua+Redis+OpenResty实现电商详情页相关的知识,希望对你有一定的参考价值。
电商详情页案例介绍
电商的详情页是并发量很高的服务,开发者通常采用静态化或缓存的方式减少后台服务器的压力
案例的技术点:
-
OpenResty服务器,
介绍和安装可以参考 https://blog.csdn.net/u013343114/article/details/123991729
-
Lua调用Redis
-
Lua的http模块
-
Lua页面模板
下面先使用几个案例,介绍这些技术点
使用Lua连接Redis
OpenResty的库中自带的resty.redis可以用于连接Redis
在openresty/nginx/conf新建lua目录,新建redis_test.lua文件
-- 导入resty.redis
local redis = require "resty.redis"
-- 创建redis对象
local red = redis:new()
-- 连接redis ok返回成功信息,erro是错误信息
local ok,err = red:connect("127.0.0.1",6379)
if not ok then
ngx.say("connect failed",err)
return
end
-- 调用set命令
ok,err = red:set("city","wuhan")
if not ok then
ngx.say("redis set failed",err)
return
end
ngx.say("set city ok<br>")
-- 调用get命令
local val,err = red:get("city")
if not val then
ngx.say("redis get failed",err)
return
end
if val == ngx.null then
ngx.say("city is null")
return
end
-- 输出结果
ngx.say("city==>",val)
修改nginx.conf
server
listen 8080;
location /redis_test
default_type text/html;
content_by_lua_file conf/lua/redis_test.lua;
重启nginx,访问
使用Lua发送HTTP请求
使用Lua发送http请求可以借助开源框架 lua-resty-http
https://github.com/ledgetech/lua-resty-http
下载文件:http_headers.lua、http.lua、http_connect.lua
保存到openresty/lualib/resty目录下
基本的http请求
创建http_test.lua
-- 创建连接对象
local httpc = require("resty.http").new()
-- 发送GET请求
local res, err = httpc:request_uri("http://192.168.101.11:8001/item?id=99",
method = "GET",
headers =
["Content-Type"] = "application/x-www-form-urlencoded"
)
if not res then
ngx.log(ngx.ERR, "request failed: ", err)
return
end
-- 返回请求内容
local status = res.status
local length = res.headers["Content-Length"]
local body = res.body
ngx.say("body:",body)
使用SpringBoot开发接口
@RestController
public class HelloController
@Value("$server.port")
private Long port;
@RequestMapping("item")
public String item(Long id)
return "From: "+ port +",Get Item " + id;
修改nginx.conf
location /http_test3
default_type text/html;
content_by_lua_file conf/lua/http_test.lua;
重启nginx,访问
URL哈希实现负载均衡
下面案例通过对id参数进行哈希运算,对服务器列表实现负载均衡
local http = require("resty.http").new()
-- 服务器列表
local hosts = "192.168.101.11:8001","192.168.101:11:8002"
-- 获得id参数
local item_id= ngx.var.arg_id
if not item_id then
ngx.say("id is null")
return
end
-- 获得哈希值
local id_hash = ngx.crc32_long(item_id)
-- 计算下标 lua从1开始
local index = (id_hash % 2) +1
-- 通过下标获得主机名,执行GET请求
local resp, err = http:request_uri("http://"..hosts[index],
method = "GET",
path = "/item?id="..item_id,
headers =
["Content-Type"] = "application/x-www-form-urlencoded"
)
if not resp then
ngx.say("request error :", err)
return
end
ngx.say(resp.body)
http:close()
让后台接口在8001和8002两个端口启动,不同的id会访问不同的服务器
使用Lua创建页面模板
lua-resty-template可以使用Lua创建类似JSP的模板
https://github.com/bungle/lua-resty-template
下载template和template.lua,保存到resty中
基本使用
view_template.lua
local template = require "resty.template"
-- 方法1 使用new方法进行页面渲染,message是自定义数据
local view = template.new "view.html"
view.message = "Hello, World!"
view:render()
-- 方法2 使用render实现页面渲染
template.render("view.html", message = "Hello, World!" )
nginx/html/view.html
<!DOCTYPE html>
<html>
<body>
<h1>message</h1>
</body>
</html>
nginx.conf
location /view_template
default_type text/html;
content_by_lua_file conf/lua/view_template.lua;
root html;
index view.html;
访问效果
Lua+Redis+OpenResty实现电商详情页
实现思路
course.lua
-- 获得路径参数id
local id = ngx.var.id
-- 连接redis
local redis = require "resty.redis"
local red = redis:new()
local ok,err = red:connect("127.0.0.1",6379)
if not ok then
ngx.say("connect failed",err)
return
end
-- 查询该id的课程
local val,err = red:get("course"..id)
if not val then
ngx.say("redis get failed",err)
return
end
if val == ngx.null then
-- 缓存为空,查询后台接口
local httpc = require("resty.http").new()
local res, err = httpc:request_uri("http://192.168.101.18:8002/course/"..id,
method = "GET",
headers =
["Content-Type"] = "application/x-www-form-urlencoded"
)
if not res then
ngx.log(ngx.ERR, "request failed: ", err)
return
end
val = res.body
if val == ngx.null then
ngx.say("course not found ",id)
return
end
-- 保存到redis
red:set("course"..id,val)
end
-- 实现页面渲染
local template = require "resty.template"
template.caching(false)
local context =
course = val
template.render("course.html", context)
nginx.conf
location ~*/course/([0-9]+)$
default_type text/html;
root html;
set $id $1; #获得uri最后的数字保存到id变量中,lua中通过ngx.var.id获得
index course.html;
content_by_lua_file conf/lua/course.lua;
course.html\\css\\js 保存到nginx/html目录中
页面使用了Vue.js,其中Vue的 符号和Lua模板冲突,所以需要使用-raw-括起来,Lua不进行处理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>课程页面</title>
<link rel="stylesheet" type="text/css" href="/css/course.css">
</head>
<body>
<div id="course">
<div style="background: #eee;">
<div class="nav-wrap">
<p class="nav-p-pc" style="margin-top:-25px;text-align:left;">
<a href="/">课程列表</a>
<span class="sharp-content">></span>
<span class="nav-sec">-raw-course.courseName-raw-</span>
</p>
</div>
<!-- 课程详情 -->
...
-raw-course.price-raw-
...
</div>
</div>
</body>
<script src="/js/vue.js"></script>
<script>
var vue = new Vue(
el: "#course",
data:
course:*course* //以非转义方式绑定lua模板中的course对象
,
created()
console.log(this.course);
);
</script>
</html>
后台查询接口
@RestController
public class CourseController
@Autowired
private CourseService courseService;
@GetMapping("course/courseid")
public Course getCourseById(@PathVariable("courseid")Integer courseid)
Course course = courseService.getCourseById(courseid);
return course;
访问效果
以上是关于Lua+Redis+OpenResty实现电商详情页的主要内容,如果未能解决你的问题,请参考以下文章
使用Lua+Redis+OpenResty实现电商首页并发优化
使用Lua+Redis+OpenResty实现电商首页并发优化