Ngnix技术研究系列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
Ngnix技术研究系列2-基于Redis实现动态路由的更多相关文章
- Nginx技术研究系列2-基于Redis实现动态路由
上篇博文我们写了个引子: Ngnix技术研究系列1-通过应用场景看Nginx的反向代理 发现了新大陆,OpenResty OpenResty 是一个基于 Nginx 与 Lua 的高性能 Web 平台 ...
- Ngnix技术研究系列1-通过应用场景看Nginx的反向代理
随着我们业务规模的不断增长,整个系统规模由两年前的几十台服务器,井喷到现在2个数据中心,接近400台服务器,上百个WebApi站点,上百个域名. 这么多的WebApi站点这么多的域名,管理和维护成本很 ...
- Nginx技术研究系列3-OpenResty安装配置
上两篇中介绍了: Ngnix技术研究系列1-通过应用场景看Nginx的反向代理 Ngnix技术研究系列2-基于Redis实现动态路由 发现,应该加一篇OpenResty的安装部署说明,方便大家按图索骥 ...
- Nginx技术研究系列6-配置详解
前两篇文章介绍了Nginx反向代理和动态路由: Ngnix技术研究系列1-通过应用场景看Nginx的反向代理 Ngnix技术研究系列2-基于Redis实现动态路由 随着研究的深入,很重要的一点就是了解 ...
- Nginx技术研究系列5-动态路由升级版
前几篇文章我们介绍了Nginx的配置.OpenResty安装配置.基于Redis的动态路由以及Nginx的监控. Nginx-OpenResty安装配置 Nginx配置详解 Nginx技术研究系列1- ...
- 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和 ...
- ML.NET技术研究系列-2聚类算法KMeans
上一篇博文我们介绍了ML.NET 的入门: ML.NET技术研究系列1-入门篇 本文我们继续,研究分享一下聚类算法k-means. 一.k-means算法简介 k-means算法是一种聚类算法,所谓聚 ...
- Azure IoT 技术研究系列3
上篇博文中我们将模拟设备注册到Azure IoT Hub中:我们得到了设备的唯一标识. Azure IoT 技术研究系列2-设备注册到Azure IoT Hub 本文中我们继续深入研究,设备到云.云到 ...
随机推荐
- 深入剖析C++多态、VPTR指针、虚函数表
在讲多态之前,我们先来说说关于多态的一个基石------类型兼容性原则. 一.背景知识 1.类型兼容性原则 类型兼容规则是指在需要基类对象的任何地方,都可以使用公有派生类的对象来替代.通过公有继承,派 ...
- spring boot / cloud (八) 使用RestTemplate来构建远程调用服务
spring boot / cloud (八) 使用RestTemplate来构建远程调用服务 前言 上周因家里突发急事,请假一周,故博客没有正常更新 RestTemplate介绍: RestTemp ...
- RPC框架实现思路浅析
第一部分,设计分析 远程调用要解决的主要问题: 1,序列化 : 如何将对象转化为二进制数据进行传输,如何将二进制数据转化对象 2,数据的传输(协议,第三方框架) 3,服务的注册/发现,单点故障,分布式 ...
- css:box-sizing什么作用
css3 box-sizing属性 box-sizing属性可以为三个值之一:content-box(default),border-box,padding-box. content-box,bord ...
- ajax请求后台,有时收不到返回值的解决办法
昨天下午做项目遇到一个问题,贴出来方便以后翻阅,也给大家个参考. 问题: 具体做的是个文件导入的功能,导入的功能是成功了,但是界面一直得不到返回值,排查了一下午,调试的时候是可以有返回的,但是关掉浏览 ...
- 使用DOM解析XML文件,、读取xml文件、保存xml、增加节点、修改节点属性、删除节点
使用的xml文件 <?xml version="1.0" encoding="GB2312" ?> <PhoneInfo> <Br ...
- CyclicBarrier和CountDownLatch介绍
详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp70 CyclicBarrier介绍 (一) 一个同步辅助类,它允许一组线 ...
- NHibernate教程(19) —— 一级缓存
本节内容 引入 NHibernate一级缓存介绍 NHibernate一级缓存管理 结语 引入 大家看看上一篇了吗?对象状态.这很容易延伸到NHibernate的缓存.在项目中我们灵活的使用NHibe ...
- NHibernate教程(11)--多对多关联查询
本节内容 多对多关系引入 多对多映射关系 多对多关联查询 1.原生SQL关联查询 2.HQL关联查询 3.Criteria API关联查询 结语 多对多关系引入 让我们再次回顾在第二篇中建立的数据模型 ...
- 五,ESP8266 TCP服务器多连接
一些时间去准备朋友的元器件了... 接着写,,争取今天写完所有的文章,,因为答应了朋友下周5之前要做好朋友的东西 对于TCP大家在玩AT指令的时候有没有发现客户端最多连接5个,,,再连接就不行了?? ...