Dynamic Routing Based On Redis

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 0;
keepalive_timeout 65; #gzip on;
init_worker_by_lua_file /usr/local/openresty/nginx/lua/split.lua;
server {
listen 80;
location = /redis {
internal;
set_unescape_uri $key $arg_key;
redis2_query get $key;
redis2_pass RedisServer:6379;
} location / {
set $target '';
access_by_lua '
local parameters = split_path(ngx.var.uri)
local action = parameters[1]

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[1]
if(#parameters == 0) then
ngx.exit(ngx.HTTP_FORBIDDEN)
end

local key = action
local res = ngx.location.capture(
"/redis", { args = { key = key } }
)if res.status ~= 200 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(500)
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(500)
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 80;
location = /redis {
internal;
set_unescape_uri $key $arg_key;
redis2_query get $key;
redis2_pass RedisServer:6379;
} location / {
set $target '';
access_by_lua '
local parameters = split_path(ngx.var.uri)
local action = parameters[1]
if(#parameters == 0) then
ngx.exit(ngx.HTTP_FORBIDDEN)
end local key = action
local res = ngx.location.capture(
"/redis", { args = { key = key } }
) if res.status ~= 200 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(500)
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(500)
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实现动态路由。分享给大家

Dynamic Routing Based On Redis的更多相关文章

  1. Hinton's paper Dynamic Routing Between Capsules 的 Tensorflow , Keras ,Pytorch实现

    Tensorflow 实现 A Tensorflow implementation of CapsNet(Capsules Net) in Hinton's paper Dynamic Routing ...

  2. 【论文笔记】Dynamic Routing Between Capsules

    Dynamic Routing Between Capsules 2018-09-16 20:18:30 Paper:https://arxiv.org/pdf/1710.09829.pdf%20 P ...

  3. Dynamic Routing Between Capsules

    目录 概 主要内容 损失函数 代码 Sabour S, Frosst N, Hinton G E, et al. Dynamic Routing Between Capsules[C]. neural ...

  4. Redis Installation、Configuration、Program Based On Redis Learning

    目录 . Redis 简介 . Redis安装配置 . 编程使用Redis . 使用Lua脚本 1. Redis 简介 0x1: Redis是什么 Redis是一款Nosql类型的基于key-valu ...

  5. dynamic routing between captual

    对于人脑 决策树形式 对于CNN 层级与层级间的传递 人在识别物体的时候会进行坐标框架的设置 CNN无法识别,只能通过大量训练 胶囊 :一个神经元集合,有一个活动的向量,来表示物体的各类信息,向量的长 ...

  6. Paper | SkipNet: Learning Dynamic Routing in Convolutional Networks

    目录 1. 概括 2. 相关工作 3. 方法细节 门限模块的结构 训练方法 4. 总结 作者对residual network进行了改进:加入了gating network,基于上一层的激活值,得到一 ...

  7. Ngnix技术研究系列2-基于Redis实现动态路由

    上篇博文我们写了个引子: Ngnix技术研究系列1-通过应用场景看Nginx的反向代理 发现了新大陆,OpenResty OpenResty 是一个基于 Nginx 与 Lua 的高性能 Web 平台 ...

  8. Nginx技术研究系列2-基于Redis实现动态路由

    上篇博文我们写了个引子: Ngnix技术研究系列1-通过应用场景看Nginx的反向代理 发现了新大陆,OpenResty OpenResty 是一个基于 Nginx 与 Lua 的高性能 Web 平台 ...

  9. nginx HttpLuaModule

    http://wiki.nginx.org/HttpLuaModule#Directives Name ngx_lua - Embed the power of Lua into Nginx This ...

随机推荐

  1. jeDeta 日历控件的那些坑

    经过亲自测试 jeDeta 发现 jeDeta 还是有坑的: 1.参数 options 里面的 format 有很多种格式 API 里面写的是 format: 'YYYY-MM-DD hh:mm:ss ...

  2. pandas的to_csv()使用方法

    1.首先查询当前的工作路径: import osos.getcwd() #获取当前工作路径2.to_csv()是DataFrame类的方法,read_csv()是pandas的方法dt.to_csv( ...

  3. 怎么配置 Oracle 侦听器来使用SQL操作ST_Geometry

    关于这个内容,其实从ArcSDE9.2推出ST_Geometry就让用户感到很有吸引力,而且特别是在ArcSDE9.3之后,用户使用SQL操作ST_geometry越来越多,但是在配置Oracle监听 ...

  4. swift函数的调用约定

    The convention of the function, indicated by the attribute. This is similar to the language-level @c ...

  5. Windows下面安装并运行composer的步骤

    在composer官网下载得到:https://getcomposer.org/download/ Composer-Setup.exe 安装时注意:安装过程中,会提示你选择php安装目录.一直到ph ...

  6. 你不得不知道的 .NET CORE —— .NET Framework, .NET Core 和 .NET Standard 的区别

    .NET Framework 和 .NET Core 是平台应用框架,而 .NET Standard 是 .NET 底层库.因此只要用 .NET Standard 工程来写的代码可以直接在上层的平台应 ...

  7. spring-batch批处理框架

    转自 http://www.cnblogs.com/gulvzhe/archive/2011/10/21/2220260.html 这个框架没有实际操作,只是从同事处学习到,先转个好文章,以后有机会再 ...

  8. 讲解Linux数据库安装

    学习了linux这门课之后,就开始实践过程了,这样比较记得牢固,学以致用. 有了基本的命令,就可以试着安装数据库了. 企业环境 需要安装VMWare ESXi虚拟机,然后再在里面新建虚拟机. 镜像vm ...

  9. PAT A1142 Maximal Clique (25 分)——图

    A clique is a subset of vertices of an undirected graph such that every two distinct vertices in the ...

  10. POJ1251(Kruskal水题)

    https://vjudge.net/problem/POJ-1251 The Head Elder of the tropical island of Lagrishan has a problem ...