在實際開發(fā)中,不可能把所有代碼寫到一個大而全的 lua 文件中,需要進行分模塊開發(fā);而且模塊化是高性能 Lua 應用的關鍵。使用 require 第一次導入模塊后,所有 Nginx 進程全局共享模塊的數(shù)據(jù)和代碼,每個 Worker 進程需要時會得到此模塊的一個副本(Copy-On-Write),即模塊可以認為是每 Worker 進程共享而不是每 Nginx Server 共享;另外注意之前我們使用 init_by_lua 中初始化的全局變量是每請求復制一個;如果想在多個 Worker 進程間共享數(shù)據(jù)可以使用 ngx.shared.DICT 或如 Redis 之類的存儲。
在 /usr/example/lualib 中已經(jīng)提供了大量第三方開發(fā)庫如 cjson、redis 客戶端、mysql客戶端:
cjson.so
resty/
aes.lua
core.lua
dns/
lock.lua
lrucache/
lrucache.lua
md5.lua
memcached.lua
mysql.lua
random.lua
redis.lua
……
需要注意在使用前需要將庫在 nginx.conf 中導入:
Java 代碼
\#lua模塊路徑,其中”;;”表示默認搜索路徑,默認到/usr/servers/nginx下找
lua_package_path "/usr/example/lualib/?.lua;;"; #lua 模塊
lua_package_cpath "/usr/example/lualib/?.so;;"; #c模塊
使用方式是在lua中通過如下方式引入
Java 代碼
local cjson = require(“cjson”)
local redis = require(“resty.redis”)
接下來我們來開發(fā)一個簡單的 lua 模塊。
Java 代碼
vim /usr/example/lualib/module1.lua
Java 代碼
local count = 0
local function hello()
count = count + 1
ngx.say("count : ", count)
end
local _M = {
hello = hello
}
return _M
開發(fā)時將所有數(shù)據(jù)做成局部變量/局部函數(shù);通過 _M 導出要暴露的函數(shù),實現(xiàn)模塊化封裝。
接下來創(chuàng)建 test_module_1.lua
Java 代碼
vim /usr/example/lua/test_module_1.lua
Java 代碼
local module1 = require("module1")
module1.hello()
使用 local var = require ("模塊名"),該模塊會到 lua_package_path 和lua_package_cpath 聲明的的位置查找我們的模塊,對于多級目錄的使用 require ("目錄1.目錄2.模塊名")加載。
example.conf 配置
Java 代碼
location /lua_module_1 {
default_type 'text/html';
lua_code_cache on;
content_by_lua_file /usr/example/lua/test_module_1.lua;
}
訪問如 http://192.168.1.2/lua_module_1 進行測試,會得到類似如下的數(shù)據(jù),count 會遞增
count : 1
count :2
……
count :N
此時可能發(fā)現(xiàn) count 一直遞增,假設我們的 worker_processes 2,我們可以通過 kill -9 nginx worker process 殺死其中一個 Worker 進程得到 count 數(shù)據(jù)變化。
假設我們創(chuàng)建了 vim/usr/example/lualib/test/module2.lua 模塊,可以通過 local module2 = require("test.module2") 加載模塊
基本的模塊開發(fā)就完成了,如果是只讀數(shù)據(jù)可以通過模塊中聲明 local 變量存儲;如果想在每 Worker 進程共享,請考慮競爭;如果要在多個 Worker 進程間共享請考慮使用 ngx.shared.DICT 或如 Redis 存儲。