2.2.2 OpenResty入门
OpenResty 将 Lua 语言解释器嵌入到 NGINX 中,从而赋予了NGINX更多拓展的可能。另外,OpenResty 还自带了一些常用的模块,如用于数据库连接的 lua-resty-mysql,lua-resty-redis,lua-resty-memcached等。
1.配置指令拓展
OpenResty 为 NGINX 配置拓展了若干指令,这些指令是使用 OpenResty 进行网关开发的关键,熟悉它们十分必要,常用的指令如下所示。
init_by_lua*
init_by_lua* 包含 init_by_lua,init_by_lua_block,init_by_lua_file 三个指令,这三个指令的作用是一样的,但是用法不同。
init_by_lua和init_by_lua_block直接在配置文件中编写 Lua 代码,init_by_lua_file 配置Lua代码文件的路径。
OpenResty 的指令往往都包含 *_by_lua,*_by_lua_block,*_by_lua_file三种形式,使用 *_by_lua_file 形式的指令可以更好地实现配置和代码分离,以下我们都以 *_lua_file 为例进行说明。
语法:init_by_lua_file
上下文:http
指令执行阶段:加载配置时
该指令指定NGINX加载配置时需要执行的Lua代码,通常这个阶段加载常用Lua模块。
// nginx.conf
http {
init_by_lua_file '/path/to/init.lua';
}
// /path/to/init.lua
-- 加载 cjson 模块
-- cjson 模块用于JSON处理
require "cjson"一些开发者习惯在 init_by_lua* 阶段定义全局变量,比如 Orange(一个基于OpenResty的网关软件) 和 APACHE APISIX 是这样使用的:
但是,这种做法是不推荐的,在 init_by_lua* 阶段定义全局变量,其作用无非是在后续使用中,不必 require 而可以直接使用诸如 context 和 apisix 之类的变量。但是这种做法会造成全局命名空间的污染,也可能会造成性能下降。
事实上,在 ngx_lua 上下文中,均需避免使用 Lua 全局变量,官方给出的解释是这样的:
全局变量的滥用会对并发请求产生不利影响;
全局变量需要在全局环境中进行 Lua 表查找,开销昂贵;
全局变量可能造成调试困难;
init_worker_by_lua*
语法:init_worker_by_lua_file
上下文:http
指令执行阶段:woker 进程启动时
init_by_lua* 指令是在 NGINX 的主进程启动阶段执行的, 而 init_worker_by_lua* 指令在 worker 进程启动阶段执行。
NGINX 的进程有两类,主进程(master进程)和worker进程,其中主进程只能有一个而worker进程可以有多个。主进程不处理请求,它负责读取和评估配置文件,维护worker进程,而 worker 进程才是真正用于处理请求的。
init_worker_by_lua* 阶段通常用来创建定时器(通过 ngx.timer.at 或 ngx.timer.every),用于健康检查或执行定时任务。
set_by_lua*
语法:set_by_lua_file $res [$arg1 $arg2 ...]
上下文:server, server if, location, location if
指令执行阶段:rewrite 阶段,用于定义NGINX变量
set_by_lua* 用来定义NGINX变量,NGINX 原生指令 set 可以用来设置变量,如 set $year 2022;,set_by_lua* 进一步拓展了 set 指令,使得变量的值可以通过运行一段Lua代码得出。
rewrite_by_lua* 语法:rewrite_by_lua_file
上下文:http, server, location, location if
指令执行阶段:rewrite 阶段结束时
rewrite_by_lua* 是 rewrite 阶段的处理程序,默认在 rewrite 请求处理阶段结束时运行,通常用于检查,改写 URI,实现重定向等。示例如下。
access_by_lua*
语法:access_by_lua_file
上下文:http, server, location, location if
指令执行阶段:access 阶段结束时
access_by_lua* 通常用来进行权限检查,安全校验等。
content_by_lua*
语法:content_by_lua_block
上下文:location, location if
指令执行阶段:content 阶段
content_by_lua* 为每个请求执行相应的 Lua 代码,当我们把 OpenResty 作为Web服务器时,业务的核心代码就在 content_by_lua* 阶段执行。
balancer_by_lua*
语法:balancer_by_lua_file
上下文:upstream
指令执行阶段:content 阶段
balancer_by_lua* 指令是实现动态负载均衡关键。
原生的NGINX使用upstream指令来配置源服务器,当源服务器有更新时,我们必须更新upstream的配置,同时也要reload NGINX。而 balancer_by_lua* 指令实现了源服务器的动态配置,更新源服务器时再也不需要更新NGINX配置文件了,这对于我们开发API网关十分重要。
使用lua-resty-core库中的ngx.balancer模块,我们可以轻松实现动态负载均衡,同时ngx.balancer模块还提供了upstream不具有的功能。利用balancer_by_lua*指令和ngx.balancer模块,我们可以实现灵活的负载均衡策略。
ngx.balancer模块提供了如下常用的静态方法。
set_current_peer
设置当前使用的源服务器
set_more_tries
设置源服务器连接失败后的重试次数
get_last_failure
获取上次连接失败的详细信息
set_timeouts
设置源服务器的连接和读写超时时间,单位是秒
header_filter_by_lua*
语法:header_filter_by_lua_file
上下文:http, server, location, location if
指令执行阶段:output-header-filter
header_filter_by_lua* 指令创建改HTTP响应标头的过滤器。比如,利用header_filter_by_lua*指令可以设置HTTP响应标头。
body_filter_by_lua*
语法:body_filter_by_lua_file
上下文:http, server, location, location if
指令执行阶段:output-body-filter
body_filter_by_lua* 指令用于创建HTTP响应体的过滤器。比如,利用 body_filter_by_lua*可以修改响应体的内容。
log_by_lua*
语法:log_by_lua_file
上下文:http, server, location, location if
指令执行阶段:log
log_by_lua*指令用于日志收集,它不会代替NGINX的access日志(access.log)。
以上是OpenResty的常用指令,这些指令及其执行的阶段的示意图如下。理解了这张图,也就基本理解了OpenResty的工作过程。
todo 示例图

todo
Last updated