一、先來看幾個概念問題
1.1?為什么需要?
nginx官方自帶了非常多的核心模塊,再加上第三方的模塊能夠滿足我們大部分的業務需要,但是業務的需求、業務的場景變化需要添加一些額外的功能,如果自己去開發一個nginx模塊相對來說比較笨重,我們可以使用lua腳本直接內嵌到nginx當中實現一些業務邏輯,完成一些特殊的功能需求。
1.2?什么是Lua?
Lua是一種輕量級、可嵌入式的腳本語言,可以非常容易的嵌入到其他語言中使用。用標準C語言編寫并以源代碼形式開放。設計目的是為了嵌入應用程序中,從而為應用程序提供靈活的擴展和定制功能。Lua由標準C編寫而成,幾乎在所有操作系統和平臺上都可以編譯,運行。Lua并沒有提供強大的庫,這是由它的定位決定的。所以Lua不適合作為開發獨立應用程序的語言。Lua有一個同時進行的JIT項目,提供在特定平臺上的即時編譯功能。另外Lua提供了協程并發,即以同步調用的方式進行異步執行,從而實現并發,比起回調機制的并發來說代碼更容易編寫和理解,排查問題也會容易。
Lua編寫過的項目:
1.3 什么是ngx_lua?
ngx_lua是nginx的一個模塊,將Lua嵌入到nginx中,從而可以使用Lua來編寫腳本,這樣就可以使用Lua編寫應用腳本,部署到nginx中運行,即 nginx變成了一個web容器。這樣開發人員就可以使用Lua語言開發高性能的web應用了。
1.4?部分應用場景
理論上可以使用ngx_lua開發各種復雜的web應用,不過Lua是一種腳本/動態語言,不適合業務邏輯比較重的場景,適合小巧的應用場景,代碼行數保持在幾十行到幾千行。目前見到的一些應用場景如下:
web應用:會進行一些業務邏輯處理,甚至進行耗CPU的模板渲染,一般流程:mysql/redis/http獲取數據、業務處理、產生JSON/XML/模板渲染內容,比如京東的列表頁/商品詳情頁。
接入網關:實現如數據校驗前置、緩存前置、數據過濾、API請求聚合、AB測試、灰度發布、降級、監控等功能,比如京東的交易大nginx節點、無線部門開發的無線網關、單品頁統一服務、實時價格、動態服務。
web防火墻:可以進行IP/URL/UserAgent/Referer黑名單、限流等功能。
緩存服務器:可以對響應內容進行緩存,減少到后端的請求,從而提升性能。
二、安裝nginx的lua模塊支持
2.1?安裝lua腳本語言
#?1、步驟一:下載并安裝lua
wget?http://luajit.org/download/LuaJIT-2.0.5.tar.gz?? #下載lua腳本語言?
????? tar?-zxvf?LuaJIT-2.0.5.tar.gz?? #?解壓
????? ?
????? cd?LuaJIT-2.0.5? #?進入解壓后的lua文件夾
????? ?
????? make?&&?make?install?PREFIX=/usr/local/LuaJIT? #編譯并安裝lua腳本語言?PREFIX=lua腳本語言安裝到的目錄?可以自己隨意更改
????? ?
????? ?
????? ?
#?2、步驟二:配置環境變量
vim?/etc/profile
#?加入下面2行lua的環境變量,注意自己lua的安裝路徑
export?LUAJIT_LIB=/usr/local/LuaJIT/lib
export?LUAJIT_INC=/usr/local/LuaJIT/include/luajit-2.0
#?保存后,使用以下命令?使當前窗口的環境變量立即生效????
source?/etc/profile
#?查看當前lua語言的版本
lua?-v? #?成功輸出lua語言的版本的話,則表示lua語言安裝成功
|
2.2 下載并解壓ngx_devel_kit模塊和lua-nginx-module模塊
備注說明:
#?注意:我這里都是下載到/root目錄下了
#?下載
wget?https: //github .com /simpl/ngx_devel_kit/archive/v0 .3.0. tar .gz
wget?https: //github .com /openresty/lua-nginx-module/archive/v0 .10.9rc7. tar .gz
#?解壓
tar ?-zxvf?ngx_devel_kit-0.3.0. tar .gz?
tar ?-zxvf?lua-nginx-module-0.10.9rc7. tar .gz
|
2.3?重新編譯nginx加入lua模塊的支持
nginx -V 查看當前nginx已經編譯安裝好的配置模塊
我這里的配置如下:
--user=www?--group=www?--prefix= /usr/local/nginx ?--with-http_stub_status_module?--with-http_ssl_module?--with-http_v2_module?--with-http_gzip_static_module?--with-http_sub_module?--with-stream?--with-stream_ssl_module?--with-openssl= /root/lnmp1 .6 /src/openssl-1 .1.1c?--with-openssl-opt= 'enable-weak-ssl-ciphers'
|
進入之前安裝nginx的源碼包目錄,需要重新編譯安裝nginx(在nginx -V得到的配置下,加入ngx_devel_kit-0.3.0和ua-nginx-module-0.10.2的目錄),最終的配置如下:
#?啰嗦一句。。。下面的步驟是在nginx的源碼包目錄進行的,下面的./configure可執行文件在nginx源碼包目錄中有
. /configure ?--user=www?--group=www?--prefix= /usr/local/nginx ?--with-http_stub_status_module?--with-http_ssl_module?--with-http_v2_module?--with-http_gzip_static_module?--with-http_sub_module?--with-stream?--with-stream_ssl_module?--with-openssl= /root/lnmp1 .6 /src/openssl-1 .1.1c?--with-openssl-opt= 'enable-weak-ssl-ciphers' ?--add-module= /root/lua-nginx-module-0 .10.9rc7?--add-module= /root/ngx_devel_kit-0 .3.0
#?就是在nginx原有編譯安裝配置好的基礎上增加了--add-module=/your?path/lua-nginx-module-0.10.9rc7和--add-module=/your?path/ngx_devel_kit-0.3.0
|
開始編譯并安裝(編譯安裝后新產生的nginx不會把之前配置好的nginx.conf文件中的配置給覆蓋掉 放心)
#?開始編譯并且安裝
make ?&&? make ?install
|
問題一:如果執行 make && make install 的時候 中途編譯過程中報如下錯誤:

/root/lua-nginx-module-0 .10.9rc7 /src/ngx_http_lua_module .c:?In? function ?‘ngx_http_lua_merge_srv_conf’:
/root/lua-nginx-module-0 .10.9rc7 /src/ngx_http_lua_module .c:1022:37:?error:?passing?argument?2?of?‘SSL_CTX_sess_set_get_cb’?from?incompatible?pointer? type ?[-Werror]
????????????????????????????????????? ngx_http_lua_ssl_sess_fetch_handler);
????????????????????????????????????? ^
In? file ?included?from?src /event/ngx_event_openssl .h:15:0,
????????????????? from?src /core/ngx_core .h:83,
????????????????? from? /root/lua-nginx-module-0 .10.9rc7 /src/ddebug .h:13,
????????????????? from? /root/lua-nginx-module-0 .10.9rc7 /src/ngx_http_lua_module .c:11:
/root/lnmp1 .6 /src/openssl-1 .1.1c/.openssl /include/openssl/ssl .h:720:6:?note:?expected?‘struct?SSL_SESSION?*?(*)(struct?ssl_st?*,?const?unsigned?char?*,?int,??int?*)’?but?argument?is?of? type ?struct?SSL_SESSION?*?(*)(struct?SSL?*,?u_char?*,?int,??int?*)’
? void?SSL_CTX_sess_set_get_cb(SSL_CTX?*ctx,
?????? ^
cc1:?all?warnings?being?treated?as?errors
make [1]:?***?[objs /addon/src/ngx_http_lua_module .o]?Error?1
make [1]:?Leaving?directory?` /root/lnmp1 .6 /src/nginx-1 .16.1'
make :?***?[build]?Error?2
[root@izm5e8vp7zjro140az4o97z?nginx-1.16.1] #
|
產生的報錯原因:我們在編譯配置的時候指定了--with-openssl=/root/lnmp1.6/src/openssl-1.1.1c,而lua-nginx-module模塊和openssl 1.1.1不兼容 有沖突,所以我們換成openssl 1.0.2(如果沒有 就自行下載源碼包并解壓,然后重新指定--with-openssl=openssl1.0.2的版本目錄路徑)就好了
解決該問題的方案(重新指定nginx編譯參數中的--with-openssl選項為openssl 1.0.2版本)最終nginx的編譯配置如下:
. /configure ?--user=www?--group=www?--prefix= /usr/local/nginx ?--with-http_stub_status_module?--with-http_ssl_module?--with-http_v2_module?--with-http_gzip_static_module?--with-http_sub_module?--with-stream?--with-stream_ssl_module?--with-openssl= /root/lnmp1 .6 /src/openssl-1 .0.2s?--with-openssl-opt= 'enable-weak-ssl-ciphers' ?--add-module= /root/lua-nginx-module-0 .10.9rc7?--add-module= /root/ngx_devel_kit-0 .3.0
#?上面這一步執行完成后?再次執行?編譯并安裝?即:
make ?&&? make ?install
|
一炷香的時間過后......(開個玩笑^_^)
再次執行 nginx -V 命令
作用:查看當前nginx已經編譯安裝好的配置模塊(主要查看ngx_devel_kit和lua-nginx-module模塊是否已經安裝上)
問題二:如果執行 nginx -V 命令的時候 報如下錯誤(如果沒有 請忽略以下錯誤的解決方案 直接看后面的):

nginx:?error? while ?loading?shared?libraries:?libluajit-5.1.so.2:?cannot? open ?shared?object? file :?No?such? file ?or?directory
|
產生該報錯的原因一般有如下2個:
一個是 操作系統里確實沒有包含該共享庫(lib*.so.*文件)或者共享庫版本不對, 遇到這種情況那就去網上下載并安裝上即可。
另外一個原因就是 已經安裝了該共享庫, 但執行需要調用該共享庫的程序的時候, 程序按照默認共享庫路徑找不到該共享庫文件。
所以安裝共享庫后要注意共享庫路徑設置問題= =?
解決該問題的方案如下:
#?執行這一步?將?/usr/local/LuaJIT/lib?添加到?/etc/ld.so.conf文件中
echo ?"/usr/local/LuaJIT/lib" ?>>? /etc/ld .so.conf
#?執行這一步?相當于?重新讀取/etc/ld.so.conf文件中的內容
ldconfig
|
再次執行 nginx -V 命令查看ngx_devel_kit和lua-nginx-module模塊是否已經安裝上:(如果順利的話)
--user=www?--group=www?--prefix= /usr/local/nginx ?--with-http_stub_status_module?--with-http_ssl_module?--with-http_v2_module?--with-http_gzip_static_module?--with-http_sub_module?--with-stream?--with-stream_ssl_module?--with-openssl= /root/lnmp1 .6 /src/openssl-1 .0.2s?--with-openssl-opt= enable -weak-ssl-ciphers?--add-module= /root/lua-nginx-module-0 .10.9rc7?--add-module= /root/ngx_devel_kit-0 .3.0
|
PS:上面列出的nginx編譯安裝好的配置中 看到了ngx_devel_kit和lua-nginx-module模塊已經被安裝進nginx中了,經過一番折騰后,終于 讓nginx支持使用Lua模塊了,現在我們可以使用Lua腳本語言給nginx開發自己想要的擴展功能了? ^_^ 大功告成了= =?
三、驗證nginx使用Lua語言
在nginx中的nginx.conf配置文件中的一個server段代碼里面,加入以下代碼:
location? /lua {
???????? default_type? 'text/plain' ;
???????? content_by_lua? 'ngx.say("hello,lua!!!")' ;
???????? }
|
保存退出后,重啟nginx
瀏覽器訪問 www.yourdomain.com/lua? 或者 ip地址/lua? 如果瀏覽器輸出?hello,lua!!!? 則表示成功~~
尾聲補充、關于上面中解決問題出現的 ldconfig 命令的說明
ldconfig命令的用途:主要是在默認搜尋目錄(/lib和/usr/lib)以及動態庫配置文件/etc/ld.so.conf內所列的目錄下, 搜索出可共享的動態鏈接庫(格式如lib*.so*), 從而創建出動態裝入程序(ld.so)所需的連接和緩存文件。緩存文件默認為/etc/ld.so.cache, 此文件保存已排好序的動態鏈接庫名字列表。
如果共享庫文件安裝到了/lib或/usr/lib(很多開源的共享庫都會安裝到該目錄下)目錄下,那么只需要執行一下 ldconfig 命令。
如果共享庫文件安裝到了其它“非/lib或/usr/lib“目錄下,那么在執行 ldconfig 命令前,還要把新共享庫目錄加入到共享庫配置文件/etc/ld.so.conf中。