一  如何在nginx中嵌入lua代码

说明: 本文只是从'全局'的'科普角度'来认识,更多的是'概念',把握'框架脉络'即可

① openresty官方提供lua代码嵌入指令图

1) openresty最大的'优势'可以让'lua代码'来控制'处理请求'的流程

理解: 类比'web'容器

2) lua代码和nginx.conf的配置指令是'完全不同'的

核心: 怎样把'lua代码'嵌入到'nginx.conf的指令'中

介绍: 相应的openresty提供的'lua'关联指令

备注: 主要介绍'ngx_http_lua_module'提供的'指令'

后续: ngx_lua 模块提供的'Directive 指令'和API等

Secure Request : '黄色'的框'不是指令',表示请求来的时候进行判'是否是ssl'

padavan Nginx 在哪个目录_初始化

+++++++++++++ "要把握两点" +++++++++++++

1) lua在nginx的'哪些阶段'可以执行代码?     --> '四个阶段'

2) lua在nginx的每个阶段可以执行'哪些操作'?  --> '涉及指令'

解耦: nginx的'11个'执行阶段,'每个阶段'都有自己能够'执行的指令',并可以实现'不同的功能'

padavan Nginx 在哪个目录_初始化_02

②  在启动过程中嵌入lua代码

1、init_by_lua* '指令集'  --> 有三种格式的指令 '引号'、{}、'文件名' 

  1) 在init_by_lua*阶段,openresty是在'主协程'中通过'lua_pcall'直接'执行'lua代码

  2) init_by_lua 是在 'Lua VM 虚拟机 创建后'调用的

  运行时机: 每当 nginx '加载配置文件'时,都会创建一个'新的 Lua VM',在该'VM'中执行

  通俗: 压根就'没有到'server和location层面,是http的context,是'master进程'中跑的

  3) 在'start'、'reload'、'rsetart'都会执行

  备注: lua_shared_dict的内容'不会'在reload时'被清除'

  补充:HUP reload 只是更新'配置和 Lua 代码',同时也'不会丢弃共享内存中'已有的数据

  细节: 不管是'-s stop|reload'都会'读取'配置文件,都会创建一个'新的Lua VM',但是很快丢弃

  4) init_by_lua是Nginx配置加载的阶段,很多Nginx API for Lua命令是不支持的

  备注: 目前已知支持的'nginx API for Lua'的命令有ngx.log、'ngx.shared.DICT'、print

  5) 场景:

    [1]、'init初始化'一些'耗时模块',尤其是'对CPU消耗较多'的功能

    [2]、模块的'预'加载,做一些'全局'初始化配置  -->mysql、redis'初始化等'

    [3]、初始化'lua_shared_dict'共享内存的数据

nginx -s reload时,init_by_lua中的代码被执行了2次

init_worker_by_lua 中设置死循环reload后导致worker进程无法退出

lua_by_init 里面怎么判断是在nginx -t过程执行,还是真正启动的时候执行

padavan Nginx 在哪个目录_初始化_03

2、init_worker_by_lua* '指令集'

  [1]、特点:

    1) '每个'worker进程'创建时'都会执行lua代码

  [2]、应用场景:

    2) ngx.timer.every '配合'init_worker_by_lua*阶段可完成'定时任务'初始化 

    方式1: 如果'多worker',通过'if 0 == ngx.worker.id()'判断是保证只初始化一次

    常见: 定时'拉取'服务器配置

    2) resty.upstream.healthcheck   --> 动态进行后端'健康检查' --> 如'心跳'检查

在11个阶段的6个阶段嵌入lua代码

http的11个阶段嵌入的lua代码 'VS' 对比原生nginx 11阶段对应的指令

padavan Nginx 在哪个目录_padavan Nginx 在哪个目录_04

细节1: set_by_lua_*和rewrite_by_lua_*在同一个'阶段'有'先后'顺序的

原因: 

  1) set_by_lua* 是放到'官方'的ngx_http_rewrite_module模块中的'脚本指令'中

  2) rewrite_by_lua*作为'独立的模块'执行的

  3) 二者都归属于'rewrite阶段',但是'rewrite_by_lua*'是在'靠后'的位置

  4) rewrite_by_lua*'总是'在标准ngx_http_rewrite_module的 '后面'

案例1: rewrite break,进入'post_rewrite'阶段,rewrite_by_lua*就是'rewrite tail'工作

案例2: if 是rewrite_by_lua'之前' 执行的
细节2: content handler 只能'注册一个'

备注: proxy_paas 、echo'可以有多个echo'、'content_y_lua*'同时出现

特点: 服务启动'不报错',但是只有一个'生效',一般后者会'覆盖'前者

补充: 如果是'upstream'反向代理,一般是'proxy_paas',通过balance_by_lua*控制选择上游服务

content 阶段有两种: 

  1) 加入到静态'模块'     --> root、alias、index、static、gzip_static模块'依次执行'

  2) 反向代理,'独占'形式  --> content_by_lua*与其它类似'反向代理模块'都是'独占'的

padavan Nginx 在哪个目录_初始化_05

细节3:对于'content生成的响应'加工,'先处理header|后处理body'的filter加工

遗留:log_by_lua*有哪些'应用场景'?

 openresty的全局变量、模块变量、局部变量

1) openresty有哪些自身'特殊'的变量 :$prefix

2) openresty如何引入'nginx'的内置变量:ngx.var --> 使用"."或"[]",建议'local'本地存储

④   控制rewrite/access是否延迟执行lua代码

遗留:rewrite_by_lua_no_postpone只能控制'rewrite_by_lua',还是所有的'*'?

padavan Nginx 在哪个目录_openresty_06

过滤响应和负载均衡时嵌入lua代码

1) balance_by_lua*

说明: 为了深入学习'balance_by_lua*'先回顾下HTTP的'反向代理'流程

特点: 根据'负载均衡策略'选择上游的服务器

细节: 有一个回调方法叫'init_upstream','很多模块'在这里做,openresty也是'图中红色的地方'

引入: 'balance_by_lua*'去处理请求,openresty在这里通过'hook'钩子加入lua代码

高效: 可以自定义'负载均衡算法',通过'lua+redis'自定义gray'灰度策略'实现灰度发布

padavan Nginx 在哪个目录_初始化_07

细节: ngx_http_lua_module在'许多阶段'都有引入,在'filter'阶段也有引入

padavan Nginx 在哪个目录_openresty_08

padavan Nginx 在哪个目录_padavan Nginx 在哪个目录_09

⑥  在openssl处理ssl协议时嵌入lua代码

介入时机: 在openssl处理'SSL协议'时嵌入lua代码,专门用来'处理ssl握手'的

备注: openresty当前支持'3'个指令集,后续随着'版本迭代',可能提供更多'功能'

思考: 为什么openresty可以在ssl握手中定义'回调'函数,而nginx都'做不到'

原因: 'openresty'使用了'openssl'的库,跟nginx'没有'任何关系

思考: 是否支持'双向'认证?

细节: 注意'openssl'的版本

遗留: 关于该'部分',会在学习完'ssl/tls'协议后,先学习'nginx'的ssl,再扩展openresty的ssl

padavan Nginx 在哪个目录_lua_10

  • ssl_client_hello_by_lua_block
  • ssl_client_hello_by_lua_file
  • ssl_certificate_by_lua_block
  • ssl_certificate_by_lua_file
  • ssl_session_fetch_by_lua_block
  • ssl_session_fetch_by_lua_file
  • ssl_session_store_by_lua_block
  • ssl_session_store_by_lua_file

⑦  在代码中获取当前的阶段

说明: 并'没有'实际的意义,但是会让你清晰的了解'lua相关的指令'在nginx 11个阶段的'位置'

背景: 很多'lua代码'都可以添加到处理请求过程中,而lua代码可能'互相引用'

需求: 有'一段lua代码',想知道这段代码在'哪个阶段'引用? 

做法: 通过SDK的API --> 'ngx.get_phrase',调用'返回值'

目的: 在'哪些'地方开始'影响'我们请求的? 才能处理'复杂'的openresty问题

padavan Nginx 在哪个目录_lua_11

企业使用: nginx'自编译'ngx_lua_moudle,没有使用'openresty'

维护成本: openresty官方只对'直接下载编译'提供了较好的支持

⑧  根据功能拆分

padavan Nginx 在哪个目录_padavan Nginx 在哪个目录_12

⑨  题外话

ngx_lua模块提供的指令和API

github优秀的nginx文章