攜程新一代監控告警平臺 Hickwall 架構演進

監控告警是網站可用性的第一道防線,爲網站提供更加實時可靠高效的監控告警,對互聯網企業具有非凡的意義。致力於這個目標,經過不斷地改進,攜程新一代監控告警平臺Hickwall在存儲效率、查詢速度和告警可靠性方面都有了極大的改善。

本文將從存儲、聚合、告警三個方面介紹Hickwall在覈心架構方面的演進。

架構演進概述

爲了更好地瞭解Hickwall在覈心架構方面的設計,我們首先將Hickwall第一代的架構和現有架構進行比較。

Hickwall最初的研發是在2015-2016年,當時我們調研了業界知名的開源監控系統。

比如Graphite,擁有非常好的生態,但是集羣配置複雜,每個指標都採用一個文件存儲,導致小文件多,iowait高,並且使用python實現,性能方面不太令人滿意。

再比如OpenTSDB,基於HBase天然就支持分佈式,但是也受限於HBase,多維查詢的時候性能比較差。而其他的監控系統也並未非常成熟,最後我們決定使用ElasticSearch作爲存儲引擎。下圖是第一代的核心架構圖。

在這個架構中監控數據從Proxy進來,經過格式整理、數據補全、限流後發送到Kafka。Donwsample消費Kafka中的原始數據進行時間維度上的聚合,聚合成5m、15m等時間維度的數據點之後寫入到Kafka。Consumer消費Kafka中的原始數據和聚合數據寫入到ES,通過API-Server提供統一的接口給看圖和告警。

因爲ES的查詢性能無法滿足Trigger高頻率的拉取需求,我們另外增加了Redis用來緩存最近一段時間的數據用於告警。這套架構初步實現了監控系統的功能,但是在使用過程中我們也發現以下幾個問題:

  • 組件過多。運維架構追求的是至簡至穩,過多的組件會增加部署和維護的難度。另外在團隊人員變動的情況下,新成員進來無法快速上手。

  • 數據堆積。Consumer消費Kafka出現問題,容易導致Kafka中數據堆積,用戶將無法看到線上系統的當前實時狀態,直到將堆積的數據消費完。按照我們的實踐經驗,數據堆積的時間往往會有幾十分鐘,這對於互聯網企業來講是個非常大的問題。

  • 數據鏈條過長。監控數據從Proxy進來到Trigger告警需要依次經過6個組件,任何一個組件出現問題,都可能導致告警漏告或誤告。

爲了解決這些問題,我們研發了Hickwall的第二代架構,使用自研的Influxdb集羣取代了ES作爲存儲引擎,如下圖。

在這個架構中監控數據從Proxy進來分三路轉發,第一路發送給Influxdb集羣,確保無論發生任何故障,只要Hickwall恢復正常,用戶就能立即看到線上系統的當前狀態。

第二路發送給Kafka,由Downsample完成數據聚合後將聚合數據直接寫入到Influxdb集羣。第三路發送給流式告警,這三路數據互不影響,即使存儲和聚合都出現問題,告警依然可以正常工作,確保了告警的可靠穩定。

Influxdb集羣設計

ES用於時間序列存儲存在不少問題,例如磁盤使用空間大,磁盤IO使用多,索引維護複雜,寫入和查詢速度慢等。

而Influxdb是排名第一的時間序列數據庫,能針對時間範圍進行高效的查詢,支持自動刪除過時數據,較低的使用和維護成本。只是早期的Influxdb不夠穩定,bug比較多,直到2017年底。我們經過測試確認Influxdb已經足夠穩定可以交付生產,就萌生了用Influxdb替換ES的想法。當然Influxdb存在單點問題,在0.12版本以後,官方的集羣方案還閉源了。

爲了解決Influxdb的單點問題,我們研發了Influxdb的集羣方案Incluster,如下圖。

Incluster並沒有對Influxdb進行代碼侵入式的修改,而是在上層維護關於數據分佈和查詢的元數據,因此當Influxdb有重大發布的時候Incluster能夠及時更新數據節點。

客戶端通過Incluster節點寫入數據,Incluster按照數據分佈策略將寫入請求轉發到相關的Influxdb節點上,查詢的時候按照數據分佈策略從各個節點上讀取數據併合並查詢結果。在元數據這一層Incluster採用raft保證元數據的一致性和分區容錯性,在具體數據節點上使用一致性hash保證數據的可用性和分區容錯性。

Incluster提供了三種數據分佈策略Series、Measurement和Measurement+Tag。通過調整數據分佈策略,Incluster能夠儘量做到減少數據熱點並在查詢時減少查詢節點。在實踐過程中,我們使用Measurement策略來存儲系統指標,如CPU;使用Measurement+Appid策略來存儲請求量。

作爲一個分佈式存儲,磁盤損壞不可避免,災備是必須考慮的問題。我們按照數據分佈策略通過讀取Influxdb底層的TSM數據文件,來恢復損壞的節點上面的數據。實踐經驗表明Incluster能夠做到半個小時恢復一個損壞的節點。

在用戶使用方面,Incluster提供了對InfluxQL的透明支持,也提供了類Graphite語法用於配圖。類Graphite語法可以簡化配圖語法,提供InfluxQL無法實現的功能,例如查詢最近一段時間變化最劇烈的指標,除此之外還可以屏蔽底層存儲細節,以後如果想使用比Influxdb更優秀的時間序列存儲引擎,可以減少用戶遷移成本。

數據聚合的探索

Influxdb在數據存儲和簡單查詢方面表現出色,但是在數據聚合上就存在一些問題。

Influxdb提供了Continuous Query Language(CQL)用於數據聚合,但是經過測試發現CQL內存佔用較大。Influxdb原本需要的內存就不小,在我們使用過程中128G內存已經使用了一半,如果再加上CQL的內存,容易造成節點不穩定。

另外CQL無法從不同的節點獲取數據進行聚合,在Incluster集羣方案中存在資源浪費維護複雜的問題。因此我們將數據聚合功能獨立出來,在外部進行數據聚合後再將聚合數據寫入到Incluster。

時間維度的聚合是有狀態的計算,我們面臨兩個問題。一個是中間狀態如何減少內存的使用,另外一個是節點重啓的時候中間狀態如何恢復。

我們通過指定每個節點需要消費的Kafka Partition,使得每個節點需要處理的數據可控,避免KafkaPartition Rebalance導致內存不必要的使用,另外通過對Measurement和Tag這些字符串的去重可以減少內存使用。中間狀態恢復方面我們並沒有使用保存CheckPoint的方法,而是通過提前一段時間消費來恢復中間狀態。這種方式避免了保存CheckPoint帶來的資源損耗。

業務場景聚合主要的挑戰在於一次聚合涉及到的指標數太多,聚合邏輯複雜。例如某個應用的某個接口的請求成功率,涉及到的指標數目上千,這種聚合查詢Influxdb無法支持的。

我們的解決方案是使用ClickHouse進行預聚合。ClickHouse是俄羅斯開源的面向OLAP的分佈式列式數據庫,擁有極高的讀寫性能,並提供了強大的SQL語言和豐富的數據處理函數,可以完成很多指標的處理,例如P95。

流式告警的實現

告警最簡單的實現就是定時從數據庫中拉取數據,然後檢查一下數據是否有異常。但是這種Pull的方式對存儲存在一定的壓力,尤其是告警規則告警對象衆多的時候,對存儲的可靠性和響應時間有極高的要求。

我們經過研究發現告警數據在所有監控數據中佔比其實不大,以攜程爲例只佔了8%,而且需要的絕大部分都是最近幾分鐘的數據,如果我們能從數據流中直接獲取所需要的數據,就能過濾掉大部分不必要的數據,避免對後臺存儲的依賴,讓告警變得更加可靠實時。

實現流式告警最大的挑戰是數據訂閱。我們不可能讓每一個告警規則都去消費一遍數據流,最好的方式是消費一遍數據流然後將告警數據準確的分發到告警上下文中。

在這裏如何降低數據分發的時間複雜度和空間複雜度是最大的難點。

Hickwall的實現思路是減治法,通過Measurement精確匹配減少下一步需要匹配的規則數量,通過tagValue的布隆過濾器判斷是哪個Trigger節點需要的數據。Trigger節點收到數據以後對數據點進行精確的匹配過濾,轉發到具體的告警上下文中。

這個方案的優勢在於時間複雜度不隨規則數量告警對象而線性增長,空間複雜度不隨tagValue的長度而增長。

Hickwall使用Akka框架進行告警邏輯和告警數據的處理。Akka是異步高併發的框架,提供了Actor編程模型,能夠輕鬆實現併發地處理數據和執行告警邏輯。

生產系統是個時刻變化的系統,每時每刻都可能有機器上下線,每時每刻都可能有應用發佈變更,隨着這些變動告警系統需要隨之增刪告警對象和修改告警閾值。而Actor的創建刪除是非常輕量的,爲生產系統提供了非常友好的抽象,降低了開發成本。

Hickwall使用了RocksDB來緩存告警數據,通過JNI直接嵌入到Trigger實例中。RocksDB是Facebook開源的KV數據庫,基於Google的LevelDB進行了二次開發,底層存儲使用LSM Tree,擁有極高的寫入速率。

無停滯的處理數據在流式告警中是非常重要的,使用RocksDB能夠減少JVM中的對象,減少內存的使用,進而減少了JVM GC的壓力。

在用戶使用方面,Hickwall提供了基於JS語法的DSL語言,Init DSL負責數據的訂閱和接收到數據後的處理工作,提供了groupBy、filter、exclude、summarize等流式計算中常見的數據處理函數,Run DSL負責具體的告警邏輯,判斷是否有異常。

考慮到DSL書寫有一定的難度,Hickwall提供了語法檢查、歷史數據回測等功能,幫助用戶書寫出符合需求的告警邏輯。


作者簡介

陳漢,攜程網站運營中心研發工程師,從事Hickwall監控告警平臺的研發工作。 經歷了Hickwall項目的雛形到交付生產再到不斷改進,通過整個開發過程,對監控領域有了深入的瞭解。喜歡探究系統的底層原理,對分佈式有濃厚的興趣。本文來自陳漢在“2018攜程技術峯會”上的分享,首發於“攜程技術中心“。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章