Nginx+Lua+Redis 实现Nginx301跳转配置管理

在这里插入图片描述

业务场景需求


long long ago:

在项目的运维过程中有一次SEO团队提出 网页的URL 中如果可以带上关键字,那么网页在各大搜索引擎中收录和排名有非常重大的突出优势(~~SEO团队到底专不专业 ~~,此处不做置评),遂业务方决定,项目的CMS系统中增加修改页面URL的功能(不是什么大事,甲方爸爸要求了就加了)。
功能增加后,业务人员笃信此内容有效果,一天增删改好几遍,对于搜索引擎收录后的页面修改URL后要求增加301或302跳转,确保对搜索引擎友好。(虽然一天改那么多遍,到底友好在哪儿 我也不知道,不予置评)

因为项目架构涉及到多层级CDN分发,网站内容静态化管理,流量资源控制等情况,采用的是将变更URL的301映射定期存储在配置文件中进行reload的方式,为确保系统稳定,选择了每日更新的情况。

now :
外来的运维团队对实时性情况要求逐渐提升,要求立马生效,遂寻求了此解决方案。

在这个业务场景的解决问题上,我是在mac本地进行的流程验证和测试,旨为梳理思路和流程。在其他平台,也可以找到对应的方式。(官方文档和教程中都有我就不赘述了)

OpenResty = Nginx+Lua


因为web服务器一直使用的是Nginx,在项目中也有对Nginx源码的改造需求在,所以在此解决方案中选择了OpenResty。

https://openresty.org/

OpenResty是通过Lua 扩展Nginx 实现的可伸缩的Web平台。可以理解为Web服务核心是Nginx,但是通过Lua的方式增加了很多的扩展功能,还是很Nice的。

Nginx 早年间推出了njs 模块,支持使用javascript的部分子集进行扩展,也是不错的方式,但是在Nginx的许多场景中NJS的扩展使用生态没有Lua的好一些,在解决问题和功能扩展上不如Lua容易,感谢社区和开源的大佬。

MacOS下安装 :

brew install openresty/brew/openresty

在这里插入图片描述

需要注意

brew install openresty #采用此命令是安装不了的,会说找不到

安装后需要添加环境变量,以便Nginx 命令启动可以找到
在这里插入图片描述

brew安装后的地址(macOS)可以参考以下,其他的可能在/usr/local/openresty(这是默认地址)

PATH=/opt/homebrew/Cellar/openresty/1.25.3.1_1/nginx/sbin:$PATH
export PATH

之后创建Web服务所需的工作区

mkdir www logs conf

在这里插入图片描述

创建工作区这一步是因为我在全新的环境终验证流程所需,在已有的项目中,可以依据自身的情况进行配置即可,后续的命令是在nginx-lua-redis目录下执行的,如果切换到了别的目录,注意一些命令中所需的文件路径的变更。

在conf文件夹下新建一个示例配置Nginx.conf

worker_processes 1; 
error_log logs/error.log; 
events { 
	worker_connections 1024; 
} 
http {
	server {
		 listen 8080; 
		 location / {
			  default_type text/html; 
			  content_by_lua_block {
				   ngx.say("<p>hello, world</p>") 
			   } 
	   } 
   } 
}

然后启动Nginx 服务:

nginx -p `pwd`/ -c conf/nginx.conf

如果说找不到文件,就检查一下自己所在路径是否正确。

测试:

curl http://localhost:8080/

结果:

<p>hello, world</p>

此时在nginx-lua-redis目录下会自动生成其他web服务所需的相关文件,可以不必理会。

此时Nginx+Lua环境就可以使用了,这里得益于OpenResty项目的集成,如果采用Nginx + Lua模块及其他扩展的安装会稍显麻烦,毕竟还有许多依赖和听都没听过得许多模块要学习和了解…… OpenResty本身已经集成了大多是扩展所需,Nice +1.

Redis 支持


为什么这个方案中用Redis?因为官网说它快……

在这里插入图片描述

Redis在mac上安装也是相对简单

brew install redis
brew services start redis
redis-server

在这里插入图片描述

Ok,Redis 的简单实例就搭好了

新开终端窗口测试链接:

redis-cli -h 127.0.0.1 -p 6379

因为是流程验证和测试,不想写为Redis写什么代码,直接从官网下载了支持Mac的免费客户端 :
RedisInsight https://redis.io/insight/
完全傻瓜化的操作,而且界面也很好看

在这里插入图片描述

在这里我尝试创建了两组页面跳转的实例,最终选择了HASH的模式.在自带的终端中创建了百度和知乎的跳转键值对用作后续的测试。

Redis中不同的数据类型操作方式不同,选择不同的数据类型在Lua脚本调用时需要进行调整。
Lua调用Redis中数据匹配跳转规则时,传入的URL数据是从"/"开始的,这也是为什么截图中有两组数据的原因(第一组我忘记这个事儿了,所以失败了,然后才想起来😭)

配置文件案例


Nginx + Lua脚本的实现是比较轻松地,只要了解了语法写起来就很轻松。这个实例的核心就是Nginx 在 匹配的URL 规则时,通过Lua脚本 调用后端Redis 中存储的301跳转规则,而不是之前写在配置文件中固定规则。通过对Redis的操作,来实时进行规则内容的更新。

worker_processes  1;
error_log logs/error.log;
events {
    worker_connections 1024;
}
http {
    lua_shared_dict redirects_cache 3m; # 分配1MB共享内存用于缓存

    server {
        listen 8080;
        
        location / {
            access_by_lua_block {
                local redis = require "resty.redis"
                local red = redis:new()
                red:set_timeout(1000) -- 设置超时时间
                local ok, err = red:connect("127.0.0.1", 6379)
                
                if not ok then
                    ngx.log(ngx.ERR, "failed to connect to redis: ", err)
                    return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
                end
                
                -- 尝试从缓存中获取跳转规则
                local cached_redirect = ngx.shared.redirects_cache:get(ngx.var.uri)
                if cached_redirect then
                    ngx.redirect(cached_redirect, 301)
                    return
                end
                
                -- 查询Redis
                local new_url = red:hget("redirects", ngx.var.uri)
                if type(new_url)=="string" then
                    -- 缓存结果以加速后续请求
                    ngx.shared.redirects_cache:set(ngx.var.uri, new_url, 600) -- 缓存600秒
                    red:close() -- 关闭连接
                    ngx.redirect(new_url, 301)
                    return
                end
                red:close()
            }
            
            default_type text/html;
            content_by_lua_block {
                ngx.say("<p>hello, world. nginx-lua-Redis</p>")
            }
        }
    }
}

redirects_cache:设置一个缓存区,毕竟每次都去查Redis也是要消耗的,缓存之后消耗会少一些,缓存多大要看项目中需要的301规则有多少。

通过访问预设的地址都可以正常跳转

localhost:8080/test1.shtml -> 正确的去了百度
localhost:8080/test2.shtml -> 正确的去了知乎

在对Redis 中数据进行更新后,跳转效果也可以实时生效。

后记:


关于Nginx 热加载 reload

Nginx本身是提供热加载的 :

nginx -s reload

这也是我们之前自动化所采用的方式。在实际使用中,大流量或者长链接保持情况下,reload的方式式经常会出现一些意外情况,比如服务中断,reload失败等等。所以在早期的方案中我们实际是高可用集群切换来保障自动更新的效果。但是目前业务方热衷于频繁修改URL跳转规则,并要求在短时间内立马生效。采用 Reload的方式对 平台业务服务的稳定性增加了较多隐患,可能这次集群Reload还没结束,下次又开始了,对于系统消耗和稳定性的考虑才决定尝试验证Nginx+Lua+Redis的方案。

方案的局限性
这个方案的产生和测试,都是基于在手的一个项目业务情况和环境需求所产生的,并不是说这是一个非常完善或者普适性的方案,它只解决我所处情况的问题,这里做的总结只是做一个思路梳理和验证,实际的项目中要依据自身情况进行。如有更好的方法和意见,欢迎批评指正。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C/C++ strftime函数

目录 strftime()函数 函数原型 头文件 功能 返回值 参数 案例 结语 strftime()函数 函数原型 size_t strftime(char *s, size_t max, const char *format, const struct tm *tm); 头文件 #include <time.h> 功能 用于日期和时间格式化的函数&#xff0c;它允许你…

【算法】二叉树 - 理论基础

1.种类 1.1 满二叉树 只有度为0和2的节点&#xff0c;且度为0的节点都都在同一层。深度为k&#xff0c;有2^k-1个节点。 1.2 完全二叉树 在完全二叉树中&#xff0c;除了最底层节点可能没填满外&#xff0c;其余每层节点数都达到最大值&#xff0c;并且最下面一层的节点都…

【论文复现|智能算法改进】一种基于多策略改进的鲸鱼算法

目录 1.算法原理2.改进点3.结果展示4.参考文献5.代码获取 1.算法原理 SCI二区|鲸鱼优化算法&#xff08;WOA&#xff09;原理及实现【附完整Matlab代码】 2.改进点 混沌反向学习策略 将混沌映射和反向学习策略结合&#xff0c;形成混沌反向学习方法&#xff0c;通过该方 法…

Atcoder Beginner Contest 359

传送门 A - Count Takahashi 时间限制&#xff1a;2秒 内存限制&#xff1a;1024MB 分数&#xff1a;100分 问题描述 给定 N 个字符串。 第 i 个字符串 () 要么是 Takahashi 要么是 Aoki。 有多少个 i 使得 等于 Takahashi &#xff1f; 限制 N 是整数。每个…

Cyber Weekly #12

赛博新闻 1、Anthropic发布Claude 3.5 Sonnet 本周五&#xff08;6月21日&#xff09;凌晨&#xff0c;Anthropic宣布推出其最新的语言模型Claude 3.5 Sonnet&#xff0c;距离上次发布Claude3才过去3个月。Claude3.5拥有20万token的长上下文窗口&#xff0c;目前已经在Claude…

数据库断言

在数据库验证断言 目的&#xff1a;不能相信接口返回结果&#xff0c;通过到数据库检验可知接口返回结果是否真的正确 如何校验&#xff1a;代码与mymql建立网络连接&#xff0c;操作数据库&#xff0c;断开连接 代码&#xff1a;java操作数据库 pom文件配置依赖 步骤&…

15.树形虚拟列表实现(支持10000+以上的数据)el-tree(1万+数据页面卡死)

1.问题使用el-tree渲染的树形结构&#xff0c;当数据超过一万条以上的时候页面卡死 2.解决方法&#xff1a; 使用vue-easy-tree来实现树形虚拟列表&#xff0c;注意&#xff1a;vue-easy-tree需要设置高度 3.代码如下 <template><div class"ve-tree" st…

ARM32开发--WDGT看门狗

知不足而奋进 望远山而前行 目录 文章目录 前言 目标 内容 什么是看门狗 ARM中的看门狗 独立看门狗定时器 窗口看门狗定时器 独立看门狗FWDGT 初始化配置 喂狗 完整代码 窗口看门狗WWDGT 初始化配置 喂狗 完整代码 注意 总结 前言 嵌入式系统在如今的科技发…

OpenGL3.3_C++_Windows(18)

接口块&#xff1a; glsl彼此传输数据&#xff0c;通过in / out&#xff0c;当更多的变量&#xff0c;涉及数组和结构体接口块(Interface Block)类似struct&#xff0c;in / out 块名{……}实例名 Uniform缓冲对象&#xff1a; 首先理解uniform Object&#xff1a;负责向gl…

基于协方差信息的Massive MIMO信道估计算法性能研究

1. 引言 随着移动互联网不断发展&#xff0c;人们对通信的速率和可靠性的要求越来越高[1]。目前第四代移动通信系统已经逐渐商用&#xff0c;研究人员开始着手研究下一代移动通信系统相关技术[2][3]。在下一代移动通信系统中要求下行速率达到10Gbps&#xff0c;这就要求我们使…

Debian Linux安装minikubekubectl

minikube&kubectl minkube用于在本地开发环境中快速搭建一个单节点的Kubernetes集群,还有k3s&#xff0c;k3d&#xff0c;kind都是轻量级的k8skubectl是使用K8s API 与K8s集群的控制面进行通信的命令行工具 这里使用Debian Linux演示&#xff0c;其他系统安装见官网,首先…

完美解决找不到steam_api64.dll无法执行代码问题

游戏缺失steam_api64.dll通常意味着该游戏依赖于Steam平台的一些功能或服务&#xff0c;而这个DLL文件是Steam客户端的一部分&#xff0c;用于游戏与Steam平台之间的交互。如果游戏中缺失这个文件&#xff0c;可能会出现无法启动、崩溃或其他问题。 一&#xff0c;详细了解stea…

Java内存泄漏检测和分析介绍

在Java中&#xff0c;内存泄漏检测和分析是一个重要的任务&#xff0c;可以通过以下几种方式进行&#xff1a; 1. 使用VisualVM VisualVM是一个可视化工具&#xff0c;可以监控、分析Java应用程序的内存消耗。它可以显示堆内存、垃圾收集、线程等信息&#xff0c;并且可以对内…

Linux - 利用/proc/sys/vm/drop_caches实现手工清理系统缓存

文章目录 现象buff/cache 的作用和含义分析 buff/cache 占用大量内存的原因是否需要清理缓存及其方法 命令清理缓存方法1. sync 命令2. echo 3>/proc/sys/vm/drop_caches 命令 注意事项小结 现象 使用free 命令&#xff0c;看到 buff/cache 占用很多 。 free 命令用于显示系…

用 idea 启动多个实例

在学习负载均衡的时候&#xff0c;要模拟多个实例均提供一个服务&#xff0c;我们要如何用 idea 启动多个实例呢&#xff1f; 如下图&#xff0c;我们已经启动了一个 ProductService 服务&#xff0c;现在想再启动两个相同的服务 1. 选中要启动的服务,右键选择 Copy Configura…

【机器学习】音乐大模型的深入探讨——当机器有了创意,是机遇还是灾难?

&#x1f440;国内外音乐大模型基本情况&#x1f440; ♥概述♥ ✈✈✈如FreeCompose、一术科技等&#xff0c;这些企业专注于开发人工智能驱动的语音、音效和音乐生成工具&#xff0c;致力于利用核心技术驱动文化产业升级。虽然具体公司未明确提及&#xff0c;但可以预见的是…

docker搭建mongo副本集

1、mongo集群分类 MongoDB集群有4种类型&#xff0c;分别是主从复制、副本集、分片集群和混合集群。 MongoDB的主从复制是指在一个MongoDB集群中&#xff0c;一个节点&#xff08;主节点&#xff09;将数据写入并同步到其他节点&#xff08;从节点&#xff09;。主从复制提供…

图像数字化基础

一、像素 1、获取图像指定位置的像素 import cv2 image cv2.imread("E:\\images\\2.png") px image[291,218] print("坐标(291,218)上的像素的BGR值是&#xff1a;",px) &#xff08;1&#xff09;RGB色彩空间 R通道&#xff1a;红色通道 G通道&…

Failed to establish a new connection: [WinError 10061] 由于目标计算机积极拒绝,无法连接

在进行参数化读取时发现一个问题&#xff1a; 发现问题&#xff1a; requests.exceptions.ConnectionError: HTTPConnectionPool(hostlocalhost, port8081): Max retries exceeded with url: /jwshoplogin/user/update_information.do (Caused by NewConnectionError(<url…

MFC学习--CListCtrl复选框以及选择

如何展示复选框 //LVS_EX_CHECKBOXES每一行的最前面带个复选框//LVS_EX_FULLROWSELECT整行选中//LVS_EX_GRIDLINES网格线//LVS_EX_HEADERDRAGDROP列表头可以拖动m_listctl.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES | LVS_EX_GRIDLINES); 全选&#xff0c;全…