Nginx技术研究系列2-基于Redis实现动态路由
上篇博文我们写了个引子:
Ngnix技术研究系列1-通过应用场景看Nginx的反向代理
发现了新大陆,OpenResty
OpenResty 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。
OpenResty 通过汇聚各种设计精良的 Nginx 模块(主要由 OpenResty 团队自主开发),从而将 Nginx 有效地变成一个强大的通用 Web 应用平台。这样,Web 开发人员和系统工程师可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,快速构造出足以胜任 10K 乃至 1000K 以上单机并发连接的高性能 Web 应用系统。
OpenResty的目标是让你的Web服务直接跑在 Nginx 服务内部,充分利用 Nginx 的非阻塞 I/O 模型,不仅仅对 HTTP 客户端请求,甚至于对远程后端诸如 MySQL、PostgreSQL、Memcached 以及 Redis 等都进行一致的高性能响应。
回到我们的原始需求:
http://api.***.com/action => http://192.168.0.11/api/action
Header: *** Header: ***
Body: *** Body: ***
通过Actiton获取对应的后端服务器地址
Action和服务器的对应关系(路由表)存储在Redis中.(实时更新实时获取)
根据请求的Action动态解析对应的内网服务器地址,再实现服务的转发。
Nginx原生的路由配置无法实现上述动态路由配置,因为我们要访问Redis,获取到反向代理的路由信息,再实现服务的转发。详细的实现步骤:
1. 解析URL中的Action
2.访问Redis,Key=Action Value=内网服务器地址
3.Http请求转发到内网服务器
明确了具体的实现方案后,我们需要先详细的研究一下OpenResty和Lua
http://openresty.org/cn/
https://www.tutorialspoint.com/lua/
大致了解OpenResty是什么,能做什么,同时能简单写一些Lua脚本。
然后,我们重点看OpenResty提供的样例:
Dynamic Routing Based On Redis
通过这个样例,我们就可以模仿着写一个我们自己的配置和脚本,实现上面的动态路由的需求。
Come On。
一、解析URL中的Action
首先,要解析并拆分URL字符串,各种百度和Google,需要写一段Lua代码,实现字符串按"/"拆分

其实就是定义了一个split_path函数。
然后我们将上面的Split.lua文件,配置到Nginx的配置文件中
/usr/local/openresty/nginx/conf/nginx.conf

注:split.lua文件我们放在了
/usr/local/openresty/nginx/lua
编辑/usr/local/openresty/nginx/conf/nginx.conf文件
http {
include mime.types;
default_type application/octet-stream; sendfile on;
#tcp_nopush on;
#keepalive_timeout ;
keepalive_timeout ;
#gzip on;
init_worker_by_lua_file /usr/local/openresty/nginx/lua/split.lua;
server {
listen ;
location = /redis {
internal;
set_unescape_uri $key $arg_key;
redis2_query get $key;
redis2_pass RedisServer:;
}
location / {
set $target '';
access_by_lua '
local parameters = split_path(ngx.var.uri)
local action = parameters[]
location中的access_by_lua '这一段负责执行Lua脚本和方法
local action = parameters[1]
这样,我们便解析到了Action,注:Lua中数组的下标从1开始
二.访问Redis,Key=Action Value=内网服务器地址
继续编辑Nginx配置文件
location / {
set $target '';
access_by_lua '
local parameters = split_path(ngx.var.uri)
local action = parameters[]
if(#parameters == ) then
ngx.exit(ngx.HTTP_FORBIDDEN)
end
local key = action
local res = ngx.location.capture(
"/redis", { args = { key = key } }
)if res.status ~= then
ngx.log(ngx.ERR, "redis server returned bad status: ",
res.status)
ngx.exit(res.status)
end
if not res.body then
ngx.log(ngx.ERR, "redis returned empty body")
ngx.exit()
end
local parser = require "redis.parser"
local server, typ = parser.parse_reply(res.body)
if typ ~= parser.BULK_REPLY or not server then
ngx.log(ngx.ERR, "bad redis response: ", res.body)
ngx.exit()
end
if server == "" then
server = "default.com"
end
三.Http请求转发到内网服务器
继续编辑Nginx.Conf文件
init_worker_by_lua_file /usr/local/openresty/nginx/lua/split.lua;
server {
listen ;
location = /redis {
internal;
set_unescape_uri $key $arg_key;
redis2_query get $key;
redis2_pass RedisServer:;
} location / {
set $target '';
access_by_lua '
local parameters = split_path(ngx.var.uri)
local action = parameters[]
if(#parameters == ) then
ngx.exit(ngx.HTTP_FORBIDDEN)
end local key = action
local res = ngx.location.capture(
"/redis", { args = { key = key } }
) if res.status ~= then
ngx.log(ngx.ERR, "redis server returned bad status: ",
res.status)
ngx.exit(res.status)
end if not res.body then
ngx.log(ngx.ERR, "redis returned empty body")
ngx.exit()
end local parser = require "redis.parser"
local server, typ = parser.parse_reply(res.body)
if typ ~= parser.BULK_REPLY or not server then
ngx.log(ngx.ERR, "bad redis response: ", res.body)
ngx.exit()
end if server == "" then
server = "default.com"
end
server = server .. "/api/" .. action
if ngx.var.QUERY_STRING ~= nil and ngx.var.QUERY_STRING ~= "" then
server = server .."&"..ngx.var.QUERY_STRING
end ngx.var.target = server
';
resolver 8.8.8.8;
proxy_pass http://$target;
}
}
至此,我们完成了Nginx的配置文件。
启动Nginx测试:
sudo /usr/local/openresty/nginx/sbin/nginx -c /usr/local/openresty/nginx/conf/Nginx.conf
PostMan发起一次请求:
查看Nginx日志

以上就是使用Nginx+lua+redis实现动态路由。分享给大家
周国庆
2017/10/01
Nginx技术研究系列2-基于Redis实现动态路由的更多相关文章
- Ngnix技术研究系列2-基于Redis实现动态路由
上篇博文我们写了个引子: Ngnix技术研究系列1-通过应用场景看Nginx的反向代理 发现了新大陆,OpenResty OpenResty 是一个基于 Nginx 与 Lua 的高性能 Web 平台 ...
- Nginx技术研究系列5-动态路由升级版
前几篇文章我们介绍了Nginx的配置.OpenResty安装配置.基于Redis的动态路由以及Nginx的监控. Nginx-OpenResty安装配置 Nginx配置详解 Nginx技术研究系列1- ...
- Nginx技术研究系列3-OpenResty安装配置
上两篇中介绍了: Ngnix技术研究系列1-通过应用场景看Nginx的反向代理 Ngnix技术研究系列2-基于Redis实现动态路由 发现,应该加一篇OpenResty的安装部署说明,方便大家按图索骥 ...
- Nginx技术研究系列6-配置详解
前两篇文章介绍了Nginx反向代理和动态路由: Ngnix技术研究系列1-通过应用场景看Nginx的反向代理 Ngnix技术研究系列2-基于Redis实现动态路由 随着研究的深入,很重要的一点就是了解 ...
- Nginx技术研究系列1-通过应用场景看Nginx的反向代理
随着我们业务规模的不断增长,整个系统规模由两年前的几十台服务器,井喷到现在2个数据中心,接近400台服务器,上百个WebApi站点,上百个域名. 这么多的WebApi站点这么多的域名,管理和维护成本很 ...
- Nginx技术研究系列7-Azure环境中Nginx高可用性和部署架构设计
前几篇文章介绍了Nginx的应用.动态路由.配置.在实际生产环境部署时,我们需要同时考虑Nginx的高可用性和部署架构. Nginx自身不支持集群以保证自身的高可用性,商业版本的Nginx+推荐: T ...
- Nginx技术研究系列4-Nginx监控-Nginx+Telegraf+Influxb+Grafana
搭建了Nginx集群后,需要继续深入研究的就是日常Nginx监控. Nginx如何监控?相信百度就可以找到:nginx-status 通过Nginx-status,实时获取到Nginx监控数据后,如何 ...
- Azure IoT 技术研究系列3-设备到云、云到设备通信
上篇博文中我们将模拟设备注册到Azure IoT Hub中:我们得到了设备的唯一标识. Azure IoT 技术研究系列2-设备注册到Azure IoT Hub 本文中我们继续深入研究,设备到云.云到 ...
- Azure IoT 技术研究系列5-Azure IoT Hub与Event Hub比较
上篇博文中,我们介绍了Azure IoT Hub的使用配额和缩放级别: Azure IoT 技术研究系列4-Azure IoT Hub的配额及缩放级别 本文中,我们比较一下Azure IoT Hub和 ...
随机推荐
- QT4.5.3移植到hi3536
QT版本:qt-embedded-linux-opensource-src-4.5.31.添加交叉编译(1)copy qt-embedded-linux-opensource-src-4.5.3/mk ...
- kvc原理
KVC底层实现原理 第一步:寻找该属性有没有setsetter方法?有,就直接赋值 第二步:寻找有没有该属性带下划线的成员属性?有,就直接赋值 第三步:寻找有没有该属性的成员属性?有,就直接赋值 1. ...
- (4.23)sql server区服大小写的检索
是的,SQL Server数据库可以区分大小写.区分大小写意味着SQL Server将为CASE,Case,CaSe等返回不同的结果集,并将所提到的字符串视为3个不同的字符串.区分大小写的数据库具有区 ...
- ntpdata 同步时间
ntpdate用来同步时间 [root@localhost ~]# yum install -y ntp [root@localhost ~]# ntpdate time.windows.com # ...
- 前端 HTML body标签相关内容 常用标签 盒子标签 div
盒子标签 div <div>可定义文档的分区 division的缩写 译:区 <div> 标签可以把文档分割为独立的.将他们进行分区 div在浏览器中,默认是不会增加任何的效果 ...
- SQL SERVER 2016研究一
一.安装SQL Server 2016 安装检查提示异常: 安装补丁: 根据系统判断补丁安装顺序,按顺序安装 Windows server 2012 R2 安装SQL补丁如下以及JDK: 安装完成 二 ...
- AlertWindowManager 弹出提示窗口使用帮助(下)
//显示消息提示框 //function TdxAlertWindowManager.Show(const ACaption, AText: string; AImageIndex: TcxImage ...
- 用PowerDesigner建立概念模型的问题:不能创建相同字段名的关键字段
依次点击Tools--->Model Options->Model Settings,在Model Settings中有Data Item组框,取消里面的Unique Code,勾选All ...
- php使用solr全文搜索引擎
前言 本来以为网上已经有了类似博文,不想重复,可是一圈搜下来,都是一些内容不甚明了的文章,或者solr版本太过老,参考价值不高,更有甚者,直接拷贝的别人的内容.一篇博客,各大平台都能看到,也不见转载链 ...
- 下载apk安装包后,调用安装器自动安装apk(适配7.0)
在更新操作时,下载新apk之后,往往需要自动安装新apk,用以下代码即可安装下载在本地的apk文件(apkFile) Intent intent = new Intent(); intent.setA ...