全域性 Lua 模組

在用 Edgelang 編寫自定義的 Edge 規則時,有時會需要呼叫自定義的 Lua 模組,此時可以通過在 全域性 Lua 模組 中增加此 Lua 模組。 下面我們看下如何建立一個全域性 Lua 模組,並在 Edgelang 中引用它。

在用 Edgelang 編寫自定義的 Edge 規則時,有時會需要呼叫自定義的 Lua 模組,此時可以通過在 全域性 Lua 模組 中增加此 Lua 模組。

1. 建立全域性 Lua 模組

下面我們看下如何建立一個全域性 Lua 模組,並在 Edgelang 中引用它。

首先點選 全域性配置:

然後點選左側導航欄的 全域性 Lua 模組 進入全域性 Lua 模組頁面。

在這個頁面中,會列出已經存在的全域性 Lua 模組,點選 新建 Lua 模組 按鈕建立一個新模組。

彈出的 新建 Lua 模組 對話方塊中提供以下配置項:

  • 模組名稱:填寫模組名稱,即後續在 Edgelang 中引用時使用的名稱。
  • 上傳 Lua 檔案:點選 選擇檔案 直接匯入已有的 .lua 檔案,模組名稱預設使用檔名。
  • Lua 程式碼:在編輯框中直接編寫 Lua 程式碼,支援開啟 Vim 模式 進行編輯。
  • 啟動時執行:開啟後,Edge Node 啟動時會在每個 worker 程序初始化時呼叫該模組的 init_worker() 函式。注意:啟用後,修改該 Lua 模組配置將觸發 Edge Node 的優雅重啟。此選項於 26.6.1-1 版本首次引入。

例如,編寫一個簡單的返回問候語的模組:

local _M = {}
function _M.say_hello()
    return "hello world!"
end

return _M

填寫完畢後點擊 儲存 按鈕進行儲存,Lua 模組會自動下發到每個節點,之後即可在 Edgelang 程式碼中引用:

true =>
    say(foreign-call(module: "custom_lua_module", func: "say_hello"));

2. 同步選項

頁面右上方是 同步選項,含義同 全域性配置

有點區別的是,當取消選中 自動同步到其他分割槽 後,全域性 Lua 模組除了支援複製所有 Lua 模組到指定分割槽外,還支援單獨複製某一個 Lua 模組到指定分割槽,讓我們點選複製按鈕。

然後選擇要同步的分割槽,點選 copy,當前分割槽的配置就會覆蓋指定分割槽的配置。

3. 修改歷史

可以在釋出頁面檢視同一個分割槽下 Lua 模組的修改歷史。讓我們點選 釋出 按鈕

找到對應的釋出歷史,點選 檢視詳情

就能看到此次的修改內容

4. 搜尋 Lua 模組

使用 全域性 Lua 模組 頁面中的搜尋框篩選當前頁面。搜尋會同時匹配模組名稱和 Lua 程式碼。

在 Windows 或 Linux 上按 Ctrl+K,在 macOS 上按 Cmd+K,可以開啟全域性搜尋。 全域性 Lua 模組搜尋結果會顯示所屬分割槽,用於區分同名模組。後端搜尋還支援分頁和分割槽篩選。

5. 自定義共享記憶體字典

全域性 Lua 模組 頁面的 自定義共享記憶體字典 標籤頁用於為閘道器節點定義共享記憶體字典。每個字典會在閘道器節點上生成一個指定名稱和大小的 nginx lua_shared_dict 共享記憶體區,同一閘道器節點的所有 worker 程序共享其中的資料。Lua 程式碼(例如全域性 Lua 模組)通過 ngx.shared.<name> 訪問字典。示例請參閱自定義挑戰,其中的 Lua 模組把驗證碼答案儲存在 ngx.shared.captcha_store 中。

自定義共享記憶體字典列表

點選 新建自定義共享記憶體字典,填寫字典的 名字 和 大小,然後點選 儲存。在列表中點選 編輯 或 刪除 可以修改或刪除字典。變更儲存後立即生效,無需釋出,並會觸發閘道器程序更新(binary upgrade),重啟 Edge Node 程序。詳見配置變更與程序更新。

刪除字典前,請確認沒有已釋出的 Lua 模組繼續引用它,否則相關請求會在執行時訪問不到共享記憶體。

共享記憶體字典按分割槽配置。Lua 模組 和 自定義共享記憶體字典 兩個標籤頁共用右上方的分割槽選擇框,以及同一個 自動同步到其他分割槽 選項。選擇 default 分割槽時可以修改該選項:

  • 開啟該選項時,只能編輯 default 分割槽,在該分割槽儲存的字典會替換其他所有分割槽的字典。
  • 關閉該選項時,每個分割槽各自儲存字典。兩個標籤頁分別提供 複製到其他分割槽:Lua 模組 標籤頁複製 Lua 模組,自定義共享記憶體字典 標籤頁複製字典定義。

開啟該選項本身不會複製任何字典。其他分割槽會在 default 分割槽下一次儲存或刪除字典時獲得這些字典。在此之前,同步到其他分割槽的 Lua 模組無法使用只存在於 default 分割槽的字典。如需立即複製,在 default 分割槽中點選任一字典的 編輯,不做修改直接點選 儲存。

複製自定義共享記憶體字典

在 default 分割槽關閉 自動同步到其他分割槽,然後選擇源分割槽,切換到 自定義共享記憶體字典 標籤頁,點選 複製到其他分割槽。

關閉自動同步後的自定義共享記憶體字典頁面

在彈出的 Copy Custom Shared Memory Dictionaries 視窗中勾選目標分割槽,點選 複製。源分割槽不能作為目標分割槽。

選擇自定義共享記憶體字典的目標分割槽

複製前請確認以下覆蓋範圍:

  • 複製源分割槽的全部已儲存字典定義,整組替換每個目標分割槽的字典定義。
  • 僅存在於目標分割槽的字典定義會被刪除。源分割槽沒有字典時,會清空目標分割槽的全部字典定義。
  • 不復制字典中的執行資料,也不復制 Lua 模組。

複製成功後立即下發有變更的目標分割槽,無需另行釋出。如果源分割槽或任一目標分割槽還有未釋出的 通用 配置變更,或正在批次釋出,複製會失敗。請先完成釋出,再重試複製。儲存字典時,所作用的任一分割槽有未釋出的 通用 配置變更,也會導致儲存失敗。

修改共享記憶體字典需要 全域性 Lua 模組 的寫許可權,通過 API 路徑 partitions/{partition_id}/ngx 儲存時還需要 通用 的寫許可權。更早的版本只需要 通用 的寫許可權,因此升級後請為管理共享記憶體字典的使用者組授予 全域性 Lua 模組 的寫許可權。

按分割槽配置共享記憶體字典在 OpenResty Edge 26.12.1-1 中首次引入。在更早的版本中,所有分割槽共用同一個字典列表。

6. 模組變數與更新

從 OpenResty Edge 26.12.1-1 開始,每個全域性 Lua 模組的每個版本都有獨立的變數環境。 模組中的非 local 賦值不會覆蓋另一個模組的同名變數;同一版本再次執行時可保留這些值, 新版本則使用新的環境,避免舊版本的初始化標誌或全域性變數殘留。

請通過模組返回的介面和 require 顯式共享資料,不要依賴不同模組之間的隱式全域性變數共享。 這種環境隔離不等同於安全沙箱,也不應當用於跨 worker 的持久化儲存。

重新執行模組時,會根據當前版本的 require 呼叫重新建立依賴關係。 新版本不再引用的舊依賴不會繼續影響它的更新;多個模組仍在使用的依賴會保留。