← 返回上一頁
實測 DevOps Linux/Unix

VictoriaMetrics 1.156 實測:CPU 節流終於有指標可查

把 vmsingle 限在 0.5 核,用六條並行連線打 40 秒的 quantileovertime 查詢,之後去 /metrics 找「被限速了多久」。v1.155.0 的輸出裡什麼都沒有,只能自己進容器翻 cpu.stat;v1.156.0 多出一行 processcgroupcputhrottledsecond…

重點摘要
  • v1.156.0(2026-11-09)所有元件新增 process_cgroup_cpu_throttled_seconds_total,數值直接來自 cgroup 的 cpu.stat,v1.155.0 的 /metrics 裡沒有這條
  • 0.5 核限額下跑 40 秒查詢負載,指標累計 20.99 秒,跟 cpu.stat 的 throttled_usec(20986071)一致;475 個 CFS 週期中有 410 個被節流
  • 限額 0.25、1、2、4 核各跑 30 秒:節流 26.66、0.15、0、0 秒,完成查詢數 41、246、252、261 次,從 1 核起不再吃節流的虧
  • rate() 看這條指標最直覺,0.5 核滿載時約 0.51(每秒被暫停約半秒),限額調到 2 核後回到 0
  • 同版還有 vm_cache_mode、vmagent -remoteWrite.queuePath、cgroup v1 systemd slice 限額偵測修正;後兩項本次沒有實測
測試環境驗證於 2026-11-14
適用讀者
用容器或 systemd 對 VictoriaMetrics 設 CPU 限額、想提早發現被限速的維運工程師
測試版本
victoria-metrics v1.155.0 與 v1.156.0(單機版 vmsingle)
測試環境
Docker Desktop 29.8.2(linuxkit 7.0.14,cgroup v2,arm64,8 核),容器 --memory=512m
本頁目錄

把 vmsingle 限在 0.5 核,用六條並行連線打 40 秒的 quantile_over_time 查詢,之後去 /metrics 找「被限速了多久」。v1.155.0 的輸出裡什麼都沒有,只能自己進容器翻 cpu.stat;v1.156.0 多出一行 process_cgroup_cpu_throttled_seconds_total 20.986071,剛好等於 cpu.stat 的 throttled_usec 換算成秒。

這個指標在 v1.156.0(2026 年 11 月 9 日發佈)進了所有 VictoriaMetrics 元件。容器或 systemd 設了 CPU 限額的人都踩過同一個坑:行程看起來沒吃滿 CPU、機器也很閒,查詢卻變慢,因為每個 100 ms 的 CFS 週期裡被硬生生暫停了一段時間。這篇把它在不同限額下的數字、vmui 上怎麼看、以及同版其他幾個變更跑了一輪。

v1.156.0 在 0.5 核限額下 40 秒累計節流 20.99 秒,與 cpu.stat 一致
圖 1:0.5 核限額下的關鍵數字(來源:本機實測)

一、背景:限額到了,但看不到

Kubernetes 的 resources.limits.cpu、docker run --cpus、systemd 的 CPUQuota=,底層都是 cgroup 的 CFS bandwidth control:每 100 ms 一個週期,配額用完就把行程暫停到下個週期。VictoriaMetrics 這類 Go 程式在高併發查詢時很容易一瞬間把配額吃光,結果是延遲拉長,但 process_cpu_seconds_total 看起來還在限額之內,儀表板上沒有任何異常。

過去要知道有沒有被節流,只能在 Kubernetes 上靠 cAdvisor 的 container_cpu_cfs_throttled_seconds_total,或直接讀容器裡的 /sys/fs/cgroup/cpu.stat。不是 K8s 環境、或者沒裝 cAdvisor 的單機部署就看不到。v1.156.0 把這個數字直接放進程式自己的 /metrics,單機一個 binary 也能靠 -selfScrapeInterval 自己存、自己查。

github.comVictoriaMetrics v1.156.0新增 CPU 節流指標、vmagent 逐 URL 佇列路徑、cgroup v1 systemd slice 限額偵測修正Apache-2.0 / 2026-11-09

二、1.156.0 這個指標怎麼來

2.1 資料路徑

指標是 counter,單位秒。它讀的是 cgroup 的節流累計時間,所以只有在行程跑在有 CPU 限額的 cgroup 裡才會有意義;沒有限額時會是 0。

cgroup cpu.stat 被 v1.156.0 讀成 process_cgroup_cpu_throttled_seconds_total,經 self-scrape 後用 rate 查詢
圖 2:節流資料從 cgroup 到 vmui 的路徑(Graphviz 繪製)

2.2 本次 release 的重點項目

項目 v1.155.0 v1.156.0 本次是否實測
process_cgroup_cpu_throttled_seconds_total ❌ 沒有 ✅ 所有元件 ✅
vm_cache_mode(5 種快取的工作集模式) — ✅ 新增 ✅ 只看數值
vmagent -remoteWrite.queuePath — ✅ 每個 remoteWrite URL 各自設持久化佇列路徑 ❌
cgroup v1 下 systemd slice 的 CPU/記憶體限額偵測 只抓到主機整體限額 ✅ 已修正 ❌ 需要 cgroup v1 主機
Enterprise 授權 驗證 license key 改成 -eula 旗標,不再驗 key ❌ 非本次範圍

三、實測環境與方法

3.1 環境

項目 內容
主機 Docker Desktop 29.8.2,linuxkit 7.0.14,arm64,8 核,cgroup v2
被測容器 victoriametrics/victoria-metrics v1.155.0 與 v1.156.0,--cpus=0.5 --memory=512m,-retentionPeriod=1d
資料集 4,000 條序列 × 60 個樣本(15 秒間隔),共 24 萬筆,用 /api/v1/import/prometheus 匯入
負載 6 條並行 curl 迴圈,重複打 sum(quantile_over_time(0.95, load_metric[30m])) by (grp),範圍 1 小時、step 15 秒
測試日期 2026-11-14

3.2 方法與限制

每個限額只跑一輪,沒有重複取中位數,數字用來看量級與趨勢,不當成效能基準。兩個版本都給 0.5 核,各跑 40 秒對照;v1.156.0 另外用 docker update --cpus 在同一個容器上調限額,每檔 30 秒。節流秒數取負載前後 /metrics 的差值。

展開重現步驟
docker network create vm-net
docker run -d --name vm-1156 --network vm-net --cpus=0.5 --memory=512m \
  -p 55001:8428 victoriametrics/victoria-metrics:v1.156.0 \
  -retentionPeriod=1d -selfScrapeInterval=5s

# 產生並匯入 4000 序列 x 60 點
N=$(($(date +%s)*1000))
awk -v now=$N 'BEGIN{srand(1); for(s=0;s<4000;s++) for(i=0;i<60;i++)
  printf "load_metric{id=\"%d\",grp=\"g%d\"} %f %d\n", s, s%50, rand()*100, now-(i*15000)}' > data.txt
curl -s -X POST --data-binary @data.txt http://127.0.0.1:55001/api/v1/import/prometheus
curl -s http://127.0.0.1:55001/internal/force_flush

# 負載:6 個 worker 重複 query_range
Q='sum(quantile_over_time(0.95,load_metric[30m])) by (grp)'
for i in 1 2 3 4 5 6; do
  ( end=$(( $(date +%s)+40 )); while [ $(date +%s) -lt $end ]; do
    curl -s -o /dev/null -G http://127.0.0.1:55001/api/v1/query_range \
      --data-urlencode "query=$Q" --data-urlencode "start=$(( $(date +%s)-3600 ))" \
      --data-urlencode "end=$(date +%s)" --data-urlencode step=15s; done ) &
done; wait

四、結果:限額越緊,節流越多

4.1 兩個版本的 /metrics 對照

資料匯入後先確認序列數正確:

docker
$ curl -s -X POST --data-binary @data.txt http://127.0.0.1:55001/api/v1/import/prometheus
$ curl -s http://127.0.0.1:55001/internal/force_flush
$ curl -s "http://127.0.0.1:55001/api/v1/query?query=count(load_metric)"
{"status":"success","data":{"resultType":"vector","result":[{"metric":{},"value":[1794600974,"4000"]}]},"stats":{"seriesFetched": "4000","executionTimeMsec":30}}

先確認版本與指標有沒有出現。兩個容器都是 0.5 核,空閒時 process_cpu_seconds_total 都只有零點幾秒。

docker
$ docker exec vm-1155 wget -qO- http://127.0.0.1:8428/metrics | grep -E "^(process_cgroup|vm_app_version|process_cpu_seconds_total)"
process_cpu_seconds_total 0.01
vm_app_version{version="victoria-metrics-20261023-161715-tags-v1.155.0-0-g3fec2f7241", short_version="v1.155.0"} 1

再看 v1.156.0:

docker
$ docker exec vm-1156 wget -qO- http://127.0.0.1:8428/metrics | grep -E "^(process_cgroup|vm_app_version|process_cpu_seconds_total)"
process_cpu_seconds_total 0.01
process_cgroup_cpu_throttled_seconds_total 0
vm_app_version{version="victoria-metrics-20261106-175016-tags-v1.156.0-0-g0c1bf87a0c", short_version="v1.156.0"} 1

v1.155.0 那邊整條指標都不存在,不是 0。寫告警規則時要注意:混版本的叢集裡,舊節點查不到這條序列,absent() 類的規則會誤報。

4.2 0.5 核滿載 40 秒

六條連線同時打,結果兩個版本完成的查詢數幾乎一樣(151 與 152 次),差別只在 v1.156.0 能直接告訴你被節流了多久。

docker
$ ./load.sh 55000 40     # v1.155.0
queries_done=151
docker
$ ./load.sh 55001 40     # v1.156.0
queries_done=152
$ curl -s http://127.0.0.1:55001/metrics | grep -E "^process_cgroup_cpu_throttled|^process_cpu_seconds_total"
process_cpu_seconds_total 20.69
process_cgroup_cpu_throttled_seconds_total 20.986071

同一個時間點的 cgroup 原始統計:

docker
$ docker exec vm-1156 sh -c 'cat /sys/fs/cgroup/cpu.max /sys/fs/cgroup/cpu.stat'
50000 100000
usage_usec 20719189
user_usec 20494618
system_usec 224571
nr_periods 475
nr_throttled 410
throttled_usec 20986071

指標的 20.986071 與 throttled_usec 的 20986071 逐位相符,確定它就是 cgroup 的節流累計,沒有額外換算。475 個週期裡 410 個被節流,約 86%。40 秒內實際用掉的 CPU 時間是 20.69 秒(約 0.5 核乘 40 秒),被暫停的時間累計 20.99 秒,因為六條查詢同時搶一個很小的配額。

4.3 調整限額的掃描

同一個 v1.156.0 容器,docker update --cpus 切換限額,每檔 30 秒、同樣的六條連線。

docker
$ docker update --cpus=<N> vm-1156 && ./load.sh 55001 30   # N = 0.25 / 1 / 2 / 4
cpus=0.25 queries_done=41 throttled_delta=26.66
cpus=1 queries_done=246 throttled_delta=0.15
cpus=2 queries_done=252 throttled_delta=0.00
cpus=4 queries_done=261 throttled_delta=0.00
限額 0.25 核 30 秒內節流 26.66 秒,1 核降到 0.15 秒,2 核以上為 0
圖 3:CPU 限額與 30 秒內累計節流秒數(來源:本機實測)
限額 0.25 核完成 41 次查詢,1 核 246 次,2 核 252 次,4 核 261 次
圖 4:同一組負載下不同限額完成的查詢數(來源:本機實測)
CPU 限額 30 秒完成查詢數 30 秒節流秒數
0.25 核 41 26.66
1 核 246 0.15
2 核 252 0.00
4 核 261 0.00

0.25 核時吞吐掉到 1 核的約六分之一,而且節流秒數 26.66 比 30 秒的實際時間還長,因為多條線程各自被暫停,節流時間是加總。這點讀指標時要記得:節流秒數的 rate() 可以大於 1,不是百分比。從 1 核起查詢數只剩個位數差距,這個負載的瓶頸在 1 核附近。

五、在 vmui 與告警裡怎麼用

5.1 單機版要自己開 self-scrape

第一次在 vmui 查 rate(process_cgroup_cpu_throttled_seconds_total[1m]) 什麼都沒回,因為 vmsingle 預設不抓自己的 /metrics。重新啟動時加 -selfScrapeInterval=5s,再把資料重新匯入之後才查得到。實務上通常已經有 vmagent 或 Prometheus 在抓,就不需要這個旗標。

5.2 節流速率的圖

負載分兩段:先在 0.5 核限額下連跑兩輪,再用 docker update --cpus=2 把限額拉到 2 核後重跑。

vmui 上節流速率在 0.5 核時升到約 0.52,調到 2 核後回到 0
圖 5:vmui 的 rate(process_cgroup_cpu_throttled_seconds_total[20s]),兩個高峰是 0.5 核下的兩輪負載,之後回到 0(來源:本機實測,vmui v1.156.0)

用 API 取同一段 10 秒步長的數值,可以看到上升、回落與歸零的完整形狀:

docker
$ curl -s http://127.0.0.1:55001/api/v1/query_range --data-urlencode 'query=rate(process_cgroup_cpu_throttled_seconds_total[20s])' ... | python3 -c "..."
[0.0, 0.0, 0.17, 0.42, 0.51, 0.52, 0.49, 0.23, 0.05, 0.3, 0.51, 0.51, 0.48, 0.23, 0.0, 0.0, 0.0, 0.0]

曲線最高 0.5172,中位數 0.2305,跟 0.5 核的限額對得很整齊:配額用完之後每一秒大約被暫停半秒。調成 2 核之後曲線直接貼回 0,同樣的負載在 2 核下完成的查詢數也從 210 變成 423。

vmui 表格顯示累計節流秒數為 44.365471
圖 6:Table 檢視下的累計值 44.365471,是三輪負載的總和(來源:本機實測)

告警規則可以從這個寫起,閾值要依自己的服務調整,下面只是示範寫法,沒有在本次實測中真的觸發 vmalert:

rate(process_cgroup_cpu_throttled_seconds_total{job="victoria-metrics"}[5m]) > 0.1

PromQL 範本與解說

請求率、錯誤率、P95 延遲、CPU、記憶體、硬碟預測等查詢,逐段說明

載入工具中…

5.3 vm_cache_mode

同版新增的 vm_cache_mode 用 0、1、2 表示快取的工作集模式(split、switching、whole)。這個負載下看到的值:

docker
$ curl -s http://127.0.0.1:55001/metrics | grep -E "^vm_cache_mode"
vm_cache_mode{type="promql/rollupResult"} 0
vm_cache_mode{type="storage/tsid"} 0
vm_cache_mode{type="storage/metricIDs"} 2
vm_cache_mode{type="storage/metricName"} 2
vm_cache_mode{type="indexdb/tagFiltersLoops"} 0
vmui 表格顯示五種快取的 vm_cache_mode,metricIDs 與 metricName 為 2,其餘為 0
圖 7:vm_cache_mode 五種快取的目前模式,只有 storage/metricIDs 與 storage/metricName 是 2(來源:本機實測)

這張表本身沒有「好壞」,用途是除錯記憶體時知道哪個快取現在在哪種模式。4,000 條序列的小資料集看不出什麼,這裡只確認指標存在、數值可讀。

六、同版其他變更與沒測到的部分

vmagent 的 -remoteWrite.queuePath 讓每個 -remoteWrite.url 各自指定持久化佇列的目錄,多個目的地共用同一個磁碟路徑時比較好分開管理,我們沒有架 vmagent,不評論行為。cgroup v1 的 systemd slice 修正針對「只抓到主機整體限額而不是 slice 限額」的問題,結果是 Go 的 GOMAXPROCS 與記憶體上限設得比實際高,導致 OOM 與節流;這台測試環境是 cgroup v2,沒辦法重現,只能引用 release notes。

Enterprise 版的授權方式也改了,現在要加 -eula,舊的 -license 等旗標視為 -eula,原本的設定仍能啟動。用 Enterprise 的團隊升級前要自己確認合約條款,這已經超出技術測試的範圍。

七、限制與不適用的情境

這個指標只反映 cgroup 的 CFS 限額節流。沒設 CPU 限額的裸機或 VM 上,它永遠是 0,不代表沒有 CPU 瓶頸。Kubernetes 上若本來就有 cAdvisor 的 container_cpu_cfs_throttled_seconds_total,兩邊數字會重複,新指標的價值主要在單機、Docker Compose、systemd 這類沒有 cAdvisor 的部署。

本次只在 Docker Desktop 的 Linux VM 上跑,每個限額一輪,沒有驗證 Kubernetes 的 limits.cpu 路徑、cgroup v1,也沒有長時間浸泡。節流秒數會隨 CFS 週期長度與核心版本略有差異,數字的絕對值不要直接套到正式環境。

升級到 v1.156.0 後的確認清單
  • /metrics 看得到 process_cgroup_cpu_throttled_seconds_total
  • 確認有 CPU 限額的元件,數值會隨負載上升
  • 混版本叢集的告警規則不要用 absent() 判斷舊節點
  • 先用 rate(...[5m]) 觀察一週,再決定告警閾值
  • 若用 Enterprise,確認 -eula 旗標與合約

八、結論:值得升,尤其是有限額的單機部署

這個版本不需要為了它專門排升級,但本來就要跟上 v1.15x 的環境,順手升上去之後多一條很便宜的觀測訊號。對我們來說最有用的是它直接回答「查詢變慢是不是被限速」:0.5 核時節流速率接近 0.5,調高限額後立刻歸零,不用再進容器翻 cpu.stat。

我們會先在測試環境用一陣子,看 rate() 在平常負載下的基線,再訂告警閾值。若你的 VictoriaMetrics 跑在沒有限額的機器上,這個版本對你沒有新增的觀測價值,照原本節奏升級就好。

這個指標在 Kubernetes 上也能用嗎?

原理上讀的是行程所在 cgroup 的節流統計,容器有設 limits.cpu 時應該同樣適用,但本次實測只在 Docker 環境,沒有跑 Kubernetes。

節流秒數為什麼會比經過的時間還長?

它是各線程被暫停時間的加總。0.25 核跑 30 秒累計 26.66 秒,所以 rate() 可能大於 1,不能當成百分比。

舊版 v1.155.0 要怎麼看節流?

進容器讀 /sys/fs/cgroup/cpu.stat 的 nr_throttled 與 throttled_usec,或用 cAdvisor 的 container_cpu_cfs_throttled_seconds_total。

單機版為什麼一開始查不到?

vmsingle 預設不抓自己的指標,要加 -selfScrapeInterval,或讓 vmagent、Prometheus 來抓。

參考資料

  • VictoriaMetrics v1.156.0 release notes(2026-11-09):https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.156.0
  • Linux kernel:CFS Bandwidth Control(cpu.max、cpu.stat):https://docs.kernel.org/scheduler/sched-bwc.html
  • VictoriaMetrics 單機版文件:https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/
  • 本機實測原始輸出與重現步驟:見第三章折疊區塊
分享這篇
X LinkedIn Facebook Hacker News Reddit

這篇對你有幫助嗎?

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料。