openresty实现网关功能
什么是网关从一个房间到另一个房间,必须必须要经过一扇门,同样,从一个网络向另一个网络发送信息,必须经过一道“关口”,这道关口就是网关。顾名思义,网关(Gateway)就是一个网络连接到另一个网络的“关口”。那什么是 api 网关呢?在微服务流行起来之前,api 网关就一直存在,最主要的应用场景就是开放平台,也就是 open api; 这种场景大家接触的一定比较多,比如阿里的开放平台。微服务流...
什么是网关
从一个房间到另一个房间,必须必须要经过一扇门,同样,从一个网络向另一个网络发送信息,必须经过一道“关口”,这道关口就是网关。顾名思义,网关(Gateway)就是一个网络连接到另一个网络的“关口”。
那什么是 api 网关呢?
在微服务流行起来之前,api 网关就一直存在,最主要的应用场景就是开放平台,也就是 open api; 这种场景大家接触的一定比较多,比如阿里的开放平台。微服务流行起来后,api网关就成了上层应用集成的标配组件。
为什么需要网关?
1、把 API 网关放到微服务的最前端,让 API 网关变成所有应用请求的入口。这样就可以简化客户端实现和微服务应用程序之间的沟通方式。
网关功能示意图:
2、当服务越来越多以后,我们需要考虑一个问题,就是对某些服务进行安全校验以及用户身份校验。甚至包括对流量进行控制。 开始我们会再需要做流控、需要做身份认证的服务内单独提供认证功能,但是服务越来越多以后,会发现很多组件的校验是重复的。这些东西很明显不是每个微服务组件需要去关心的事情。微服务组件只需要负责接收请求以及返回响应即可。可以把身份认证、流控都放在 API 网关层进行控制。
OpenResty 为什么能做网关?
前面我们了解到了网关的作用,通过网关,可以对 api 访问的前置操作进行统一的管理,比如鉴权、限流、负载均衡、日志收集、请求分片等。所以 API 网关的核心是所有客户端对接后端服务之前,都需要统一接入网关,通过网关层将所有非业务功能进行处理。
OpenResty 为什么能实现网关呢? 有一个非常重要的因素是,对于每一个请求,Openresty 会把请求分为不同阶段,从而可以让第三方模块通过挂载行为来实现不同阶段的自定义行为。这种机制可以非常方便的设计api网关
Nginx 本身在处理一个用户请求时,会按照不同的阶段进行处理,总共会分为 11个阶段。而 openresty 的执行指令,就是在这 11 个步骤中挂载 lua 执行脚本实现扩展,我们分别看看每个指令的作用。
initbylua : 当 Nginx master 进程加载 nginx 配置文件时会运行这段 lua 脚本,一般用来注册全局变量或者预加载 lua 模块
initwokerby_lua: 每个 Nginx worker 进程启动时会执行的 lua 脚本,可以用来做健康检查
setbylua:设置一个变量
rewritebylua:在 rewrite 阶段执行,为每个请求执行指定的 lua 脚本
accessbylua:为每个请求在访问阶段调用 lua 脚本
contentbylua:前面演示过,通过 lua 脚本生成 content 输出给 http 响应
balancerbylua:实现动态负载均衡,如果不是走 contentbylua,则走 proxy_pass,再通过 upstream 进行转发
headerfilterby_lua: 通过 lua 来设置 headers 或者 cookie
bodyfilterby_lua:对响应数据进行过滤
logbylua : 在 log 阶段执行的脚本,一般用来做数据统计,将请求数据传输到后端进行分析
实现网关的灰度发布功能
灰度发布就是新版本刚上线时,可以只对某一部分用户开放,比如90%的客户还是只能访问到旧版本,另外10%的用户被添加到灰度名单中可以访问最新版本。
openresty 根目录下创建 gray目录 gray目录下创建 conf logs lua 三个目录 如下:
[root@zk03 openresty]# mkdir gray
[root@zk03 openresty]# cd gray
[root@zk03 gray]# mkdir conf logs lua
[root@zk03 gray]# ll
总用量 0
drwxr-xr-x. 2 root root 6 1月 30 05:05 conf
drwxr-xr-x. 2 root root 6 1月 30 05:05 logs
drwxr-xr-x. 2 root root 6 1月 30 05:05 lua
在gray/conf 下新增nginx.conf 文件如下:
[root@zk03 gray]# vi conf/nginx.conf
worker_processes 1;
error_log logs/error.log;
events{
worker_connections 1024;
}
http{
lua_package_path "$prefix/lualib/?.lua;;";
lua_package_cpath "$prefix/lualib/?.so;;";
upstream prod {
server zk03:8080;
}
upstream pre {
server zk03:8081;
}
server {
listen 80;
server_name localhost;
location /api {
content_by_lua_file lua/gray.lua;
}
location @prod {
proxy_pass http://prod;
}
location @pre {
proxy_pass http://pre;
}
}
server {
listen 8080;
location / {
content_by_lua_block {
ngx.say("I'm prod env");
}
}
}
server {
listen 8081;
location / {
content_by_lua_block {
ngx.say("I'm pre env");
}
}
}
}
在gray/lua 目录下新增 gray.lua文件如下 实现逻辑:在名单中的ip 访问 pre环境 否则访问prod环境:
[root@zk03 gray]# vi lua/gray.lua
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.say("failed to connect redis",err);
return;
end
local ip=ngx.var.remote_addr;
local ip_lists=red:get("gray");
if string.find(ip_lists,ip) == nil then
ngx.exec("@prod");
else
ngx.exec("@pre");
end
local ok,err=red:close();
启动openresty
[root@zk03 gray]# ../nginx/sbin/nginx -s reload -p /usr/local/openresty/gray
连接redis 将 gray 设置为 192.168.68.2 即将该ip加入到名单中 如下:
[root@zk03 src]# ./redis-cli
127.0.0.1:6379> set gray 192.168.68.2
OK
浏览器访问 zk03/api 返回 pre 环境
修改 redis 中的 gray 为 192.168.68.1 如下:
127.0.0.1:6379> set gray 192.168.68.1
OK
浏览器访问 zk03/api 返回 prod 环境 如下:
更多推荐
所有评论(0)