OpenResty 是一个经过 Lua 扩展 Nginx 实现的可伸缩的 Web 平台,内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建可以处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。html
安装:前端
1. 下载安装包 https://openresty.org/cn/download.htmljava
2. 安装软件包 tar -zxvf openresty-1.13.6.2.tar.gz。cd openrestry-1.13.6.2。./configure [默认会安装在/usr/local/openresty 目录] --prefix= 指定路径。make && make installmysql
3. 可能存在的错误,第三方依赖库没有安装的状况下会报错 yum install readline-devel / pcre-devel /openssl-develnginx
安装过程和 Nginx 是同样的,由于他是基于 Nginx 作的扩展。开始第一个程序,HelloWorld cd /usr/local/openresty/nginx/conf 编辑 nginx 配置文件 nginx.conf redis
location / { default_type text/html; content_by_lua_block { ngx.say("helloworld"); } }
在 sbin 目录下执行.nginx 命令就能够运行,访问能够看到 helloworld。算法
创建工做空间:sql
为了避免影响默认的安装目录,咱们能够建立一个独立的空间来练习,先到在安装目录下建立 demo 目录,安装目录为/usr/local/openresty .mkdir demo。而后在 demo 目录下建立三个子目录,一个是 logs 、一个是 conf,一个是 lua。数据库
进接下去演示一个实现 API网关功能的简单demo,而后提供一个算法去计算传入参数a,b的和。入conf 建立配置文件 vim nginx.conf :vim
worker_processes 1; error_log logs/error.log; events { worker_connections 1024; } http { lua_package_path '$prefix/lua/?.lua'; //这里的¥prefix在启动的时候指定 lua_code_cache off; // lua脚本不须要从新加载 server { listen 80; // 正则匹配访问路径 location ~ ^/api/([-_a-zA-Z0-9]+) { // 请求过滤一下 access_by_lua_file lua/check.lua; content_by_lua_file lua/$1.lua; } } }
当来到的请求符合 ^/api/([-_a-zA-Z0-9/] 时 会在NGX_HTTP_CONTENT_PHASE HTTP请求内容阶段 交给 lua/$1.lua来处理。好比:
/api/addition 交给 lua/addition.lua 处理。
/api/lua/substraction 交给 lua/substraction .lua 处理。
接下去建立 三个 lua 脚本:params.lua:
local _M ={} // 定义一个模块 //定义一个方法 //该方法用于判断参数是否为数字 function _M.is_number(...) local args={...} local num; for i,v in ipairs(arg) do num=tonumber(v); if nil ==num then return false; end end return true; end //将该模块返回出去 return _M;
写一个用于起到网关过滤的检查脚本check.lua:
//导入模块<br>local param=require("params");<br>//获取uri的参数 local args=ngx.req.get_uri_args();<br>//判断a,b是否为空且是否为数字 if not args.a or not args.b or not param.is_number(args.a,args.b) then ngx.exit(ngx.HTTP_BAD_REQUEST); return; end
算法脚本 add.lua:
local args =ngx.req.get_uri_args();
ngx.say(args.a+args.b);
进入nginx的sbin目录执行:./nginx -p /usr/local/openresty/demo 【-p 主要是指明 nginx 启动时的配置目录】,此时会提示一个警告信息,无需理会,有强迫症把对应配置关了就还了:nginx: [alert] lua_code_cache is off; this will hurt performance in /usr/local/openresty/demo/conf/nginx.conf:12。经过访问http://192.168.254.137/api/add?a=1&b=3 能显示最后的值:
库文件使用:经过上面的案例,咱们基本上对 openresty 有了一个更深的认识,其中咱们用到了自定义的 lua 模块。实际上 openresty 提供了很丰富的模块。让咱们在实现某些场景的时候更加方便。能够在 /openresty/lualib 目录下看到;好比在 resty 目录下能够看到 redis.lua、mysql.lua 这样的操做 redis 和操做数据库的模块。更多的库能够去百度,或者查找相关书籍。
从一个房间到另外一个房间,必须必需要通过一扇门,一样,从一个网络向另外一个网络发送信息,必须通过一道“关口”,这道关口就是网关。顾名思义,网关(Gateway)就是一个网络链接到另外一个网络的“关口”。那什么是 api 网关呢?
在微服务流行起来以前,api 网关就一直存在,最主要的应用场景就是开放平台,也就是 open api; 这种场景你们接触的必定比较多,好比阿里的开放平台;当微服务流行起来之后,api 网关就成了上层应用集成的标配组件.
为何须要网关?
对微服务组件地址进行统一抽象,API 网关意味着你要把 API 网关放到你的微服务的最前端,而且要让 API 网关变成由应用所发起的每一个请求的入口。这样就能够简化客户端实现和微服务应用程序之间的沟通方式.
当服务愈来愈多之后,咱们须要考虑一个问题,就是对某些服务进行安全校验以及用户身份校验。甚至包括对流量进行控制。 咱们会对须要作流控、须要作身份认证的服务单独提供认证功能,可是服务愈来愈多之后,会发现不少组件的校验是重复的。这些东西很明显不是每一个微服务组件须要去关心的事情。微服务组件只须要负责接收请求以及返回响应便可。能够把身份认证、流控都放在 API 网关层进行控制。
在单一架构中,随着代码量和业务量不断扩大,版本迭代会逐步变成一个很困难的事情,哪怕是一点小的修改,都必需要对整个应用从新部署。 可是在微服务中,各个模块是是一个独立运行的组件,版本迭代会很方便,影响面很小。同时,为服务化的组件节点,对于咱们去实现灰度发布(金丝雀发布:将一部分流量引导到新的版本)来讲,也会变的很简单;因此经过 API 网关,能够对指定调用的微服务版本,经过版原本隔离。以下图所示
OpenResty 实现 API 网关限流及登陆受权
OpenResty 为何能作网关?
前面咱们了解到了网关的做用,经过网关,能够对 api 访问的前置操做进行统一的管理,好比鉴权、限流、负载均衡、日志收集、请求分片等。因此 API 网关的核心是全部客户端对接后端服务以前,都须要统一接入网关,经过网关层将全部非业务功能进行处理。OpenResty 为何能实现网关呢? OpenResty 有一个很是重要的因素是,对于每个请求,Openresty 会把请求分为不一样阶段,从而可让第三方模块经过挂载行为来实现不一样阶段的自定义行为。而这样的机制可以让咱们很是方便的设计 api 网关。
Nginx 自己在处理一个用户请求时,会按照不一样的阶段进行处理,总共会分为 11个阶段。而 openresty 的执行指令,就是在这 11 个步骤中挂载 lua 执行脚本实现扩展,咱们分别看看每一个指令的做用
init_by_lua : 当 Nginx master 进程加载 nginx 配置文件时会运行这段 lua 脚本,通常用来注册全局变量或者预加载 lua 模块。
init_woker_by_lua: 每一个 Nginx worker 进程启动时会执行的 lua 脚本,能够用来作健康检查。
set_by_lua:设置一个变量。
rewrite_by_lua:在 rewrite 阶段执行,为每一个请求执行指定的 lua 脚本。
access_by_lua:为每一个请求在访问阶段调用 lua 脚本。
content_by_lua:前面演示过,经过 lua 脚本生成 content 输出给 http 响应。
balancer_by_lua:实现动态负载均衡,若是不是走 contentbylua,则走 proxy_pass,再经过 upstream 进行转发。
header_filter_by_lua: 经过 lua 来设置 headers 或者 cookie。
body_filter_by_lua:对响应数据进行过滤。
log_by_lua : 在 log 阶段执行的脚本,通常用来作数据统计,将请求数据传输到后端进行分析。
灰度发布的实现:
1.跟前面同样建立一个新的工做空间 mkdir gray。而后在 demo 目录下建立三个子目录,一个是 logs 、一个是 conf,一个是 lua。
2.编写 Nginx 的配置文件 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 {//tomcat地址 server 192.168.254.137:8080; } // 预生产环境 upstream pre {//tomcat地址 server 192.168.254.139:8080; } server { listen 80; server_name localhost; //当访问该路径就会进入lua脚本 location / { content_by_lua_file lua/gray.lua; } // 定义变量在lua中会使用 location @prod { proxy_pass http://prod; } location @pre { proxy_pass http://pre; } } }
3.编写 gray.lua 文件
local redis=require "resty.redis"; local red=redis:new(); red:set_timeout(1000); local ok,err=red:connect("192.168.254.138",6379); if not ok then ngx.say("failed to connect redis",err); return; end ok, err = red:auth("wuzhenzhao"); local_ip=ngx.var.remote_addr; local ip_lists=red:get("gray"); if string.find(ip_lists,local_ip) == nil then ngx.exec("@prod"); else ngx.exec("@pre"); end local ok,err=red:close();
4.
1.进入sbin目录 执行命令启动 nginx: ./nginx -p /usr/local/openresty/gray
2. 启动 redis,并设置 set gray 192.168.254.1,因为我这边是访问虚拟机,因此我本地ip去访问就是这个。
3. 经过浏览器运行: http://192.168.254.137/查看运行结果
修改 redis gray 的值, 到 redis 中 set gray 192.168.254.2. 再次运行结果,便可看到访问结果已经发生了变化.