OpenResty 如何只啟動(dòng)一個(gè) timer 工作?

2021-08-07 11:57 更新
應(yīng)用場(chǎng)景

整個(gè) OpenResty 啟動(dòng)后,我們有時(shí)候需要后臺(tái)處理某些動(dòng)作,比如數(shù)據(jù)定期清理、同步數(shù)據(jù)等。而這個(gè)后臺(tái)任務(wù)實(shí)例我們期望是唯一并且安全,這里的安全指的是所有 Nginx worker 任意 crash 任何一個(gè),有機(jī)制合理保證后續(xù) timer 依然可以正常工作。

這里需要給大家介紹一個(gè)重要 API ngx.worker.id()

語法: seq_id = ngx.worker.id()

返回當(dāng)前 Nginx 工作進(jìn)程的一個(gè)順序數(shù)字(從 0 開始)。

所以,如果工作進(jìn)程總數(shù)是 N,那么該方法將返回 0 和 N - 1 (包含)的一個(gè)數(shù)字。

該方法只對(duì) Nginx 1.9.1+ 版本返回有意義的值。更早版本的 nginx,將總是返回 nil 。
解決辦法

通過 API 描述可以看到,我們可以用它來確定這個(gè) worker 的內(nèi)部身份,并且這個(gè)身份是相對(duì)穩(wěn)定的。即使當(dāng)前 Nginx 進(jìn)程因?yàn)槟承┰?crash 了,新 fork 出來的 Nginx worker 是會(huì)繼承這個(gè) worker id 的。

剩下的問題就比較簡(jiǎn)單了,完全可以把我們的 timer 綁定到某個(gè)特定的 worker 上即可。 下面的例子,演示如何只在 worker.id 為 0 的進(jìn)程上運(yùn)行后臺(tái) timer。

init_worker_by_lua_block {
     local delay = 3  -- in seconds
     local new_timer = ngx.timer.at
     local log = ngx.log
     local ERR = ngx.ERR
     local check

     check = function(premature)
         if not premature then
             -- do the health check or other routine work
             local ok, err = new_timer(delay, check)
             if not ok then
                 log(ERR, "failed to create timer: ", err)
                 return
             end
         end
     end

     if 0 == ngx.worker.id() then
         local ok, err = new_timer(delay, check)
         if not ok then
             log(ERR, "failed to create timer: ", err)
             return
         end
     end
}


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)