動態指標

以往我們做一些伺服器上的指標資料統計,比如某個域名的訪問量最高的 10 個客戶端地址,某個域名的快取命中率,則需要伺服器將全量的指標資料上報到監控系統,再在監控系統中資料的聚合計算。

而動態指標功能支援以類似 SQL 語法的 Metric SQL 編寫聚合規則,在伺服器上高效地實時聚合計算得到統計資料,大大地減少了需要上報的資料量。Metric SQL 的語法可以參考這個文件:Metric SQL

動態指標的統計資料目前支援以 Lua API 和 Prometheus Exporter 的方式匯出。

這裡我們提供一個統計請求狀態碼分佈的實際例子。

建立動態指標

選擇新建動態指標,名稱填寫為 status-distribution,指標聚合上報間隔為 60 秒,SQL 內容如下:

select count(*) from reqs group by status;

匯出動態指標

點選編譯按鈕,然後可以從下面的編譯歷史中下載編譯後的 zip 壓縮包。

壓縮包中包含以下這些檔案,解壓後複製到 nginx.conf 中指定的 lua_package_path 目錄下。

Archive:  Tool-1-dymetrics-status-distribution.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
     2383  01-26-2022 17:12   dymetrics.ljbc
        0  01-26-2022 17:12   metrics/
    59638  01-26-2022 17:12   metrics/status-distribution.ljbc

此外,在列表頁也可以透過多選的方式來匯出多個動態指標。

修改 nginx.conf 配置

動態指標需要修改 nginx.conf 配置才能使用,在 http block 內新增動態指標配置,示例是推薦配置的大小,可以根據實際情況調整。同時動態指標還依賴 openresty-yajl,還需要在 lua_package_cpath 加上 openresty-yajl 的路徑。

lua_shared_dict dymetrics_keys 1m;
lua_shared_dymetrics dymetrics 100m;
lua_package_cpath "/usr/local/openresty-yajl/lib64/;./?.so;;";

新增動態指標初始化程式碼

init_worker 階段進行初始化,需要提供一個回撥函式。指標每個統計週期完成後會呼叫這個函式,在這裡將統計資料回傳。

init_worker_by_lua_block {
   local report_func = function (data)
       -- `data` is the result of the metric statistics
   end

   require "dymetrics" .init_worker(report_func)
}

新增動態指標採集入口

log_by_lua_block 階段新增採集入口。

log_by_lua_block {
    require "dymetrics" .collect()
}

新增 Prometheus Exporter 介面

Prometheus 的資料可以從這個介面匯出。

location /prometheus {
    content_by_lua_block {
        require "dymetrics" .prometheus()
    }
}

完整的 nginx.conf

worker_processes  auto;

events {
    worker_connections  1024;
}

http {
    lua_package_path "$prefix/lua/?.lua;;";
    lua_package_cpath "$prefix/lualib/?.so;/usr/local/openresty-yajl/lib64/?.so;;";

    sendfile        on;
    keepalive_timeout  65;

    lua_shared_dict dymetric_version 1m;
    lua_shared_dymetrics dymetrics 100m;

    init_worker_by_lua_block {
        local report_func = function (data)
            -- do nothing
        end

        require "dymetrics" .init_worker(report_func)
    }

    server {
        listen       127.0.0.1:80;
        server_name  localhost;

        location / {
            root   html;
            index  index.html index.htm;

            log_by_lua_block {
                require "dymetrics" .collect()
            }
        }

        location /prometheus {
            content_by_lua_block {
                require "dymetrics" .prometheus()
            }
        }
    }
}