nginx 安裝第三方模塊(lua)並熱升級

需求:

nginx上將特定請求拒絕,並返回特定值。html

解決辦法:

使用lua腳本,實現效果。node

操做步驟:

  1. 安裝Luajit環境
  2. 從新編譯nginx(目標機器上nginx -V 配置一致,並新增兩個模塊ngx_devel_kit,lua-nginx-module)
  3. 熱升級(不中斷服務)或重啓

配置文件添加lua腳本:nginx

#匹配請求體裏的 hello=world時返回此變量和值
  location /hello {
    rewrite_by_lua_block {
    ngx.req.read_body()
    local own_a = ngx.req.get_post_args()["hello"]
    if ( own_a == "world" ) then
      ngx.say("hello world")
    end
    }
    proxy_pass  xxxx;
  }

1、安裝Luajit環境

#安裝lua-nginx模塊須要先安裝Luajit
$ tar xf LuaJIT-2.0.4.tar.gz 
$ cd LuaJIT-2.0.4
$ make PREFIX=/usr/local/luajit
$ make install PREFIX=/usr/local/luajit

$ cat <<EOF > /etc/profile.d/luajit.sh
export LUAJIT_LIB=/usr/local/luajit/lib
export LUAJIT_INC=/usr/local/luajit/include/luajit-2.0
EOF

$ source /etc/profile.d/luajit.sh

#判斷是否有庫函數連接
if [ ! -f /lib64/libluajit-5.1.so.2 ];then
    ln -s /usr/local/luajit/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2
fi
#添加庫函數連接
if [ ! -f /lib64/libprofiler.so.0 ];then
    ln -sv /usr/local/lib/libprofiler.so.0.4.18 /lib64/libprofiler.so.0 || echo "/usr/local/lib/libprofiler.so.0.4.18 fasle,please check this" 
fi
#可使用 ldd $(which /usr/local/nginx/sbin/nginx) 查看缺乏的庫文件

2、編譯二進制文件

可在測試機(目標機器環境相同)編譯好最新的nginx二進制文件(nginx -V相同而且新增兩個模塊便可)。也可直接在目標機器上編譯,可是最後make install 不可執行,不然就覆蓋目標環境了。git

目標環境:

#將生成的nginx二進制文件替換至目錄機器
$ cd /usr/loca/nginx/sbin/
$ mv nginx{,_bak}   #先備份老的
$ mv /home/install_nginx/src/nginx ./    #將新的移動過來
$ nginx -t    #檢查配置,這一步很重要,一但報錯,說明nginx二進制文件編譯有問題,須要從新覈對環境信息並從新編譯
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

$ nginx -s reload
$
$ curl -d "hello=world" http://192.168.20.13/hello
xxx                                 #返回結果不是hello world,lua腳本配置未生效。此時老的配置並不影響

查看錯誤日誌:github

2019/10/08 17:25:22 [notice] 30580#0: signal process started
2019/10/08 17:25:22 [emerg] 22066#0: unknown directive "rewrite_by_lua_block" in /usr/local/nginx/conf/vhost/text.conf:41

未識別rewrite_by_lua_block 配置,說明lua腳本配置未生效。看來nginx -s reload是不行,只能經過熱升級了。shell

nginx啓動時master進程會初始化每一個模塊的信息,reload只是從新開啓新的worker進程。因此新增模塊只能重啓或熱升級。服務器

nginx 信號:

信號 nginx內置shell 說明
HUP nginx -s reload 重載配置文件
USR1 nginx -s reopen 從新打開日誌文件,配置mv,用作日誌切割
USR2 - 熱升級nginx程序
WINCH - 優雅的關閉相關的worker進程
QUIT nginx -s squit 優雅的中止nginx
TERM,INT nginx -s stop 當即中止nginx

nginx -s reload 執行後的nginx操做順序:curl

  1. 檢測配置是否正確
  • 錯誤,則不該用新的配置,仍是使用老的配置
  • 正確,使用新的配置,並新建worker進程,並通知老的worker進程優雅的關閉

發送熱升級信號:

$ kill -USR2 `cat /tmp/nginx.pid`
$
#執行完後查看進程,調接口都沒生效
##查看error log
2019/10/08 17:25:41 [alert] 30599#0: execve() failed while executing new binary process "nginx" (2: No such file or directory)

上面的報錯: 找不到nginx命令。nginx程序依賴環境變量,而上一次啓動確定不是用絕對路徑啓動(nginx命令直接啓)。這種狀況就沒法作熱升級,只能restart了,restart後配置即生效,接口調通了。函數

正確的nginx熱升級步驟

[root@node2013 vhost]# /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf   #正確的啓動nginx

從新執行編譯nginx步驟,爲了升級服務器可執行文件,應首先將新的可執行文件替換舊文件。以後,USR2信號應發送到主進程。主進程首先將其具備進程ID的文件重命名爲帶有.oldbin後綴的新文件,例如 /tmp/nginx.pid.oldbin,而後啓動一個新的可執行文件,該文件又啓動新的工做進程:post

[root@node2013 vhost]# kill -USR2 `cat /tmp/nginx.pid`  #發送熱升級信號
[root@node2013 vhost]# ps -ef | grep nginx            
root     31118     1  0 17:36 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
nobody   31119 31118  0 17:36 ?        00:00:00 nginx: worker process
nobody   31120 31118  0 17:36 ?        00:00:00 nginx: worker process
nobody   31121 31118  0 17:36 ?        00:00:00 nginx: worker process
nobody   31122 31118  0 17:36 ?        00:00:00 nginx: worker process
root     31177 31118  0 17:36 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
nobody   31178 31177  0 17:36 ?        00:00:00 nginx: worker process
nobody   31179 31177  0 17:36 ?        00:00:00 nginx: worker process
nobody   31180 31177  0 17:36 ?        00:00:00 nginx: worker process
nobody   31181 31177  0 17:36 ?        00:00:00 nginx: worker process
root     31185 30078  0 17:37 pts/0    00:00:00 grep --color=auto nginx
[root@node2013 vhost]# ll /tmp/
total 12
-rw-r--r-- 1 root   root     6 Oct  8 17:36 nginx.pid
-rw-r--r-- 1 root   root     6 Oct  8 17:36 nginx.pid.oldbin

$ curl -d "hello=world" http://192.168.20.13/hello  #正常返回結果,lua腳本生效。如未生效則直接發送`QUIT`信號給新的master進程。
hello world

以後,全部工做進程(舊的和新的)繼續接受請求。若是WINCHQUIT信號發送到第一個主進程,它將向其工做進程發送消息,要求它們正常關閉,而後它們將開始退出:

[root@node2013 vhost]# kill -QUIT `cat /tmp/nginx.pid.oldbin`       #優雅的退出進程
[root@node2013 vhost]# ps -ef | grep nginx              #最後查看效果,只剩下新的master和其worker進程
root     31177     1  0 17:36 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
nobody   31178 31177  0 17:36 ?        00:00:00 nginx: worker process
nobody   31179 31177  0 17:36 ?        00:00:00 nginx: worker process
nobody   31180 31177  0 17:36 ?        00:00:00 nginx: worker process
nobody   31181 31177  0 17:36 ?        00:00:00 nginx: worker process
root     31254 30078  0 17:38 pts/0    00:00:00 grep --color=auto nginx
[root@node2013 vhost]#

總結:

nginx啓動須使用絕對路徑,否則沒法處理USR2信號。

文檔連接:
nginx 安裝lua模塊: https://github.com/openresty/lua-nginx-module#installation
nginx 信號: http://nginx.org/en/docs/control.html
nginx main初始化:https://blog.csdn.net/time_change/article/details/78470901

相關文章
相關標籤/搜索