所以你收集指標。 正如我們一樣。 我們也收集指標。 當然是做生意所必需的。 今天我們要講的是我們監控系統的第一個環節-相容statsd的聚合伺服器
從我們之前的文章(
權利要求1。 該專案的開發者 Github 停止了支援:發布補丁和修復程序,接受我們的和(不僅僅是我們的)PR。 在過去幾個月(2018 年 2 月至 XNUMX 月),活動已恢復,但在此之前有近兩年的完全平靜。 此外,該項目正在開發中
權利要求2。 計算的準確性。 Brubeck總共收集了65536個值進行聚合。 在我們的例子中,對於某些指標,在聚合期間(30秒),可能會到達更多的值(峰值為1)。 這次採樣的結果是,最大值和最小值顯得毫無用處。 例如,像這樣:
一如既往
本來應該怎樣
基於同樣的原因,金額通常計算不正確。 在這裡添加一個帶有 32 位元浮點溢出的 bug,當接收到看似無辜的指標時,它通常會將伺服器發送到段錯誤,然後一切都會變得很好。 順便說一句,該錯誤尚未修復。
最後, 索賠X。 在撰寫本文時,我們已準備好將其呈現給我們能夠找到的所有 14 個或多或少可用的 statsd 實作。 讓我們想像一下,某些單一基礎設施已經發展得如此之快,以至於接受 4 萬 MPS 已經不夠了。 或者,即使它還沒有增長,但這些指標對你來說已經如此重要,即使是圖表中短暫的 2-3 分鐘的下降也可能變得至關重要,並導致經理們陷入難以克服的抑鬱情緒。 由於治療憂鬱症是一項吃力不討好的任務,因此需要技術解決方案。
首先是容錯,這樣伺服器突然出現的問題不會導致辦公室出現精神病殭屍大災難。 其次,擴展至能夠接受超過 4 萬 MPS,無需深入挖掘 Linux 網路堆疊並平靜地「廣度」增長到所需的大小。
由於我們有擴展空間,因此我們決定從容錯開始。 「關於! 容錯! 很簡單,我們能做到。」我們這樣想並啟動了 2 台伺服器,在每台伺服器上提供了一份 brubeck 副本。 為此,我們必須將帶有指標的流量複製到兩台伺服器,甚至為此編寫
如果你稍微思考一下這個問題,同時用鏟子挖雪,那麼你可能會想到以下明顯的想法:你需要一個可以在分散式模式下工作的 statsd。 即實現節點之間在時間和指標上的同步。 「當然,這樣的解決方案可能已經存在,」我們說,然後去了谷歌...... 他們什麼也沒找到。 在瀏覽了不同 statsd 的文檔後(
然後我們想起了在 Just for Fun 黑客馬拉鬆上編寫的「玩具」statsd - Bioyino(專案名稱是在黑客馬拉松開始前由腳本生成的),並意識到我們迫切需要自己的 statsd。 為了什麼?
- 因為世界上的 statsd 克隆太少了,
- 因為可以提供期望的或接近期望的容錯性和可擴展性(包括同步伺服器之間的聚合指標並解決發送衝突的問題),
- 因為可以比 brubeck 更準確地計算指標,
- 因為你可以自己收集更詳細的統計數據,而布魯貝克實際上沒有向我們提供這些數據,
- 因為我有機會編寫自己的超高性能分佈式規模實驗室應用程序,該應用程式不會完全重複另一個類似的超高性能的架構......好吧,就是這樣。
寫什麼? 當然,在 Rust 中。 為什麼?
- 因為已經有了原型解決方案,
- 因為文章的作者當時已經了解 Rust,並渴望在其中寫一些東西用於生產,並有機會將其開源,
- 因為由於接收到的流量的性質(幾乎是實時),帶有 GC 的語言不適合我們,並且 GC 暫停實際上是不可接受的,
- 因為您需要與 C 相當的最大性能
- 因為 Rust 為我們提供了無所畏懼的並發性,如果我們開始用 C/C++ 寫它,我們會比 brubeck 遇到更多的漏洞、緩衝區溢位、競爭條件和其他可怕的字詞。
還有一個反對 Rust 的論點。 該公司沒有使用 Rust 創建專案的經驗,現在我們也不打算在主專案中使用它。 因此,我們非常擔心一切都不會成功,但我們決定冒險嘗試。
時間飛逝...
最後,經過幾次失敗的嘗試,第一個工作版本就準備好了。 發生了什麼事? 這就是發生的事情。
每個節點接收自己的指標集並累積它們,並且不會聚合最終聚合需要完整集合的那些類型的指標。 這些節點透過某種分散式鎖定協定相互連接,該協定允許您在其中選擇唯一一個(我們在這裡哭了)值得向偉大的節點發送指標的節點。 這個問題目前正在解決
具有度量的UDP封包透過簡單的循環在網路設備上的節點之間不平衡。 當然,網路硬體不會解析資料包的內容,因此每秒可以拉取超過 4M 的資料包,更不用說它根本不知道的指標了。 如果我們考慮到指標並不是在每個資料包中一次出現一個,那麼我們就不會預見到此位置會出現任何效能問題。 如果伺服器崩潰,網路設備會快速(1-2 秒內)偵測到這一事實,並將崩潰的伺服器從輪換中刪除。 因此,被動(即非領導者)節點實際上可以打開和關閉,而不會注意到圖表上的下降。 我們損失的最大值是最後一秒傳入的指標的一部分。 領導者的突然丟失/關閉/切換仍然會造成輕微異常(30秒間隔仍然不同步),但是如果節點之間存在通信,則可以將這些問題最小化,例如透過發送同步資料包。
關於內部結構的一些資訊。 當然,該應用程式是多執行緒的,但執行緒架構與 brubeck 中使用的不同。 brubeck 中的線程是相同的 - 每個線程都負責資訊收集和聚合。 在bioyino中,工作人員分為兩類:負責網路的人員和負責聚合的人員。 這種劃分可以讓您根據指標類型更靈活地管理應用程式:在需要密集聚合的地方,可以添加聚合器,在網路流量較大的地方,可以添加網路流量的數量。 目前,我們的伺服器在 8 個網路和 4 個聚合流中運作。
計數(負責聚合)部分非常無聊。 網路流填充的緩衝區分佈在計數流中,隨後在計數流中進行解析和聚合。 根據請求,給予發送到其他節點的指標。 所有這些,包括在節點之間發送資料以及與 Consul 一起工作,都是非同步執行的,在框架上運行
開發過程中的更多問題是由負責接收指標的網路部分引起的。 將網路流分成單獨的實體的主要目標是希望減少流所花費的時間 沒有 從套接字讀取資料。 使用非同步UDP和常規recvmsg的選項很快就消失了:第一個消耗太多的用戶空間CPU用於事件處理,第二個需要太多的上下文切換。 因此現在使用
注意
在預設設定中,緩衝區大小設定得相當大。 如果您突然決定自己嘗試該伺服器,您可能會遇到這樣的情況:發送少量指標後,它們將不會到達 Graphite,而是保留在網路流緩衝區中。 要使用少量指標,您需要在配置中將 bufsize 和 task-queue-size 設定為較小的值。
最後,為圖表愛好者提供一些圖表。
統計每台伺服器傳入的metrics數量:超過2萬MPS。
禁用節點之一併重新分配傳入指標。
傳出指標統計:只有一個節點總是發送-raid boss。
統計每個節點的運作情況,考慮到各個系統模組的錯誤。
傳入指標的詳細資訊(隱藏指標名稱)。
接下來我們打算如何處理這一切? 當然是寫程式啦,媽的……! 該專案最初計劃是開源的,並將在其整個生命週期中保持如此。 我們近期的計劃包括切換到我們自己的 Raft 版本、將對等協議更改為更便攜的協議、引入額外的內部統計數據、新類型的指標、錯誤修復和其他改進。
當然,歡迎大家為專案的開發提供協助:創建 PR、Issue,如果可能的話我們會回應、改進等。
話雖這麼說,那就是了,夥計們,買我們的大象吧!
來源: www.habr.com