鍍金池/ 教程/ Linux/ Lua 模塊開(kāi)發(fā)
Web 開(kāi)發(fā)實(shí)戰(zhàn)2——商品詳情頁(yè)
流量復(fù)制 /AB 測(cè)試/協(xié)程
常用 Lua 開(kāi)發(fā)庫(kù) 1-redis、mysql、http 客戶端
Lua 模塊開(kāi)發(fā)
常用 Lua 開(kāi)發(fā)庫(kù) 3-模板渲染
HTTP 服務(wù)
Nginx+Lua 開(kāi)發(fā)入門(mén)
安裝 Nginx+Lua 開(kāi)發(fā)環(huán)境
Redis/SSDB+Twemproxy 安裝與使用
JSON 庫(kù)、編碼轉(zhuǎn)換、字符串處理

Lua 模塊開(kāi)發(fā)

在實(shí)際開(kāi)發(fā)中,不可能把所有代碼寫(xiě)到一個(gè)大而全的 lua 文件中,需要進(jìn)行分模塊開(kāi)發(fā);而且模塊化是高性能 Lua 應(yīng)用的關(guān)鍵。使用 require 第一次導(dǎo)入模塊后,所有 Nginx 進(jìn)程全局共享模塊的數(shù)據(jù)和代碼,每個(gè) Worker 進(jìn)程需要時(shí)會(huì)得到此模塊的一個(gè)副本(Copy-On-Write),即模塊可以認(rèn)為是每 Worker 進(jìn)程共享而不是每 Nginx Server 共享;另外注意之前我們使用 init_by_lua 中初始化的全局變量是每請(qǐng)求復(fù)制一個(gè);如果想在多個(gè) Worker 進(jìn)程間共享數(shù)據(jù)可以使用 ngx.shared.DICT 或如 Redis 之類(lèi)的存儲(chǔ)。

在 /usr/example/lualib 中已經(jīng)提供了大量第三方開(kāi)發(fā)庫(kù)如 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
   ……

需要注意在使用前需要將庫(kù)在 nginx.conf 中導(dǎo)入:

Java 代碼

\#lua模塊路徑,其中”;;”表示默認(rèn)搜索路徑,默認(rèn)到/usr/servers/nginx下找  
lua_package_path "/usr/example/lualib/?.lua;;";  #lua 模塊  
lua_package_cpath "/usr/example/lualib/?.so;;";  #c模塊    

使用方式是在lua中通過(guò)如下方式引入

Java 代碼

local cjson = require(“cjson”)  
local redis = require(“resty.redis”)    

接下來(lái)我們來(lái)開(kāi)發(fā)一個(gè)簡(jiǎn)單的 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    

開(kāi)發(fā)時(shí)將所有數(shù)據(jù)做成局部變量/局部函數(shù);通過(guò) _M 導(dǎo)出要暴露的函數(shù),實(shí)現(xiàn)模塊化封裝。

接下來(lái)創(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 ("模塊名"),該模塊會(huì)到 lua_package_path 和lua_package_cpath 聲明的的位置查找我們的模塊,對(duì)于多級(jí)目錄的使用 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;  
}  

訪問(wèn)如 http://192.168.1.2/lua_module_1 進(jìn)行測(cè)試,會(huì)得到類(lèi)似如下的數(shù)據(jù),count 會(huì)遞增

count : 1
count :2
……
count :N

此時(shí)可能發(fā)現(xiàn) count 一直遞增,假設(shè)我們的 worker_processes 2,我們可以通過(guò) kill -9 nginx worker process 殺死其中一個(gè) Worker 進(jìn)程得到 count 數(shù)據(jù)變化。

假設(shè)我們創(chuàng)建了 vim/usr/example/lualib/test/module2.lua 模塊,可以通過(guò) local module2 = require("test.module2") 加載模塊

基本的模塊開(kāi)發(fā)就完成了,如果是只讀數(shù)據(jù)可以通過(guò)模塊中聲明 local 變量存儲(chǔ);如果想在每 Worker 進(jìn)程共享,請(qǐng)考慮競(jìng)爭(zhēng);如果要在多個(gè) Worker 進(jìn)程間共享請(qǐng)考慮使用 ngx.shared.DICT 或如 Redis 存儲(chǔ)。