高並發 Nginx+Lua OpenResty系列(4)——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客戶端:
在這里插入圖片描述
需要注意在使用前需要將庫在nginx.conf中導入:

#lua模塊路徑,多個之間”;”分隔,其中”;;”表示默認搜索路徑,默認到/usr/servers/nginx下找  

lua_package_path "/usr/openResty/lualib/?.lua;;"; #lua 模塊

lua_package_cpath "/usr/openResty/lualib/?.so;;"; #c 模塊

使用方式是在lua中通過如下方式引入:

-- 初始化耗時的模塊
local redis =  require("resty.redis")
local cjson =  require("cjson")

接下來我們來開發一個簡單的lua模塊。

vi /usr/openResty/lualib/module1.lua

module1.lua

local count = 0
local function hello()
   count = count + 1
   ngx.say("count : ", count)
end

local _M = {
   hello = hello
}

return _M

開發時將所有數據做成局部變量/局部函數;通過 _M導出要暴露的函數,實現模塊化封裝。
接下來創建test_module_1.lua
test_module_1.lua

local module1 = require("module1")

module1.hello()

使用 local var = require(“模塊名”),該模塊會到lua_package_path和lua_package_cpath聲明的的位置查找我們的模塊,對於多級目錄的使用require(“目錄1.目錄2.模塊名”)加載。

openResty.conf配置文件

    location /lua_module_1  {
        default_type "text/html";
        lua_code_cache on;
        content_by_lua_file /usr/openResty/lua/test_module_1.lua;
    }

test_module_1.lua

local model1 = require("model1")

model1.hello()

訪問如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存儲。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM