IT系統監控的規則引擎-CEP

CEP簡介

CEP全稱爲 Complex Event Processing 復瑣事件處理,其能夠經過在流式數據中發現符合某種特徵的模式進而觸發對應的後續動做,其既支持基於單條事件的簡單無狀態的模式匹配(例如基於事件中的某個字段進行篩選過濾),也能夠支持基於關聯/聚合/時間窗口等跨事件的複雜有狀態模式匹配(例如計算滑動時間窗口移動均值)。受益於其直接做用於流式數據,無需查詢持久化數據庫,對底層數據庫不會產生任何壓力,以及其強大的模式發現能力,在監控系統中,若是把CEP與流處理引擎結合,在IT運維管理中,能夠大大加強告警的實時性以及適用範圍。git

CEP對IT運維的價值

傳統的ITOM主要對底層的軟硬件基礎架構對單一指標基於靜態的閾值進行監控告警,這裏有兩個關鍵詞:基礎架構 以及 單一, 這其實正好對應了傳統IT監控的兩大痛點。單一致使的結果就是誤報,服務器的CPU利用率上升有時是由於交易量的上升帶來的正常現象,只要在合理區間內就無需告警,可是CPU利用率的孤立上升就多是由於代碼缺陷形成的,有經驗的工程師一眼就能看出是不是故障,是由於工程師在一瞬間就綜合分析了各個相關指標。針對基礎架構則讓運維人員的生活很是苦逼,有功勞都是其餘部門的,出了故障都是運維的兄弟在頂包,因此近些年來基本上全部的企業都在作APM,經過網絡抓包或者日誌埋點等方式能夠提取交易成功率/交易量/成功率等反映業務性能的指標,作了很多漂亮工程,不過不論是交易量仍是成功率都仍是從系統的角度去看問題,真正能帶來多少業務價值其實也很難說,大屏上那些五光十色的圖表可能更多時候也是在領導檢查或者參觀時才體現其價值。從數據來看,其實IT運維過程當中的數據是最完整的,既有包含了服務器,網絡設備等基礎設施的底層運行信息,也有包含中間件和數據庫的中間層系統信息,還有包含了所有業務過程的上層應用日誌信息,在這個數據時代,IT運維正在向IT運營轉變,理應可以發揮更大的業務價值,舉例對於一個金融企業,若是能從應用日誌中提取到同一個帳戶在1分鐘內在距離50千米的兩地櫃員機取款的類欺詐信息來支持風控,IT運維所承擔的就不僅是保障做用,而是直接參與到了業務決策過程中。雖然CEP不是爲IT運維管理而生,可是在必定程度上CEP確實能夠解決上述兩個問題,CEP最強大的就是其模式匹配引擎,其不只能夠做用於不一樣類型的事件,更能夠按照時間窗口,發生順序和次數以及其餘狀態聚合結果進行模式匹配,能夠和各類業務規則進行對應。另外CEP是直接做用於流式數據,而非經過按期查詢數據庫的方式,所以最實時,且對數據庫沒有任何壓力。目前的Flink流引擎已經自帶了CEP模塊,Flink官方給出的CEP例子正好就是針對數據中心監控的場景,案例中須要對Rack的溫度進行監控,對於同一個Rack,當10秒內連續兩次溫度超過溫度閾值時預警,當20秒內產生連續兩個預警,且第二次預警溫度高於第一次時進行告警,該模式中有不一樣狀態的切換,有時間窗口的滑動等,若是沒有CEP,須要自行構建對應的狀態機進行處理,可是基於CEP強大的模式挖掘能力之上的實現很是簡單,因而可知CEP的威力。不過Flink中的CEP模塊是與其流失API緊密結合的,若是咱們的前置流引擎不是Flink,則沒法直接使用。咱們在構建智能化監控系統時,從性能方面去考慮,在流引擎與CEP之間添加了基於AKKA的多層路由模塊,能夠按照業務系統,服務器,實例以及指標級別進行消息的路由,CEP引擎內嵌在每一個Actor內部,能夠在不一樣的路由級別對不一樣範圍的消息進行模式匹配。下圖是對應的架構圖。 監控系統的架構以及對應實現不在咱們這篇文章範圍以內,本文接下來介紹下如何使用CEP來完成一個複雜監控告警從生成到關閉的過程。github

圖片描述

CEP做爲監控告警的規則引擎

本文中使用了一個開源的CEP組件esper(https://github.com/espertechinc/esper),目前該組件已經被weblogic等中間件廠商集成到本身的日誌異常檢測功能中,其自己是一個JAR庫,無需其餘運行時框架,因此使用起來很是方便。其支持一種DSL語言EPL,與SQL相似,用戶經過輸入不一樣的EPL來定義不一樣的匹配模式。本文不包含基本的EPL語法介紹,有興趣的同窗能夠移步這裏(http://blog.csdn.net/luonanqin/article/details/21300263) 以及esper的官網(http://www.espertech.com/esper/)。本文主要從一個實際的監控需求案例出發,來介紹esper的相關功能。web

監控告警需求

監控原始事件定義以下:數據庫

//name表明監控指標的名稱,例如CPU.CPUUtil

//timestamp指某一個具體的時間點

//value表明在timestamp時間點的指標值

//tags裏面存儲了一些其餘描述信息,例如服務器名,ip地址,所屬業務系統等等

case class GenericMetric(timestamp:Long, name:String, value:Any, tags:Map[String, Any])

//timestamp表明Warning產生的時間點

//name表明指標名稱

//value表明產生Warning前最後一個事件的值

case class Warning(timestamp:Long, name:String, value:Any, tags:Map[String, Any])
//timestamp表明關閉事件產生的時間點

//name表明指標名稱

case class Close(timestamp:Long, name:String)
//timestamp表明Critical產生的時間點

//name表明指標名稱

//value表明產生Critical前最後一個事件的值

case class Critical(timestamp:Long, name:String, value:Any, tags:Map[String, Any])
告警規則1

當value連續10次 >= 0.5,< 0.8時產生Warning級別的告警,當value連續10次 >= 0.8時產生Critical級別的告警。服務器

當產生Warning級別的告警後,當出現不在 >= 0.5 < 0.8區間的事件數據時,產生Close事件把Warning告警關閉。網絡

當產生Critical級別的告警後,當出現不在 < 0.8區間的事件數據時,產生Close事件把Critical告警關閉。架構

Warning create epl:框架

insert into Warn select (select value from GenericMetric.std:lastevent()) as value, (select name from GenericMetric.std:lastevent()) as name, (select tags from GenericMetric.std:lastevent()) as tags,current_timestamp as timestamp from pattern[ every [10] (GenericMetric(value >= 0.5 and value < 0.8) and not GenericMetric(value < 0.5 or value >= 0.8))]運維

Critical create epl:分佈式

insert into Critical select (select value from GenericMetric.std:lastevent()) as value, (select name from GenericMetric.std:lastevent()) as name, (select tags from GenericMetric.std:lastevent()) as tags, current_timestamp as timestamp from pattern[ every [10] (GenericMetric(value >= 0.8) and not GenericMetric(value < 0.8))]

Warn close epl:

insert into Close select (select name from GenericMetric.std:lastevent()) as name,current_timestamp as timestamp from pattern [every [1] (Warn -> (GenericMetric(value < 0.5 or value >= 0.8)))]

Critical close epl:

insert into Close select (select name from GenericMetric.std:lastevent()) as name,current_timestamp as timestamp from pattern [every [1] (Critical -> (GenericMetric(value < 0.8)))]

告警規則2

當value連續10次 >= 0.5,< 0.8時產生Warning級別的告警,當value連續10次 >= 0.8時產生Critical級別的告警。

當產生Warning級別的告警後,當連續出現10次< 0.5的事件數據時,產生Close事件把Warning告警關閉。

當產生Critical級別的告警後,當連續出現10次 < 0.8區間的事件數據時,產生Close事件把Critical告警關閉。

告警的生成規則和規則1是相同的,這裏就再也不重複給出,須要關注的是關閉的規則與以前不一樣:

Warn close epl:

insert into Close select (select name from GenericMetric.std:lastevent()) as name,current_timestamp as timestamp from pattern [every [1] (Warn -> every [10](GenericMetric(value < 0.5)))]

Critical close epl:

insert into Close select (select name from GenericMetric.std:lastevent()) as name,current_timestamp as timestamp from pattern [every [1] (Critical -> every [10](GenericMetric(value < 0.8)))]

告警規則3

當value連續1分鐘 >= 0.5,< 0.8時產生Warning級別的告警,當value連續1分鐘 >= 0.8時產生Critical級別的告警。

當產生Warning級別的告警後,當連續出現1分鐘< 0.5的事件數據時,產生Close事件把Warning告警關閉。

當產生Critical級別的告警後,當連續出現1分鐘 < 0.8區間的事件數據時,產生Close事件把Critical告警關閉。

Warn create epl:

insert into Warn select (select value from GenericMetric.std:lastevent()) as value, (select name from GenericMetric.std:lastevent()) as name, (select tags from GenericMetric.std:lastevent()) as tags,current_timestamp as timestamp from pattern[ every (GenericMetric(value >= 0.5 and value < 0.8) -> ( timer:interval(60 sec) and not GenericMetric(value < 0.5 or value >= 0.8)))]

Critical create epl:

insert into Critical select (select value from GenericMetric.std:lastevent()) as value, (select name from GenericMetric.std:lastevent()) as name, (select tags from GenericMetric.std:lastevent()) as tags,current_timestamp as timestamp from pattern[ every (GenericMetric(value >= 0.8) -> ( timer:interval(60 sec) and not GenericMetric(value < 0.8)))]

Warn close epl:

insert into Close select (select name from GenericMetric.std:lastevent()) as name,current_timestamp as timestamp from pattern [every (Warn -> ( timer:interval(60 sec) and GenericMetric(value < 0.5) and not GenericMetric(value >= 0.5)))]

Critical close epl:

insert into Close select (select name from GenericMetric.std:lastevent()) as name,current_timestamp as timestamp from pattern [every (Critical -> ( timer:interval(60 sec) and GenericMetric(value < 0.8) and not GenericMetric(value >= 0.8)))]

若是 沒有CEP,要實現上述告警規則須要構建狀態機,以及對狀態跳轉過程當中的歷史數據的記錄,實現起來比較複雜,可是基於esper,對應每一個規則只是一句簡單的EPL,並且多個規則能夠同時起做用,代碼可讀性以及擴展性都比構建狀態機要好不少。

小結

本篇是從基礎架構監控的層面來介紹了CEP,固然CEP更強大的功能是對結構化後的日誌數據進行模式匹配,與複雜的業務規則進行對應,發揮更大的業務價值,後續的CEP系列文章裏面會更多從日誌數據挖掘的方面去作相關介紹。此外,基於AKKA構建分佈式的監控告警系統也是一個頗有意思的主題,充分利用了actor的輕量級優點,經過建立百萬甚至千萬級別的actor與各指標進行對應,充分利用了服務器的計算資源,在相對普通的服務器集羣上能夠支撐海量的指標實時有狀態監控,後續也會單獨進行介紹。

相關文章
相關標籤/搜索