基礎監控-同比告警

来源:http://www.cnblogs.com/lxmhhy/archive/2016/11/21/6084998.html
-Advertisement-
Play Games

基礎監控的同比告警主要是針對伺服器監控採集的指標,包括負載(load1/load5/load15)、平均CPU使用率、記憶體使用率、內外網流量、埠數量等,具體採集方法可參考《基礎監控-伺服器監控》。 一、告警原理 多個指標每分鐘1個數據,比較當前分鐘的前10分鐘的7天平均值,如果幅度超過100%並且 ...


  基礎監控的同比告警主要是針對伺服器監控採集的指標,包括負載(load1/load5/load15)、平均CPU使用率、記憶體使用率、內外網流量、埠數量等,具體採集方法可參考《基礎監控-伺服器監控》。

一、告警原理

  多個指標每分鐘1個數據,比較當前分鐘的前10分鐘的7天平均值,如果幅度超過100%並且絕對值相差達到M則算是一次異常,包括上升/下降異常,如果一個指標持續兩次上升異常或者持續兩次下降異常(不包括先上升後下降或者先下降後上升情況)則開始告警給機器的對應負責人(運維/開發)。例如當前是10號11:00,則比較的是10:59,10:58...10:50共10分鐘的最近7天的平均值,例如10:59則是10號、9、8...4共7天的10:59這個點的數據的平均值。實際情況一般是第二分鐘才解析了前一分鐘的數據,相當於當前是11點,則解析的是10:59這個點和它之前的10分鐘的7天平均值的比較。

二、數據來源

  基礎監控-伺服器監控每分鐘會採集一份數據保存到Redis中,保存格式是 reportTime - hash,hash的格式是{ip1:{item1:value, item2:value2...}, ip2:{item1:value, item2:value2...}, ip3...},則每分鐘一個redis hash,共7天 7*1440=10080個數據。實際情況保存的時候會多保留10分鐘的數據,即7天+10分鐘;由於reportTime是根據機器的實際時間來上報(這樣畫圖才能保證是準確的),而某些機器沒有NTP伺服器或者其他原因導致時間不准,則reportTime則又會多種多樣,所以導致的結果是redis的hash會變多一些,當然這並不影響我們的數據獲取,因為整個同比告警就是根據畫圖來比較的,畫圖採用的是reportTime。採用hash保存到redis則不用每個ip讀取一次redis,可以減少N次網路IO,大大提高程式速度。由於redis占據記憶體較多,大概10G左右,需要調整redis配置文件maxmemory的大小,不然redis會隨機刪除設置自動過期的key。

三、程式設計

1、DB設計

需要數據來源保存(redis)、異常展示表(mysql)、閾值配置表(mysql)、上次狀態(redis)。異常展示表保存所有ip的異常描述信息、異常持續時間,可在頁面展示;閾值配置表保存所有ip的閾值配置信息,每個ip的異常比率、各個指標的絕對值差、是否需要監控等;上次狀態則用來判斷是否需要告警的,持續2次同類異常則告警,使用redis保存即可。

mysql> show tables;
+-----------------------------------+
| Tables_in_machineMonitor_overLast |
+-----------------------------------+
| currentDisplay                    |
| monitorConf                       |
+-----------------------------------+

2、導入測試數據

測試數據是使用mysql和redis將數據從mysql導入redis中,線上數據是等程式完成後修改"伺服器監控"的上報CGI來導入的。測試導入的時候遇到的坑參考《python處理json和redis hash的坑

def initRedis(client):
    if client not in CONF.redisInfo:
        raise RedisNotFound("can not found redis %s in config" % client)
    try:
        pool = redis.ConnectionPool(**CONF.redisInfo[client])  # 線程安全
        red = redis.Redis(connection_pool=pool)
        red.randomkey()  # check
    except Exception, e:
        raise RedisException("connect redis %s failed: %s" % (client, str(e)))
    return red


def initDb(client):
    if client not in CONF.dbInfo:
        raise MysqlNotFound("can not found mysql db %s in config" % client)
    try:
        db = opMysql.OP_MYSQL(**CONF.dbInfo[client])
    except Exception, e:
        raise MysqlException("connect mysql %s failed: %s" % (client, str(e)))
    code, errMsg = db.connect()
    if 0 != code:
        raise MysqlException("connect mysql %s failed: %s" % (client, errMsg))
    return db

3、告警介面

調用"告警平臺"介面,項目配置後可發送RTX/SMS/Wechat,可在頁面查看歷史記錄,輕鬆修改配置和臨時屏蔽等。調用介面直接使用urllib/urllib2庫即可

postData = urllib.urlencode(values)
req = urllib2.Request(CONF.amcUrl, postData)
response = urllib2.urlopen(req, timeout=CONF.AMC_TIME_OUT)
amcDict = json.loads(response.read())
code = int(amcDict["returnCode"])
errMsg = amcDict["errorMsg"]

4、解析來源的數據

將數據轉成可識別字典,並做排錯處理,將錯誤數據拒絕掉

5、使用numpy和panda求平均值

將來源數據解析後存入panda.DataFrame中,如果數據不存在則使用numpy.nan代替,使用panda.DataFrame().mean().round(2)求平均值並保留2位數。如果某一分鐘的7天數據全部獲取不到則拒絕解析當前值,如果是7天數據的部分數據獲取不到則剔除該點併在平均值的除數相對減一,使用NAN代替該點則在mean中可以解決這種情況。增加自定義函數比較每個列是否滿足幅度上升/下降100%(可配置)並且絕對值差達到M(可配置),是則返回True,否則返回False,判斷所有返回值是否均為True或者均為False,是則符合異常場景。

初始化DataFrame

for item in vd:
    if value is None or value[item] is None:
        vd[item][lastDayKey] = numpy.nan
    else:
        vd[item][lastDayKey] = value[item]           
vf = pandas.DataFrame(vd)
            
columns.append(vf.mean().round(2))  
indexes.append(lastMinKey)   

self.ipInfo[ip]["lastData"] = pandas.DataFrame(columns, index=indexes)

panda自定義函數比較並且判斷是否需要告警

for item in curValue:
    if curValue[item] is None:  # error
        continue
    else:
        curValue[item] = round(curValue[item], 2)
    
        def overLastCompute(v2, absSub):
            """
            :param v2: float  
            :param absSub: absolute subtract 
            :return: high/low/null
            """
            v1 = curValue[item]
            v2 = round(v2, 2)
            if 0 == v2:
                if v1 > absSub:
                    return "HIGH"
                if v1 < -absSub:
                    return "LOW"
                return "NULL"
            subVal = abs(v1 - v2)
            if subVal / v2 > CONF.RATIO and subVal > absSub:
                if v1 > v2:
                    return "HIGH"
                return "LOW"
            return "NULL"
        self.ipInfo[ip]["result"][item] = self.ipInfo[ip]["lastData"][item].apply(overLastCompute, absSub=self.monitorConf[ip][item])
        res = self.ipInfo[ip]["result"][item] == "HIGH"  # Series
        if all(i for i in res):
            resErr[item] = CONF.HIGH_ERR
            if CONF.HIGH_ERR == self.lastCache[str(ip)][item]:
                # will  Alert if switch on 
                pass
        else:
            res = self.ipInfo[ip]["result"][item] == "LOW"
            if all(i for i in res):
                resErr[item] = CONF.LOW_ERR
                if CONF.LOW_ERR == self.lastCache[str(ip)][item]:
                    # will  Alert if switch on 
                    pass

6、由於IP較多,並且主要邏輯在解析數據和panda的計算上,使用CPU比較多,則需要使用多進程,並且結合線程池將進程跑滿,別浪費進程資源。

step = ipNums / multiprocessing.cpu_count()
ipList = list()
i = 0
j = 1
processList = list()

for ip in self.ipInfo:
    ipS = str(ip)
    if ipS not in self.lastCache:
        self.lastCache[ipS] = copy.deepcopy(self.value)
    ipList.append(ip)
    i += 1
    if i == step * j or i == ipNums:
        j += 1

        def innerRun():
            wm = Pool.ThreadPool(CONF.POOL_SIZE)
            for myIp in ipList:
                kw = dict(ip=myIp, handlerKey=myIp)
                wm.addJob(self.handleOne, **kw)
            wm.waitForComplete()
            ipListNums = len(ipList)
            for tmp in xrange(ipListNums):
                res = wm.getResult()
                if res:
                    handlerKey, code, handlerRet, errMsg = res
                    if 0 != code:
                        continue
                    self.lastCache[str(handlerKey)] = handlerRet
        process = multiprocessing.Process(target=innerRun)
        process.start()
        processList.append(process)
        ipList = list()

for process in processList:
    process.join()

四、優化

指標監控v2則是同比告警的升級版,數據量將會大好幾倍,目前想到的優化如下

1、使用hbase替代redis

2、將程式做京廣容災,改成分散式運行,橫向擴展多套程式併列運行

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. 索引(Index) 索引是快速的定位和查找數據。索引分為: 聚集索引:唯一,預設主鍵,一般選取比較連貫的欄位,聚集索引是物理排序。 非聚集索引: 並沒有把數據物理排序,只是多了一個索引頁(包括索引項+存儲位置row number) a. 新建“非聚集索引” b. 選擇“專業”創建非聚集性索引。 ...
  • Hey,大家好!我是CrazyCatJack。今天我來說幾個在嵌入式開發中常用的C語言技巧吧。也許你曾經用過,也許你只是見到過但是沒有深入理解。那麼今天好好補充下吧^_^ 1.指向函數的指針 指針不光能指向變數、字元串、數組,還能夠指向函數。在C語言中允許將函數的入口地址賦值給指針。這樣就可以通過指 ...
  • 轉自:http://www.cnblogs.com/phoebus0501/archive/2010/12/14/1906144.html 1.確保RHEL5中已經安裝了yum [root@lvs-master ~]# rpm -qa |grep yumyum-metadata-parser-1.1 ...
  • 操作系統API: 1、API是一些函數,這些函數是由linux系統提供支持的,由應用層程式來使用,應用層程式通過調用API來調用操作系統中的各種功能,來幹活 文件操作的一般步驟: 1、在linux系統中要操作一個文件,一般是先open打開一個文件,得到一個文件描述符,然後對文件進行讀寫操作(或其他操 ...
  • 前言 日常用Python多一些,不過很多時候shell腳本更簡單實用一些,所以有必要熟悉一下shell腳本。當然shell有他特定的一些場景,比方說我曾經改過一個vpn斷線自動重連的 "腳本" ,簡單實用。 另: 本文比較簡單,算是入門簡述,類似於30分鐘入門的東西,想詳細看的可以去搜其他文章,很多 ...
  • 設置 NLS_LANG 變數 1) 正確配置 LC_ALL 參數 2) 配置 telnet/ssh/SecureCRT 客戶端的字元集 linux中可以用locale命令來查看 NLS_LANG設置,如下例所示 [root@HXZG ~]# locale LANG=en_US.UTF-8 LC_CT ...
  • #Elaine:master;Dylan:minion#利用salt給minion安裝包[root@elaine states]# vim /etc/salt/master 1 default_include: master.d/*.conf 2 3 interface: 0.0.0.0 4 5 ' ...
  • InfluxDB每秒可以處理成千上萬條數據,要將這些數據全部保存下來會占用大量的存儲空間,有時我們可能並不需要將所有歷史數據進行存儲,因此,InfluxDB推出了數據保留策略(Retention Policies),用來讓我們自定義數據的保留時間。更多InfluxDB詳細教程請看:InfluxDB系 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...