特來電監控引擎流計算應用實踐

    隨着雲計算的深刻落地,大數據技術有了堅實的底層支撐,不斷向前發展並日趨成熟,不管是傳統企業仍是互聯網公司,都再也不知足於離線批處理計算,而是更傾向於應用實時流計算,要想在殘酷的企業競爭中立於不敗之地,企業數據必須被快速處理並輸出結果,流計算無疑將是企業Must Have的大殺器。做爲充電生態網的領軍企業,特來電在流計算方面很早便開始佈局,下面筆者拋磚引玉的談一下流計算及在特來電監控引擎中的應用實踐。數據庫

1、由Bit說開去瀏覽器

 

 

    做爲計算機信息中的最小單位,Bit就像工蟻同樣忙碌,任一時刻都只能處於如下三種狀態中的一種:計算、存儲、傳輸,要麼在參與計算,要麼在去計算的路上,要麼等候計算。見微知著,雲計算架構圖中,底層IAAS必然有三個模塊:計算、存儲、網絡,由於微觀的Bit狀態本質,決定了宏觀的架構行爲。不管微觀仍是宏觀,不難發現計算是永恆的主題,一切都圍繞着計算進行,計算的結果,便會產生數據。緩存

 

今天如火如荼的大數據,本質也是數據,可是又多了一些新的特徵,好比老生常談的「4V」:Volume(數據量大,至少是TB級,甚至是PB級)、Velocity(數據增加速度快)、Variety(數據格式多樣,結構化、半結構化、非結構化)、Value(數據價值大)。大數據之因此能落地,不是依靠表面的「V」,而是「V」後強有力的支撐工具,好比用批處理工具高吞吐的支撐「Volume」,用流計算工具低延遲的支撐「Velocity」,用NoSQL工具高效存儲支撐「Variety」等。針對這幾個「V」,筆者總結了兩個共識:1. 大數據的發展,將逐漸從Volume之大,轉向Velocity之大;2.數據的價值(Value)隨着時間流逝而急劇降低。這就要求必須快速處理數據,因此咱們應該專一流計算。微信

流計算(Streaming Computing)是一種被設計來處理無窮數據集的數據處理系統引擎,流計算面向的對象是無窮數據(一種持續生成,本質上是無窮盡的數據集),與之相對的批處理面對的是有限固定的數據集。子在川上曰:逝者如斯夫!面對滾滾的無窮數據集,流計算該怎樣處理它們呢?答案即是使用窗口,就是對一個無限的流設置一個有限的元素集合,在有界的數據集上進行操做的一種機制,能夠分爲基於時間(Time-based,好比1分鐘一個窗口進行計算)以及基於數量(Count-based,好比100個數一個窗口進行計算)。網絡

流計算早期是不成熟的,由於在實現上存在一些技術難點:如何保證強一致性、如何作到精確一次(Exactly-Once)的處理數據、如何應對網絡抖動時數據的亂序與延遲到達,如何按數據的發生時間(Event Time)進行計算而不是數據被處理的時間(Processing Time)、如何在流數據上執行Streaming SQL、如何解決數據接收速度大於數據處理速度時帶來的背壓問題等。使人欣慰的是,隨着技術的不斷髮展,以上問題都被逐步解決,流計算已經能夠媲美並超越傳統批處理計算,總結起來,流計算髮展經歷了三個階段:架構

1.Lambda架構(一套數據、兩個處理引擎、兩套代碼);app

2.Kappa架構(一套數據、一個處理引擎、一套代碼,當須要全量計算時,從新起一個流計算實例,從頭開始讀取數據進行處理,並輸出到一個結果存儲中);機器學習

3.真正流計算,典型特性有:事件驅動、Exactly-Once、以流計算爲主、流計算與批處理徹底統一。異步

 

 

大數據是從批處理開始的, MapReduce花開兩枝,一枝是閉源的Google,一枝是開源的Apache,基本上谷歌內部有的大數據工具,都有對應的開源實現,Apache Beam則但願作救世主,讓閉源和開源大數據工具備一個統一的開發界面,爲上層應用開發作透明代理,屏蔽底層的各類實現方式。在亂花漸欲迷人眼的各類大數據工具中,咱們必須保持一種技術定力,不然很容易陷入技術虛無主義。基於前面分析的原則:要快速處理數據、要專一流計算、要基於真正流計算工具等,咱們最終選定了老當益壯的Flink,這也是目前在Apache Beam上運行的最好的開源Runner。maven

2、老當益壯的Flink

 

 

上圖是一些主流開源及閉源大數據工具的起源時間,能夠看到Flink(歐洲)和Spark(美國)雖然都發軔於2009年,但Flink實際上是比Spark稍早一點的,不過從當前發展形勢看,Spark意欲一統大數據天下,已經對Flink以及其餘大數據工具造成了碾壓態勢,Flink可謂「起個大早趕個晚集」,這很大程度上也和歐洲及美國的商業化環境有關。儘管如此,Flink仍可以倔強成長,一方面是你們不但願看到Spark一家獨大,須要保持平衡;另外一方面則是Flink着實有本身的獨門絕技,不然早被Spark拍死了。

 

 

上圖左邊是Spark技術棧,右邊是Flink技術棧,不難發現,兩者使命相同,都是要提供「One Stack To Rule Them All」的一站式大數據分析解決方案(涵蓋批處理、流計算、機器學習、圖計算等)。除了開源社區,Spark背後有DataBricks商業公司在運做,Flink背後有DataArtisans商業公司在運做,因爲生態環境不一樣,所以願景稍有差別。不過最大的差別在於兩者的價值觀:Spark以批處理爲主,認爲流計算是批處理的特例,使用微批處理(Micro-Batch)來應對流計算;Flink以流計算爲主,認爲批處理是流計算的特例,使用一段時間內的有限數據集來應對批處理。打個比方,Spark和Flink一塊兒吃麪包,Spark正常狀況下是一口一個麪包的吃,遇到流計算時,把麪包切片了,一口一個麪包片的吃;Flink正常狀況下一口一個麪包片的吃,遇到批處理時,幾個麪包片一塊兒吃,也能一口吃一個麪包了。從長遠來看,Flink的設計理念更契合流計算的標準模型及本質特徵,除Google閉源工具外,它是第一個真正實現亂序數據處理的開源流計算引擎,下面簡要看一下Flink的關鍵技術點。

  1. Exactly-Once

Exactly-Once是流處理系統核心特性之一,它保證每一條消息只被流處理系統處理一次,經過借鑑Chandy和Lamport在1985年發表的一篇關於分佈式快照的論文,Flink實現了Exactly-Once特性。它根據用戶自定義的Checkpoint間隔時間,定時在全部數據源中插入一種特殊的快照標記消息(Barrier),這些快照標記消息和其餘數據消息一塊兒在DAG(有向無環圖)中流動,但不會被用戶定義的業務邏輯所處理,快照的存儲是異步和增量操做,不會阻塞數據消息的處理。若發生節點掛掉等異常狀況時,只須要恢復以前成功存儲的分佈式快照狀態,並從數據源重發該快照之後的消息便可,固然這也要求數據輸出端持久化時支持冪等操做。

  1. 三個時間域

 

如上圖所示,Flink支持三個時間域:

a)    Event Time:事件時間

每一個數據都要攜帶一個時間戳,用於標記數據產生時間。

b)    Ingestion Time:攝取時間

數據被從消息隊列(好比Kafka),提取到Flink時的時間。

c)    Processing Time:處理時間

數據真正被處理時所在機器的時間。

    打個比方,筆者在網上訂了一本關於Flink的書(迄今沒有Flink相關的中文書籍出版),這本書的出版日期是Event Time,從快遞員手裏接過書的當天日期是Ingestion Time,真正看這本書的當天日期是Processing Time。

    通常的流計算系統進行數據處理時,都是基於Processing Time的,這相對來講比較簡單,即無論數據是什麼時間產生的,都以數據實際被處理時所在機器的時間爲準,這在計數類應用或者計時不敏感類應用中可能沒啥影響,可是若是要嚴格按照數據實際產生時間進行計算的計時類應用,則當數據亂序產生或者延遲到達時,計算結果將會截然不同,使人讚歎的是,Flink可以輕鬆應對上述三種時間域的計算。

  1. 四種窗口

時間域肯定了計算數據時的時間類型,而窗口則要肯定對多長時間內或多少個數據進行計算,Flink支持四種內置窗口:

a)    Tumbling Window:翻滾窗口、固定窗口

每一個窗口的大小是固定的(好比1分鐘),各個窗口內的數據互不重疊。

b)    Sliding Window:滑動窗口

每一個窗口由兩個時間構成,一個是窗口大小時間(好比1分鐘),一個是窗口滑動時間(好比30秒),各個窗口內數據有重疊,好比要每隔30秒統計過去1分鐘的數據。

c)    Session Window:會話窗口

用於標記一段用戶持續活躍的週期,由非活躍的間隙分隔開。各個窗口內數據互不重疊,沒有固定的開始時間和結束時間,當它在一個固定的時間週期內再也不收到數據,即非活動間隔產生,這個會話窗口就會關閉,後續的數據將被分配到新的窗口中去。

d)    Global Window:全局窗口

將全部具備相同Key的元素分配到同一個全局窗口中,該窗口模式僅適用於用戶還需自定義觸發器的狀況。

  1. Watermark:水位

流處理從事件產生,到最終輸出計算結果,中間有一個過程和時間,大部分狀況下,流數據都是按照事件產生的時間順序來的,但不排除因爲網絡、背壓等緣由,致使數據亂序或延遲到達,對於延遲數據,又不能無限期的等下去,必須有個機制來保證一個特定的時間後,觸發window去進行計算,這個機制就是Watermark。

Watermark是數據自己的一個隱藏屬性,一般基於Event Time的數據,自身都包含一個Timestamp,好比1320981071111(2011-11-11 11:11:11.111),則這條數據的Watermark時間多是:

Watermark(1320981071111)= 1320981068111(2011-11-11 11:11:08.111)

   即Timestamp小於1320981068111(2011-11-11 11:11:08.111)的數據,都已經到達了,能夠對窗口內數據進行計算了。

3、特來電監控引擎

 

 

上圖是特來電監控平臺總體架構圖,和通常的大數據分析處理流程相似,主要由如下幾部分組成:

  1. 數據採集

由部署在各個機器上的監控Agent組成,職責是收集監控數據。收集方式既支持業務經過程序埋點方式主動上報數據,也支持經過監控插件方式,由監控Agent定時主動拉取數據(如性能計數器數據、Windows日誌數據、網絡端口連通性數據、Kafka運行數據、RabbitMQ運行數據、Redis運行數據、關係數據庫運行數據、大數據組件運行數據等)。

  1. 數據輸入緩存(Source)

     基於開源的Kafka緩存監控上報的數據,Kafka是流計算的標配,能夠說「無Kafka,不流計算」,Kafka最近剛發佈了1.0版本,不管是穩定性,仍是性能方面,Kafka都是不可替代的消息隊列技術棧。

  1. 數據計算

監控引擎是監控平臺的核心組件,主要作兩件事:一是必定要基於監控數據的Event Time進行計算,並能處理亂序數據以及延遲到達數據;二是要對監控數據作各類維度的聚合計算。利用Flink,基於Event Time進行聚合計算,計算時間能夠控制在秒級,是計算密集型場景。

 

 如上所示,使用Flink進行計算時,能夠很容易設置計算數據的時間類型,針對監控數據,必須用Event Time,才能保證指定時間的數據都落在同一個窗口。

爲了應對數據亂序以及延遲,還須要設置水位,由於每一個監控數據自身都攜帶了數據產生的時間戳,因此設置起來也很天然:

 

 監控引擎核心功能在作各類維度的聚合計算,以下所示,若是一分鐘內上報的監控數據以下所示:

 

則進行維度計算時,主要有以下四種維度計算方式,分別計算出相應維度數據的最大值、最小值、平均值、最後值、求和值以及數據個數:

a)    所有數據維度

           將全部數據進行累加求值

b)    指定集羣維度

          將全部數據按不一樣集羣進行累加求值

c)    指定應用節點維度

 

            將全部數據按不一樣節點進行累加求值

d)    自定義維度

前面三種維度至關於固定維度,監控數據還支持用戶自定義維度,若是上報數據有自定義的維度,則將自定義維度Key以及Value取出後進行flatMap,和前面三種固定維度進行並列計算。

基於Flink進行聚合計算時,須要先根據監控元數據進行分組,而後計算指定時間窗口內的數據,以下所示:

 

 監控引擎運行時,能夠經過Flink的Job Graph,實時查看每一個Operator的執行鏈,以下所示:

 

 

  1. 數據輸出緩存(Sink)

監控數據進行聚合計算完畢後,不是當即持久化到存儲,仍是先Sink到Kafka,一是讓監控引擎工做更純粹,面對的Source和Sink都是Kafka;二是經過Kafka對數據落盤進行緩衝,減小直接寫存儲可能帶來的監控引擎阻塞,讓流計算更流暢,下降背壓的產生機率。

  1. 數據存儲

特來電監控平臺和其餘互聯網監控平臺最大的不一樣,也是特來電監控平臺最大亮點,是支持從計算後的聚合數據,鑽取聯查到監控Agent上報的原始數據,這要求既要存儲計算後的聚合數據,也要存儲原始數據,還要存儲聚合數據與原始數據的關聯關係。由於監控數據最大的特色是時間相關性的,所以使用時間序列數據庫InfluxDB存儲計算後的聚合數據,使用HBase存儲原始數據以及原始數據與聚合數據的關聯關係。

  1. 數據展示

監控數據最終經過Grafana進行展示,能夠實時監控雲平臺系統層面以及業務層面的運行狀態,爲故障檢測、診斷及定位打下了堅實基礎。如前所述,經過Grafana不只能夠查看存儲在InfluxDB中計算完畢的聚合數據,還能夠經過Grafana鑽取功能,聯查到存在HBase中的原始數據。

4、技術不止、坑坑不息

技術研究、探索以及應用,老是會伴隨着不少坑,踩坑填坑的過程,就是技術積累的過程,技術人要感謝這些坑,由於它們加深了對技術的認識。

1. 時間戳與Decimal

因爲監控Agent是基於C#開發的,監控引擎是基於Scala開發的,DateTime做爲C#中內置的數據類型,在Scala中沒有可直接對應的數據類型。考慮到監控Agent上報到Kafka中的數據是Protobuf格式,所以須要根據C#中DateTime對應的.proto文件,生成對應的Java代碼,而後在Scala中反序列化時,調用Protobuf時間類,轉換成可識別的時間戳。

另外一個在跨語言時沒有直接對應的數據類型是C#中的Decimal,處理方式和DateTime相似,也是須要定義中間轉換的.proto文件,生成對應語言的類,反序列化時進行調用處理便可。

【注】在處理Protobuf類時,專業的作法是隻定義.proto文件,使用gRPC插件動態生成對應的Java類。

2. 從Spark Streaming到Flink

特來電監控引擎的前一版本是基於Spark Streaming實現的,可是在解決亂序數據及延遲到達數據時,遇到了很大的技術障礙,由於Spark Streaming是根據Processing Time進行計算的,若是要基於Event Time進行計算,技術實現難度很大,前後嘗試過Alluxio、Ignite、Structured Streaming,都沒能很好解決該問題。直到嘗試使用Flink,發現這是其內置特性,能夠輕鬆解決之前遇到的問題,後面便果斷放棄Spark Streaming,堅決選擇Flink做爲監控引擎的實現工具。

3. 其餘常常會遇到的坑還有:應用程序使用的jar包,比Flink自身提供的jar包新,能夠經過maven-shade-plugin進行打包;查看Flink的Job Graph時,須要使用Chrome瀏覽器,微軟的IE瀏覽器無法顯示完整執行鏈;Map做爲Protobuf中的特殊集合,不能被Flink直接序列化,須要自定義序列化類或者將類封裝後,實現Serializable Trait;Checkponit時間不要設置的過短,不然會致使頻繁建立快照;生產環境不要把執行鏈斷開,不然會有一些性能問題等等。

5、All In Flink

筆者認爲,「老當益壯」的Flink做爲「新一代」冉冉升起的真正流計算引擎,將會長期與Spark並駕齊驅,並逐步擴大其應用範圍。咱們也會將其逐步應用到實時預警、實時全鏈路分析、風控管理、用戶行爲分析,並逐步探索基於Flink的機器學習、監控數據突變分析,但願能在監控預警方面取得進一步突破,爲雲平臺的穩定運行保駕護航。

6、特來電雲計算與大數據微信公衆號

 1.微信公衆號名稱:特來電雲計算與大數據

 2.二維碼:

 

相關文章
相關標籤/搜索