Lua 模块开发
在实际开发中,不可能把所有代码写到一个大而全的lua文件中,需要进行分模块开发;而且模块化是高性能Lua应用的关键。
使用require第一次导入模块后,所有Nginx 进程全局共享模块的数据和代码,每个Worker进程需要时会得到此模块的一个副本(Copy-On-Write),即模块可以认为是每Worker进程共享而不是每Nginx Server共享;
另外注意之前我们使用init_by_lua中初始化的全局变量是每请求复制一个;如果想在多个Worker进程间共享数据可以使用ngx.shared.DICT或如Redis之类的存储。
在/usr/openResty/lualib中已经提供了大量第三方开发库如cjson、redis客户端、mysql客户端:
- lua-resty-memcached 基于cosocket API的ngx_lua的Lua memcached客户端驱动
- lua-resty-mysql ngx_lua 或 OpenResty 的非阻塞 Lua MySQL 驱动程序库
- lua-resty-redis 基于cosocket API的ngx_lua的lua redis客户端驱动
- lua-resty-dns nginx lua 模块的 DNS 解析器
- lua-resty-upload 基于ngx_lua cosocket的http文件上传流式阅读器和解析器
- lua-resty-websocket
- lua-resty-lock 简单非阻塞式锁,基于 shared memory dictionaries
- lua-resty-logger-socket 旨在替换 Nginx 的标准ngx_http_log_module以通过非阻塞套接字将访问日志推送到远程服务器(支持 syslog-ng 的日志服务)
- lua-resty-lrucache 基于LuaJIT FFI的Lua-land LRU Cache
- lua-resty-string 关于ngx_lua 和 LuaJIT 的字符串实用程序和通用哈希函数(实验性,非生产级别)
- ngx_memc 标准 memcached 模块的扩展版本,支持设置、添加、删除和更多 memcached 命令。
- ngx_postgres 允许 nginx 直接与 PostgreSQL 数据库通信的上游模块。
- ngx_redis2
- ngx_redis
- ngx_proxy 允许将请求传递到另一台服务器
- ngx_fastcgi 允许将请求传递到 FastCGI 服务器
需要注意在使用前需要将库在nginx.conf中导入:
1 | #lua模块路径,多个之间”;”分隔,其中”;;”表示默认搜索路径,默认到/usr/servers/nginx下找 |
使用方式是在lua中通过如下方式引入:
1 | -- 初始化耗时的模块 |
接下来我们来开发一个简单的lua模块。
1 | vi /usr/openResty/lualib/module1.lua |
1 | local count = 0 |
开发时将所有数据做成局部变量/局部函数;通过 _M导出要暴露的函数,实现模块化封装。
接下来创建test_module_1.lua
test_module_1.lua
1 | local module1 = require("module1") |
使用 local var = require(“模块名”),该模块会到lua_package_path和lua_package_cpath声明的的位置查找我们的模块,对于多级目录的使用require(“目录1.目录2.模块名”)加载。
openResty.conf配置文件
1 | location /lua_module_1 { |
test_module_1.lua
1 | local model1 = require("model1") |
访问如http://127.0.0.1/lua_module_1进行测试,会得到类似如下的数据,count会递增
count : 1
count :2
……
count :N
此时可能发现count一直递增,假设我们的worker_processes 2,我们可以通过kill -9 nginx worker process杀死其中一个Worker进程得到count数据变化。
假设我们创建了vim /usr/openResty/lualib/test/module2.lua模块,可以通过local module2 = require(“test.module2”)加载模块
基本的模块开发就完成了,如果是只读数据可以通过模块中声明local变量存储;如果想在每Worker进程共享,请考虑竞争;如果要在多个Worker进程间共享请考虑使用ngx.shared.DICT或如Redis存储。