PromQL聚合計算函數

本章重點,promQL進階,by/without, on/ignoring,group_left/group_right

promQL篇章: 表達式,豆包ai,偏移量修改器,指標類型,指標類型,聚合計算函數,持久化查詢

參考:豆包ai+(prometheus實戰個人總結)

一、聚合計算

  • 單指標的侷限性

    在實際監控場景中,孤立的單指標樣本值往往無法直接支撐決策:

    • 集羣場景:Web服務器集羣包含20+實例時,逐個查看每個實例的響應時長,既低效又無法把握集羣整體負載狀態;
    • 多維度場景:同一接口的請求量按“地域+終端類型”拆分後,單維度數據無法反映接口整體服務能力;
    • 趨勢分析:單時間點的CPU使用率無法判斷負載是否持續升高。
  • 聚合計算的核心價值

    PromQL的聚合計算通過對多Target的同一指標、或同一指標的多維度數據進行聯合統計,實現三大核心價值:

    • 全局視角:彙總集羣、服務級別的核心指標,如“微服務集羣總請求量”“全機房內存使用率均值”;
    • 維度鑽取:按業務標籤(如服務、地域、接口)分組聚合,定位問題根源,如“長沙地域5xx錯誤率最高的服務”;
    • 趨勢提煉:通過統計量(如均值、分位數)過濾瞬時波動,反映指標真實趨勢,如“接口95分位響應時間”。

二、聚合函數:by/without

聚合函數的核心能力通過bywithout子句實現標籤分組,控制聚合後的結果標籤,兩者功能互補,可根據場景靈活選擇。

  • 語法格式: 聚合操作支持兩種等價格式,推薦使用格式1(聚合函數後接分組子句),可讀性更高:

    # 格式1:聚合函數後接分組子句(推薦)
    <聚合函數>([參數, ]<即時向量表達式>)[without | by (標籤列表)]
    
    # 格式2:分組子句嵌入聚合函數參數
    <聚合函數>[without | by (標籤列表)]([參數, ]<即時向量表達式>)
    
  • by子句:指定分組標籤

    by (標籤列表):僅保留指定標籤作為分組依據,聚合後結果僅包含這些標籤。適用於“明確知道需要保留哪些標籤”的場景。

    # 示例1:按instance分組,計算各實例的文件系統可用空間總和
    sum(node_filesystem_avail_bytes) by (instance)
    
    # 示例2:按service和path分組,計算各接口的平均響應時間
    avg(http_request_duration_seconds_sum / http_request_duration_seconds_count) by (service, path)
    
  • without子句:排除標籤分組

    without (標籤列表):刪除指定標籤,剩餘標籤作為分組依據。適用於“需要排除少數標籤,保留大部分標籤”的場景。

    # 示例1:排除job標籤,保留其他標籤(如instance、mountpoint),計算可用空間總和
    sum(node_filesystem_avail_bytes) without (device)
    
    # 示例2:排除cpu標籤,計算各實例的CPU使用率均值
    avg(irate(node_cpu_seconds_total{mode="user"}[5m])) without (cpu)
    
  • 關鍵注意事項

    • 標籤唯一性:聚合後的標籤組合需唯一,否則會導致結果覆蓋;
    • 標量轉換:若聚合後無分組標籤(即全局聚合),返回結果為標量,可通過scalar()函數顯式轉換,如scalar(sum(http_requests_total));
    • 嵌套聚合:支持聚合函數嵌套使用,如sum(avg(irate(...)) by (instance)),實現“先按實例聚合,再全局彙總”。

三、聚合函數全解析

PromQL內置11種聚合函數,僅支持作用於即時向量(不支持範圍向量),返回結果為新的即時向量或標量。

3.1 聚合函數速查表

函數名 核心功能 返回類型 典型場景 關鍵備註
sum() 樣本值求和 即時向量/標量 集羣總資源使用、服務總請求量 支持多標籤分組求和
avg() 樣本值求平均 即時向量/標量 多實例指標均值、接口平均響應時間 受極端值影響,需結合分位數使用
count() 統計分組內時間序列數量 即時向量/標量 運行中實例數、異常接口數 統計“序列數”而非“樣本值總和”
stddev() 計算標準差 即時向量/標量 指標波動程度分析(如響應時間穩定性) 值越大,數據波動越劇烈
stdvar() 計算方差 即時向量/標量 數據離散度評估(如負載均衡度) 標準差的平方,反映整體離散程度
min() 取樣本最小值 即時向量 最低可用內存、最小接口響應時間 返回對應最小值的時間序列
max() 取樣本最大值 即時向量 最高CPU使用率、峯值網絡吞吐量 返回對應最大值的時間序列
topk(k, expr) 返回前k個最大樣本值的序列 即時向量 高負載實例排序、慢接口定位 k為正整數,支持嵌套聚合
bottomk(k, expr) 返回前k個最小樣本值的序列 即時向量 閒置資源識別、低請求量接口篩選 k為正整數,可用於資源優化
quantile(φ, expr) 返回指定分位數的值(0≤φ≤1) 即時向量/標量 響應時間分位值、負載分佈分析 φ=0.95常用作“用户體驗基準”
count_values(lbl, expr) 統計樣本值的出現次數 即時向量 狀態碼分佈、實例健康狀態統計 返回標籤為“樣本值”、值為“次數”的向量

3.2 重點函數實戰示例

以下示例基於常見監控指標(如node_exporter、http_exporter輸出指標),覆蓋不同業務場景,可直接複用或修改後使用。

3.2.1 sum():求和聚合的核心場景
  • 説明

    • sum()是最常用的聚合函數,核心用於“總量統計”,結合by/without子句可實現多維度分組求和。
    • 語法格式:sum(即時向量表達式) [by (分組標籤列表) | without (排除標籤列表)]
  • 示例

    # 1. 統計服務器集羣的物理CPU核心總數
    count(sum(node_cpu_seconds_total) by (cpu))
    
    # 2. 統計5分鐘內各微服務的HTTP請求總增量,按服務名分組
    # increase()計算5分鐘增量,sum()按service分組求和
    sum(increase(http_requests_total[5m])) by (service)
    
    # 3. 計算所有實例的內存使用總量(總內存-空閒內存)
    sum(node_memory_MemTotal_bytes - node_memory_MemFree_bytes)
    
3.2.2 avg():均值統計的正確姿勢
  • 説明

    • avg()用於計算多樣本的平均值,適合“整體水平評估”,但需注意極端值對結果的影響,建議結合max()/min()使用。
  • 示例

    # 1. 統計不同機房API服務的平均網絡延遲,按機房標籤(room)分組
    avg(net_response_time_seconds{job="api-service"}) by (room)
    
    # 2. 計算所有實例5分鐘內的平均CPU使用率,排除空閒狀態(mode="idle")
    # 説明:irate()計算瞬時速率,避免因Counter重置導致的誤差
    avg(irate(node_cpu_seconds_total{mode='idle'}[5m])) by (cpu) * 100
    
3.2.3 quantile():分位數的關鍵應用
  • 説明

    • quantile(φ, expr)是“用户體驗監控”的核心函數,通過分位數過濾極端值,更貼近真實業務場景(如95%用户的響應時間)。
    • 常見分位數場景:φ=0.5(中位數,反映整體分佈中心)、φ=0.95(常用用户體驗基準)、φ=0.99(極端場景基準)。
  • 示例

    # 1. 按服務分組,計算各服務的95分位響應時間(排除極端慢請求的干擾)
    #  響應時間=總耗時/請求數,再計算95分位值
    quantile(0.95, http_request_duration_seconds_sum / http_request_duration_seconds_count) by (service)
    
    # 2. 磁盤使用率分佈分析, 計算各掛載點的99分位磁盤使用率,評估極端情況下的磁盤壓力
    quantile(0.95,(node_filesystem_size_bytes - node_filesystem_free_bytes)/node_filesystem_size_bytes * 100) by (mountpoint)
    
3.2.4 topk()/bottomk():排序篩選實戰
  • 説明:

    • topk()和bottomk()用於從大量序列中篩選“極值序列”,常用於問題定位和資源優化。
  • 示例

    # 1. 篩選CPU使用率前5的實例,定位高負載節點
      # 先計算各實例非空閒CPU速率總和,再取前5
    topk(5,sum(irate(node_cpu_seconds_total{mode!='idle'}[5m])) by (instance))
    
    # 2. 篩選內存使用率最低的3個實例,判斷是否存在閒置資源可優化
    bottomk(3,(node_memory_MemTotal_bytes - node_memory_MemFree_bytes)/node_memory_MemTotal_bytes * 100)
    
3.2.5 count_values():狀態分佈統計
  • 説明

    • count_values(lbl, expr)用於統計“樣本值的出現次數”,返回的向量標籤為樣本值,值為出現次數,適合狀態分佈分析。
  • 示例

    # 1. 統計200、404、500三種狀態碼的請求數分佈,標籤名為status_code
    count_values("status_code", http_requests_total{status_code=~"200|404|500"})
    
    # 2. 統計nodes任務下實例的健康狀態(up=1為正常,up=0為異常)
    count_values("health_status", up{job="nodes"})
    

四、即時向量運算邏輯

PromQL支持兩個即時向量間的算術運算(如加減乘除)、比較運算(如>、<),核心通過“向量匹配”規則確定兩個向量的關聯關係,分為“一對一匹配”和“一對多/多對一匹配”。

  • 向量匹配核心概念
    • 即時向量:包含多個時間序列,每個序列有唯一的標籤組合和對應樣本值;
    • 匹配依據:通過標籤組合匹配兩個向量中的時間序列;
    • 運算結果:匹配成功的序列執行運算,未匹配的序列被過濾。

4.1、一對一匹配

兩個向量中“標籤組合完全相同”的序列進行匹配,一對一執行運算。若標籤不完全匹配,可通過ignoring(忽略指定標籤)或on(僅保留指定標籤)調整匹配範圍。

  • 語法格式

    # 忽略指定標籤進行匹配
    <向量A> <運算符號> ignoring(<標籤列表>) <向量B>
    
    # 僅按指定標籤進行匹配
    <向量A> <運算符號> on(<標籤列表>) <向量B>
    
  • 示例

    # 1. 計算HTTP 500錯誤佔總請求的比例,http_errors包含code標籤,http_requests無code標籤,需忽略code標籤匹配
    # 5分鐘內500錯誤速率 / 總請求速率,忽略code標籤 
    rate(http_errors{status_code="500"}[5m]) / ignoring(code) rate(http_requests[5m])
    
    # 2. 按instance標籤匹配總內存和空閒內存,計算各實例內存使用率
    # # (總內存-空閒內存)/總內存 *100,僅按instance標籤匹配
    (node_memory_MemTotal_bytes - node_memory_MemFree_bytes) / on(instance) node_memory_MemTotal_bytes * 100
    

4.3 一對多/多對一匹配

  • 當一個向量中的一個序列可匹配另一個向量中的多個序列時

    • group_left(左側為“多”,右側為“一”)
    • group_right(右側為“多”,左側為“一”)
    • 定“多”的一側,實現一對多或多對一運算(左多就是多對一,右多就是一對多)
  • 語法格式

    # 左側為多,右側為一,忽略指定標籤匹配
    <向量A(多)> <運算符號> ignoring(<標籤列表>) group_left <向量B(一)>
    
    # 右側為多,左側為一,僅按指定標籤匹配
    <向量A(一)> <運算符號> on(<標籤列表>) group_right <向量B(多)>
    
  • 示例

    # 1. 算各狀態碼(200、404、500)的請求佔總請求的比例,左側http_requests_total按service和status_code分組(多序列),右側按service分組(單序列)
    # 左側多序列(service+status_code),右側單序列(service),忽略status_code匹配
    sum(rate(http_requests_total[5m])) by (service, status_code) / ignoring(status_code) group_left sum(rate(http_requests_total[5m])) by (service)
    
    # 2. 判斷各實例CPU使用率是否超過所在區域的閾值,左側為各實例使用率(多序列,含instance和region標籤),右側為區域閾值(單序列,含region標籤)
    # 左側多實例,右側單區域閾值,按region標籤匹配,右側為多(通過group_right)
    sum(irate(node_cpu_seconds_total{mode!="idle"}[5m])) by (instance, region) > on(region) group_right instance region_cpu_threshold
    這個值region_cpu_threshold需要在配置文件中定義
      - job_name: 'custom_thresholds'
        static_configs:
          - targets: ['127.0.0.1']
            labels:
              region: 'cn-north'
            metrics:
              - name: region_cpu_threshold
                value: 85
    
  • 向量匹配注意事項

    • group_left/group_right必選:當兩個向量的標籤基數不匹配時,必須指定group_left或group_right,否則會報錯;
    • 標籤保留:運算後保留“多”側的標籤,“一”側的非匹配標籤會被過濾;
    • 運算優先級:向量運算優先級高於聚合運算,建議通過括號控制運算順序。

五、語法速查表

5.1. 聚合分組語法:by vs without

語法 核心作用 語法格式 適用場景
by 僅保留指定標籤為分組依據,結果含指定標籤 聚合函數 (即時向量) by (標籤 1,...) 明確需保留的分組標籤(如服務、實例)
without 刪除指定標籤,剩餘標籤為分組依據 聚合函數 (即時向量) without (標籤 1,...) 排除少數無關標籤(如排除 job 標籤)

5.2. 向量匹配調整語法:on vs ignoring

語法 核心作用 語法格式 適用場景
on 僅用指定標籤匹配,忽略其他標籤 向量 A 運算符號 on (標籤 1,...) 向量 B 兩向量標籤多,僅需部分標籤匹配(如 instance)
ignoring 忽略指定標籤,用剩餘標籤匹配 向量 A 運算符號 ignoring (標籤 1,...) 向量 B 兩向量僅少數標籤不一致(如排除 code 標籤)

5.3. 多對一匹配語法:group_left vs group_right

語法 核心作用 語法格式 適用場景
group_left 左側為 “多”、右側為 “一”,一右配多左 向量 A (多) 運算符號 on/ignoring (標籤) group_left 向量 B (一) 多序列關聯單序列數據(如各狀態碼關聯總請求)
group_right 右側為 “多”、左側為 “一”,一左配多右 向量 A (一) 運算符號 on/ignoring (標籤) group_right 向量 B (多) 多序列關聯單序列閾值(如多實例關聯區域閾值)

關鍵説明

  1. 優先級:on/ignoringgroup_left/group_right 配合使用,控制向量匹配;by/without 僅作用於聚合函數。
  2. 標籤保留:聚合後標籤由 by/without 控制;向量運算後保留 “多” 側標籤。

六、指標查詢示例速查

  • 服務器監控場景

    • CPU使用率

      • 場景:計算各實例5分鐘內非空閒CPU使用率,按實例分組。

      • 邏輯:irate()計算瞬時空閒速率 → 按實例求平均 → 100減空閒率得到使用率。

        100 - avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance) * 100
        
    • 內存使用率

      • 場景:計算各實例內存使用率,包含緩衝(Buffers)和緩存(Cached)的空閒內存。

      • 説明:Linux系統中,Buffers和Cached可被回收,需計入“可用內存”。

        (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) / node_memory_MemTotal_bytes * 100
        
    • 磁盤使用率與預測

      # 1. 計算/分區的磁盤使用率
      (node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"}) / node_filesystem_size_bytes{mountpoint="/"} * 100
      
      # 2. 基於1小時歷史數據,預測4小時後/分區是否會耗盡空間(返回<0表示將耗盡)
      predict_linear(node_filesystem_free_bytes{mountpoint="/"}[1h], 4*3600) < 0
      
  • 應用監控場景

    • HTTP接口核心指標

      # 接口QPS:
      sum(rate(http_requests_total[5m])) by (path)
      
      # 接口錯誤率
      sum(rate(http_requests_total{status_code=~"5.."}[5m])) by (path) / sum(rate(http_requests_total[5m])) by (path) * 100
      
      # 95分位響應時間:
      quantile(0.95, http_request_duration_seconds_sum / http_request_duration_seconds_count) by (path)
      
    • 服務健康狀態

      # 1. 監控systemd管理的node_exporter服務是否處於active狀態(返回1正常,0異常)
      # 配置要求:node_exporter需啓用--collector.systemd參數,並指定監控的服務單元。
      node_systemd_unit_state{name="node_exporter.service", state="active"}
      
  • 業務監控場景

    # 1. 統計電商平台各支付方式的成功率(支付成功數/支付總次數),按支付方式(pay_type)分組。
    # 説明:需業務代碼埋點輸出pay_success_total(支付成功計數器)和pay_total(支付總計數器)指標。
    sum(rate(pay_success_total[5m])) by (pay_type) / sum(rate(pay_total[5m])) by (pay_type) * 100