多级缓存架构(三)OpenResty Lua缓存

文章目录

  • 一、nginx服务
  • 二、OpenResty服务
      • 1. 服务块定义
      • 2. 配置修改
      • 3. Lua程序编写
      • 4. 总结
  • 三、运行
  • 四、测试
  • 五、高可用集群
      • 1. openresty
      • 2. tomcat

通过本文章,可以完成多级缓存架构中的Lua缓存。
在这里插入图片描述
在这里插入图片描述

一、nginx服务

docker/docker-compose.yml中添加nginx服务块。

  nginx:container_name: nginximage: nginx:stablevolumes:- ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf- ./nginx/conf/conf.d/default.conf:/etc/nginx/conf.d/default.conf- ./nginx/dist:/usr/share/nginx/distports:- "8080:8080"networks:multi-cache:ipv4_address: 172.30.3.3

删除原来docker里的multiCache项目并停止springboot应用。

nginx部分配置如下,监听端口为8080,并且将请求反向代理至172.30.3.11,下一小节,将openresty固定在172.30.3.11

upstream nginx-cluster {server 172.30.3.11;
}server {listen       8080;listen  [::]:8080;server_name  localhost;location /api {proxy_pass http://nginx-cluster;}
}

重新启动multiCache看看nginx前端网页效果。

docker-compose -p multi-cache up -d

访问http://localhost:8080/item.html?id=10001查询id=10001商品页
在这里插入图片描述
这里是假数据,前端页面会向/api/item/10001发送数据请求。

二、OpenResty服务

1. 服务块定义

docker/docker-compose.yml中添加openresty1服务块。

  openresty1:container_name: openresty1image: openresty/openresty:1.21.4.3-3-jammy-amd64volumes:- ./openresty1/conf/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf- ./openresty1/conf/conf.d/default.conf:/etc/nginx/conf.d/default.conf- ./openresty1/lua:/usr/local/openresty/nginx/lua- ./openresty1/lualib/common.lua:/usr/local/openresty/lualib/common.luanetworks:multi-cache:ipv4_address: 172.30.3.11

2. 配置修改

前端向后端发送/api/item/10001请求关于id=10001商品信息。

根据nginx的配置内容,这个请求首先被nginx拦截,反向代理到172.30.3.11 (即openresty1)。

upstream nginx-cluster {server 172.30.3.11;
}server {location /api {proxy_pass http://nginx-cluster;}
}

openresty1收到的也是/api/item/10001,同时,openresty/api/item/(\d+)请求代理到指定lua程序,在lua程序中完成数据缓存。
在这里插入图片描述
因此,openrestyconf/conf.d/default.conf如下

upstream tomcat-cluster {hash $request_uri;server 172.30.3.4:8081;
#     server 172.30.3.5:8081;
}server {listen       80;listen  [::]:80;server_name  localhost;# intercept /item and join lualocation ~ /api/item/(\d+) {default_type application/json;content_by_lua_file lua/item.lua;}# intercept lua and redirect to back-endlocation /path/ {rewrite ^/path/(.*)$ /$1 break;proxy_pass http://tomcat-cluster;}error_page   500 502 503 504  /50x.html;location = /50x.html {root   /usr/share/nginx/dist;}
}

conf/nginx.confhttp块最后添加3行,引入依赖。

    #lua 模块lua_package_path "/usr/local/openresty/lualib/?.lua;;";#c模块lua_package_cpath "/usr/local/openresty/lualib/?.so;;";#本地缓存lua_shared_dict item_cache 150m;

3. Lua程序编写

common.lua被挂载到lualib,表示可以被其他lua当做库使用,内容如下

-- 创建一个本地缓存对象item_cache
local item_cache = ngx.shared.item_cache;-- 函数,向openresty本身发送类似/path/item/10001请求,根据conf配置,将被删除/path前缀并代理至tomcat程序
local function read_get(path, params)local rsp = ngx.location.capture('/path'..path,{method = ngx.HTTP_GET,args = params,})if not rsp thenngx.log(ngx.ERR, "http not found, path: ", path, ", args: ", params);ngx.exit(404)endreturn rsp.body
end-- 函数,如果本地有缓存,使用缓存,如果没有代理到tomcat然后将数据存入缓存
local function read_data(key, expire, path, params)-- query local cachelocal rsp = item_cache:get(key)-- query tomcatif not rsp thenngx.log(ngx.ERR, "redis cache miss, try tomcat, key: ", key)rsp = read_get(path, params)end-- write into local cacheitem_cache:set(key, rsp, expire)return rsp
endlocal _M = {read_data = read_data
}return _M

item.lua是处理来自形如/api/item/10001请求的程序,内容如下

-- include
local commonUtils = require('common')
local cjson = require("cjson")-- get url params 10001
local id = ngx.var[1]
-- redirect item, 缓存过期时间1800s, 适合长时间不改变的数据
local itemJson = commonUtils.read_data("item:id:"..id, 1800,"/item/"..id,nil)
-- redirect item/stock, 缓存过期时间4s, 适合经常改变的数据
local stockJson = commonUtils.read_data("item:stock:id:"..id, 4 ,"/item/stock/"..id, nil)
-- json2table
local item = cjson.decode(itemJson)
local stock = cjson.decode(stockJson)
-- combine item and stock
item.stock = stock.stock
item.sold = stock.sold
-- return result
ngx.say(cjson.encode(item))

4. 总结

  1. 这里luaitem(tb_item表)和stock(tb_stock表)两个信息都有缓存,并使用cjson库将两者合并后返回到前端。
  2. 关于expire时效性的问题,如果后台改变了数据,但是openresty关于此数据的缓存未过期,前端得到的是旧数据
  3. 大致来说openresty = nginx + lua,不仅具有nginx反向代理的能力,还能介入lua程序进行扩展。

三、运行

到此为止,docker-compose.yml应该如下

version: '3.8'networks:multi-cache:driver: bridgeipam:driver: defaultconfig:- subnet: 172.30.3.0/24services:mysql:container_name: mysqlimage: mysql:8volumes:- ./mysql/conf/my.cnf:/etc/mysql/conf.d/my.cnf- ./mysql/data:/var/lib/mysql- ./mysql/logs:/logsports:- "3306:3306"environment:- MYSQL_ROOT_PASSWORD=1009networks:multi-cache:ipv4_address: 172.30.3.2nginx:container_name: nginximage: nginx:stablevolumes:- ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf- ./nginx/conf/conf.d/default.conf:/etc/nginx/conf.d/default.conf- ./nginx/dist:/usr/share/nginx/distports:- "8080:8080"networks:multi-cache:ipv4_address: 172.30.3.3openresty1:container_name: openresty1image: openresty/openresty:1.21.4.3-3-jammy-amd64volumes:- ./openresty1/conf/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf- ./openresty1/conf/conf.d/default.conf:/etc/nginx/conf.d/default.conf- ./openresty1/lua:/usr/local/openresty/nginx/lua- ./openresty1/lualib/common.lua:/usr/local/openresty/lualib/common.luanetworks:multi-cache:ipv4_address: 172.30.3.11

启动各项服务

docker-compose -p multi-cache up -d

启动springboot程序。
在这里插入图片描述

四、测试

清空openresty容器日志。
访问http://localhost:8080/item.html?id=10001
查看openresty容器日志,可以看到两次commonUtils.read_data都没有缓存,于是代理到tomcat,可以看到springboot日志出现查询相关记录。

2024-01-12 11:45:53 2024/01/12 03:45:53 [error] 7#7: *1 [lua] common.lua:99: read_data(): redis cache miss, try tomcat, key: item:id:10001, client: 172.30.3.3, server: localhost, request: "GET /api/item/10001 HTTP/1.0", host: "nginx-cluster", referrer: "http://localhost:8080/item.html?id=10001"
2024-01-12 11:45:53 2024/01/12 03:45:53 [error] 7#7: *1 [lua] common.lua:99: read_data(): redis cache miss, try tomcat, key: item:stock:id:10001 while sending to client, client: 172.30.3.3, server: localhost, request: "GET /api/item/10001 HTTP/1.0", host: "nginx-cluster", referrer: "http://localhost:8080/item.html?id=10001"
2024-01-12 11:45:53 172.30.3.3 - - [12/Jan/2024:03:45:53 +0000] "GET /api/item/10001 HTTP/1.0" 200 486 "http://localhost:8080/item.html?id=10001" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0"

再次访问此网址,强制刷新+禁用浏览器缓存+更换浏览器
间隔超过4s但小于1800s时,日志如下,只出现一次miss。

2024-01-12 11:48:04 2024/01/12 03:48:04 [error] 7#7: *4 [lua] common.lua:99: read_data(): redis cache miss, try tomcat, key: item:stock:id:10001, client: 172.30.3.3, server: localhost, request: "GET /api/item/10001 HTTP/1.0", host: "nginx-cluster", referrer: "http://localhost:8080/item.html?id=10001"
2024-01-12 11:48:04 172.30.3.3 - - [12/Jan/2024:03:48:04 +0000] "GET /api/item/10001 HTTP/1.0" 200 486 "http://localhost:8080/item.html?id=10001" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0"

再次访问此网址,强制刷新+禁用浏览器缓存+更换浏览器
间隔小于4s,日志如下,未出现miss。

2024-01-12 11:49:16 172.30.3.3 - - [12/Jan/2024:03:49:16 +0000] "GET /api/item/10001 HTTP/1.0" 200 486 "http://localhost:8080/item.html?id=10001" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0"

五、高可用集群

1. openresty

在这里插入图片描述
对于openresty高可用,可以部署多个openresty docker实例,并在nginxdocker/nginx/conf/conf.d/default.confupstream nginx-cluster将多个openresty地址添加进去即可。比如

upstream nginx-cluster {hash $request_uri;# hash $request_uri consistent;server 172.30.3.11;server 172.30.3.12;server 172.30.3.13;
}

多个openresty 无论是conf还是lua都保持一致即可。
并且使用hash $request_uri负载均衡作为反向代理策略,防止同一请求被多个实例缓存数据。

2. tomcat

在这里插入图片描述
对于springboot程序高可用,也是类似。可以部署多个springboot docker实例,并在openresty docker/openresty1/conf/conf.d/default.confupstream nginx-cluster将多个springboot地址添加进去即可。比如

upstream tomcat-cluster {hash $request_uri;server 172.30.3.4:8081;server 172.30.3.5:8081;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/626367.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

评估文字识别准确性的方法与流程

随着信息技术的发展,文字识别技术在各个领域得到了广泛的应用。然而,在实际应用中,如何评估文字识别的准确性,一直是相关领域的一个难题。本文将介绍几种常用的文字识别准确性评估方法,以期为相关领域的研究提供参考。…

使用vite框架封装vue3插件,发布到npm

目录 一、vue环境搭建 1、创建App.vue 2、修改main.ts 3、修改vite.config.ts 二、插件配置 1、创建插件 2、开发调试 3、打包配置 4、package.json文件配置 上一篇文章讲述使用vite《如何使用vite框架封装一个js库,并发布npm包》封装js库,本文将…

Jmeter后置处理器——JSON提取器

目录 1、简介 2、使用步骤 1)添加线程组 2)添加http请求 3) 添加JSON提取器 1、简介 JSON是一种简单的数据交换格式,允许互联网应用程序快速传输数据。JSON提取器可以从JSON格式响应数据中提取数据、简化从JSON原始数据中提取特定…

Java学习——Junit单元测试

​​ Junit:事实上的标准单元测试框架 使用Junit:只需要使用 TestCase 和 Assert http://t.csdnimg.cn/hgMFJ

Linux网络编程---IP 地址格式转换函数

Linux网络编程—IP 地址格式转换函数 我们更容易阅读的IP地址是以点分十进制表示的,例如:192.168.5.10 ,这是一种字符串的形式,但是计算器所需要的IP地址是以二进制进行表示,这便需要我们在点分十进制字符串和二进制地…

java版直播商城平台规划及常见的营销模式 电商源码/小程序/三级分销+商城 免 费 搭 建

鸿鹄云商 B2B2C产品概述 【B2B2C平台】,以传统电商行业为基石,鸿鹄云商支持“商家入驻平台自营”多运营模式,积极打造“全新市场,全新 模式”企业级B2B2C电商平台,致力干助力各行/互联网创业腾飞并获取更多的收益。从消…

【现代密码学】笔记6--伪随机对象的理论构造《introduction to modern cryphtography》

【现代密码学】笔记6--伪随机对象的理论构造《introduction to modern cryphtography》 写在最前面6 伪随机对象的理论构造 写在最前面 主要在 哈工大密码学课程 张宇老师课件 的基础上学习记录笔记。 内容补充:骆婷老师的PPT 《introduction to modern cryphtogr…

Qt/C++中英输入法/嵌入式输入法/小数字面板/简繁切换/特殊字符/支持Qt456

一、前言 在嵌入式板子上由于没有系统层面的输入法支持,所以都绕不开一个问题,那就是在需要输入的UI软件中,必须提供一个输入法来进行输入,大概从Qt5.7开始官方提供了输入法的源码,作为插件的形式加入到Qt中&#xff…

网络广播号角喇叭在智能工地施工现场的应用,以及网络广播在公共广播中的实际作用。

网络号角喇叭在智能工地施工现场的应用,以及网络广播在公共广播中的实际作用。 SV-7044村村通ip网络通信广播号角喇叭,网络音箱,网络音柱是一种公共广播技术,主要应用于公共场所,如公交、商场、大型活动场所等。可以用…

visual studio的安装及scanf报错的解决

visual studio是一款很不错的c语言编译器 下载地址:官网 点击后跳转到以下界面 下滑后点击下载Vasual Sutdio,选择社区版即可 选择位置存放下载文件后,即可开始安装 安装时会稍微等一小会儿。然后会弹出这个窗口,我们选择安装位…

无需编程,简单易上手的家具小程序搭建方法分享

想要开设一家家具店的小程序吗?现在,我将为大家介绍如何使用乔拓云平台搭建一个家具小程序,帮助您方便快捷地开展线上家具销售业务。 第一步,登录乔拓云平台进入商城后台管理页面。 第二步,在乔拓云平台的后台管理页面…

Vulnhub-Raven-1

一、信息收集 端口扫描 PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 6.7p1 Debian 5deb8u4 (protocol 2.0) | ssh-hostkey: | 1024 26:81:c1:f3:5e:01:ef:93:49:3d:91:1e:ae:8b:3c:fc (DSA) |_ 256 0e:85:71:a8:a2:c3:08:69:9c:91:c0:3f:84:18:df:…

多线程——CAS

什么是CAS CAS的全称:Compare and swap,字面意思就是:“比较并交换”,一个CAS涉及到以下操作: 假设内存中的原数据V,旧的预期值A,需要修改的新值B 1.比较A与V是否相等(比较&#xf…

antd pro项目部署到gitpage白屏

先总结一下如何部署项目到gitpage 1.新建分支gh-pages 2.把打包好的文件放在这个分支下 3. 之前打开一直白屏,有很多坑 第一个,import { getIntl } from umijs/max;这个引入要,不能是./引入的 第二个,新建一个config.prod.t…

盘点2023年信息系统故障

安全生产,人人有责。每年信息系统安全事件层出不穷,作为一线运维人员对这些生产安全故障当抱有敬畏之心,并从中总结经验教训,分析原因,不能简单的调侃为开猿节流、降本增笑的结果。本文简要盘点2023年发生的主要信息系…

Java NIO (一)简介(备份)

1 NIO简介 在1.4版本之前,Java NIO类库是阻塞IO,从1.4版本开始,引进了新的异步IO库,被称为Java New IO类库,简称为Java NIO。New IO类库的目的 就是要让Java支持非阻塞IO。 Java NIO类库包含三个核心组件: …

Shell基本操作(2)

文件显示与编辑 连接并显示文件内容 cat cat[options] file... options -n加上行号 -s将连续两行以上的空白行替换为一行如果file不止一个文件,则会将它们连接起来如果想一次只看一页,可以使用more或者less命令 过滤文件内容grep grep命令可以查找拥…

【STM32CubeMX串口通信详解】USART1 -- DMA发送 + DMA空闲中断 接收不定长数据

文章目录: 前言 一、准备工作 1、接线 2、新建工程 二、CubeMX的配置 1、USART1 配置 异步通信 2、通信协议参数 3、打开DMA发送、接收 三、发送操作、代码解释 四、printf 重定向到USART1 五、接收代码的编写 1、定义一个结构体变量&a…

初识 Elasticsearch 应用知识,一文读懂 Elasticsearch 知识文集(4)

🏆作者简介,普修罗双战士,一直追求不断学习和成长,在技术的道路上持续探索和实践。 🏆多年互联网行业从业经验,历任核心研发工程师,项目技术负责人。 🎉欢迎 👍点赞✍评论…

金和OA jc6 Upload 任意文件上传漏洞复现

0x01 产品简介 金和OA协同办公管理系统软件(简称金和OA),本着简单、适用、高效的原则,贴合企事业单位的实际需求,实行通用化、标准化、智能化、人性化的产品设计,充分体现企事业单位规范管理、提高办公效率的核心思想,为用户提供一整套标准的办公自动化解决方案,以帮助…