在本文中,我將對 carbon 進程進行壓力測試。這個涉及到在很是短的時間內發佈大量指標。java
carbon-cache 配置文件限制了 Whisper 文件每分鐘建立的數量。打開配置文件,並改變配置文件的設置。ios
# vi /opt/graphite/conf/carbon.conf # Softly limits the number of whisper files that get created each minute. # Setting this value low (like at 50) is a good way to ensure your graphite # system will not be adversely impacted when a bunch of new metrics are # sent to it. The trade off is that it will take much longer for those metrics' # database files to all get created and thus longer until the data becomes usable. # Setting this value high (like "inf" for infinity) will cause graphite to create # the files quickly but at the risk of slowing I/O down considerably for a while. MAX_CREATES_PER_MINUTE = 50
由於咱們即將發佈一堆指標,讓咱們修改配置文件的這部分,把值設爲 1000。git
MAX_CREATES_PER_MINUTE = 10000
注意:你須要重啓你的 carbon cache 進程使得變動生效。github
我有一個 Stresser 應用程序能夠按期地發佈固定量的指標給 carbon-cache。它內部使用 Coda Hale 指標 library,更具體的說,它使用一個 Timer 對象收集數據。web
Stresser 接收幾個參數:緩存
你可使用如下命令運行 Stresser:服務器
java -jar stresser.jar localhost 2003 1 128 10 false
Coda Hale 指標 library 每 timer 生成 15個獨立的指標。app
# ls -l /opt/graphite/storage/whisper/STRESS/host/ip-0/com/graphite/stresser/feg/ total 300 -rw-r--r--. 1 root root 17308 Jun 4 11:22 count.wsp -rw-r--r--. 1 root root 17308 Jun 4 11:22 m15_rate.wsp -rw-r--r--. 1 root root 17308 Jun 4 11:22 m1_rate.wsp -rw-r--r--. 1 root root 17308 Jun 4 11:22 m5_rate.wsp -rw-r--r--. 1 root root 17308 Jun 4 11:22 max.wsp -rw-r--r--. 1 root root 17308 Jun 4 11:22 mean_rate.wsp -rw-r--r--. 1 root root 17308 Jun 4 11:22 mean.wsp -rw-r--r--. 1 root root 17308 Jun 4 11:22 min.wsp -rw-r--r--. 1 root root 17308 Jun 4 11:22 p50.wsp -rw-r--r--. 1 root root 17308 Jun 4 11:22 p75.wsp -rw-r--r--. 1 root root 17308 Jun 4 11:22 p95.wsp -rw-r--r--. 1 root root 17308 Jun 4 11:22 p98.wsp -rw-r--r--. 1 root root 17308 Jun 4 11:22 p999.wsp -rw-r--r--. 1 root root 17308 Jun 4 11:22 p99.wsp -rw-r--r--. 1 root root 17308 Jun 4 11:22 stddev.wsp
使用以上命令,指定 128 個定時器,發佈到 carbon-cache 的獨立指標數將是 1920 (128 * 15)。打開 dashboard,做爲咱們前面文章構建的一部分。你將看到被 carbon cache 執行建立操做數量的詳細信息。我在 MAX_CREATES_PER_MINUTE 配置改變以前啓動 Stresser。當它運行的時候,我改變這個配置文件,並重啓 carbon-cache 進程。dashboard 上的建立操做圖形顯示發生了什麼。在配置變動前,少許的建立操做以每分鐘 10 個的速度執行。重啓後,在一分鐘以內,接近 1800 個建立操做發生了,由於閾值被設置成一個更高的值 10,000。webapp
你也能夠經過逐漸設置建立閾值到 10,000 並開啓 Stresser 來測試行爲。你將看到全部的 1920 個指標在同一分鐘被建立。socket
最終,每 10 秒發佈的指標總數量是 1920。Carbon 進程指標每 60s 被存儲一次。所以,被 carbon cache 每分鐘接收到的指標數量將是 11,520 (1920 * 6)。
如今咱們有一種方式來發布指標到 carbon cache 並可視化它的行爲,咱們能夠在限制值內發佈它。隨着指標正在被髮布,運行 iostat 命令來測量 I/O 性能,由於 carbon cache 從磁盤中讀寫數據。
我已經配置了 Stresser 來作一下事情:
java -jar stresser.jar localhost 2003 1 128 10 false Initializing 128 timers - publishing 1920 metrics every 10 seconds from 1 host(s)
# iostat -x 10 Linux 2.6.32-431.11.2.el6.x86_64 (ip-10-43-138-169) 06/04/2014 _x86_64_ (4 CPU) avg-cpu: %user %nice %system %iowait %steal %idle 0.50 0.00 0.38 0.35 0.00 98.77 Device: await svctm %util xvdap1 5.28 0.32 0.26 xvdap1 6.56 0.39 0.16 xvdap1 40.25 0.33 3.62 xvdap1 37.94 0.31 3.13 xvdap1 6.39 0.54 0.44
咱們能夠增長經過 Stresser 發佈的指標數量,看它影響的 I/O 性能:
java -jar stresser.jar localhost 2003 1 256 10 false Initializing 256 timers - publishing 3840 metrics every 10 seconds from 1 host(s)
# iostat -x 10 Linux 2.6.32-431.11.2.el6.x86_64 (ip-10-43-138-169) 06/04/2014 _x86_64_ (4 CPU) avg-cpu: %user %nice %system %iowait %steal %idle 0.08 0.00 0.08 0.04 0.00 99.80 Device: await svctm %util xvdap1 51.48 0.38 6.97 xvdap1 48.06 0.38 6.96 xvdap1 21.10 0.39 1.30 xvdap1 45.21 0.58 1.48 xvdap1 60.48 0.49 13.19
注意到在這個時間點上 CPU activity 不高也是很是重要的。
如今讓咱們大大地增長指標的發佈率來看咱們的設置是否可支撐。我將使用以下 Stresser 配置:
java -jar stresser.jar localhost 2003 1 1956 10 false Initializing 1956 timers - publishing 29340 metrics every 10 seconds from 1 host(s)
# iostat -x 10 Linux 2.6.32-431.11.2.el6.x86_64 (ip-10-43-138-169) 06/04/2014 _x86_64_ (4 CPU) avg-cpu: %user %nice %system %iowait %steal %idle 0.08 0.00 0.08 0.04 0.00 99.80 Device: await svctm %util xvdap1 94.20 0.67 40.70 xvdap1 50.60 0.38 11.84 xvdap1 59.21 0.42 23.53 xvdap1 53.77 0.39 25.62 xvdap1 45.52 0.34 12.75
CPU 利用率和內存利用率稍稍增長了。注意 cache sizes 和 cache queues 也開始增加了在指標發率忽然增長後。
使用如下 Stresser 配置:
java -jar stresser.jar localhost 2003 1 4887 10 false Initializing 4887 timers - publishing 73305 metrics every 10 seconds from 1 host(s)
# iostat -x 10 Linux 2.6.32-431.11.2.el6.x86_64 (ip-10-43-138-169) 06/04/2014 _x86_64_ (4 CPU) avg-cpu: %user %nice %system %iowait %steal %idle 0.08 0.00 0.08 0.04 0.00 99.80 Device: await svctm %util xvdap1 98.76 0.74 44.29 xvdap1 83.43 0.62 22.61 xvdap1 82.47 0.62 33.51 xvdap1 123.14 0.88 52.00 xvdap1 106.97 0.75 45.58
對比前面的測試,內存消費從 500MB 增長到 900 MB,CPU activity 略有增長。若是你凝視 htop 的輸出,你將每 10秒看到一個核心尖峯(指標發佈頻率)。
使用如下 Stresser 配置:
java -jar stresser.jar localhost 2003 1 7824 10 false Initializing 7824 timers - publishing 117360 metrics every 10 seconds from 1 host(s)
# iostat -x 10 Linux 2.6.32-431.11.2.el6.x86_64 (ip-10-43-138-169) 06/05/2014 _x86_64_ (4 CPU) avg-cpu: %user %nice %system %iowait %steal %idle 12.93 0.00 5.53 6.40 0.49 74.65 Device: await svctm %util xvdap1 241.67 1.73 58.34 xvdap1 263.33 1.83 100.00 xvdap1 256.01 1.88 54.32 xvdap1 228.32 1.63 100.00 xvdap1 474.27 3.20 100.00
對 carbon cache 來講它花了 30 分鐘來建立全部的新指標。對比前面的測試,這使用了更多的內存和 CPU 利用率。儘管如此,I/O 性能有更大的影響,由於 await 列報告值更大,在多個點百分利用率用顯示 100%。cache queues 是很是高的可是仍然穩定, cache size 增長直到全部的指標被建立完成。而後直線圍繞 1.5M 左右。
Carbon 使用了一個動態 buffering 儘量多的數據點的策略,由於須要維持輸入數據點的速率,可能超過你的存儲能跟上的 I/O 操做速率。在咱們每分鐘發佈 11K 和 700K 指標到 Carbon cache 的以上場景中。在一個更簡單的場景,好比說咱們的 Stresser 應用程序被以如下方式方式:
讓咱們假設每 60,000 個不一樣的指標每分鐘有單個數據點。由於一個指標在文件系統上是以一個 Whisper 文件呈現的,Carbon 將須要每分鐘執行 60,000 次寫操做 - 每一個 Whisper 文件一個。爲了處理指標發佈率,Carbon 須要不到一毫米的時間寫一個文件。在今天,這不是問題。
儘管如此,若是指標發佈速率增長到一個很高的水平 - 像在咱們的場景每分鐘發佈 700K 個指標 - 輸入數據點的速率超過了能夠被寫入磁盤的速率。若是在 Graphite 服務器的磁盤不是 SSDs 或者有一個很低的速度時可能發生。
成千上萬個 Whisper 文件被使用 ~12 或者每個字節的數據頻繁寫入。磁盤明顯會花費更多時間用於尋址。
讓咱們假設磁盤的寫速率不是太大,而且它沒有大大增長,甚至若是咱們買了更快的 SSDs。使得寫更快的惟一方式就是少作,而且咱們能作的更少若是咱們 buffer 多個相關的數據點而且使用單個寫操做把他們寫入正確的 Whisper 文件。 Whisper 整理連貫的數據點連續寫入磁盤。
Chris Davis 決定修改 Whisper 和增長 update_many 函數。它須要一個列表的數據點做爲單個指標並壓縮相鄰數據點到一個寫操做。即便這使得寫操做很大,它寫 10個數據點 (~120 bytes) 相對於寫一個數據點 (~12 bytes)花費的時間差別是可忽略的。在每一個寫的大小開始明顯影響延遲這將須要至關多的數據點。
爲了在 Whisper 中使用 update_many 函數,在 Carbon 中實現了一個緩存機制。每一個進入的數據點基於它的指標名字被映射到一個隊列而後添加進隊列 - 經過 Receiver 線程。另一個線程 - Writer 線程 - 重複迭代全部的隊列,對於每個,它拉取出全部的數據點並使用 update_many 寫入合適的 Whisper 文件。若是數據點進入速率超過了寫速率,隊列將最終持有更多的數據點。惟一花費的服務器資源是內存,這是可接受的,由於每一個數據點只有幾字節。
這種方法的優點是必定程度上的彈性來處理臨時的 I/O 減速。若是系統須要作其餘與 Graphite 無關的 I/O 操做,這時寫速率可能減少。若是這個發生了,Carbon 隊列將緩慢增加。隊列越大,寫越大。由於數據點的總體吞吐量等於寫操做花費的每一個寫操做的平均大小比率。只要 queues 有足夠內存 Carbon 能夠持續保持。
若是 Carbon 維護的在內存中的數據點隊列等待被寫回磁盤,這意味着這些數據點將不會顯示在你的 graphite-webapp 圖表上,對嗎?錯了!
一個 socket 監聽器被添加到 Carbon,爲訪問緩存數據提供了一個查詢接口。graphite-webapp 在它每次須要檢索數據的時候使用這個查詢接口。graphite-webapp 這時能夠組合這些它從 Carbon 和 從在磁盤上 Whisper 文件檢索的數據點。所以你的 graphite-webapp 圖表將是實時的。一旦數據點被 Carbon 接收,就能夠當即被訪問。