實時告警架構優化實戰

簡介

線上有一個告警服務採用sparkstreaming+kafka的模式實時處理數據進行布控告警,10s一個批次,34個executor,每個4core,kafka有260個分區,採用直讀的方式並且打開了慢執行推測。

運行一段時間後,都沒有延遲,目前布控任務有1000個左右,每天4000萬的數據需要處理,昨晚業務突然添加了2000個布控任務,導致任務有積壓,導致告警延遲兩個多小時,經過排查,發現慢在獲取mpp的布控任務。

原處理流程

                                                    

通過上述流程圖可以看出,每個task都需要獲取一個mpp的布控任務,因爲布控任務會被更新,所以每次處理數據的時候都需要全量獲取布控任務,這樣每一個批次,會有260個task,就需要讀取mpp260次,這肯定慢啊。寫代碼的小兄弟說,這個不這樣搞,那每個executor怎麼獲取布控任務,我說:用廣播變量啊,小兄弟說:我這布控任務是動態變化的啊,你這廣播變量是靜態不變的,,,,,,

如果spark這麼呆,估計早死了,我們其實可以動態的更新廣播變量,衆所周知,廣播變量是driver端獨有的,executor只有只讀權限,所以每次只能在driver端更新,所以原流程發現了兩個問題,均在生產環境遇到:

問題一:爲了更新布控信息,每個批次,每個task都讀取一遍mpp,一個批次讀取260,導致mpp壓力很大

解決方案:spark爲分佈式而生,分佈式協調是基本功,採用dirver端讀取定時更新布控信息,動態廣播變量,這樣每個executor都可以通過rpc獲取布控信息。

問題二:告警服務強依賴mpp,在mpp異常,或者cpu高的情況下,會阻塞告警,導致告警延遲

解決方案:採用緩存的機制,在dirver端採取內存緩存,一分鐘定時更新,可以設置jdbc查詢超時爲10s,如果遇到mpp異常,查詢不到數據的情況下,繼續使用上次的緩存信息,類似cap理論,在分佈式容錯的場景下嗎,保持服務可用,犧牲數據一致性。

優化後處理流程

                                                  

// 動態廣播變量代碼

JavaInputDStream<ConsumerRecord<String, String>> stream = KafkaUtils.createDirectStream(jssc, locationStrategy,
                consumerStrategy);

        stream.foreachRDD(rdd -> {
            // 獲取offset
            OffsetRange[] offsetRanges = ((HasOffsetRanges) rdd.rdd()).offsetRanges();
            // 設置廣播變量
            final Broadcast<List<ShinyDisposition>> instance = rdd.context().broadcast(QueryDataUtil.queryShinyDisposition(), ClassManifestFactory.classType(List.class));
            List<ShinyDisposition> ShinyDispositionList = instance.value();
            rdd.foreachPartition(new VoidFunction<Iterator<ConsumerRecord<String, String>>>() {
                public void call(Iterator consumerRecordIterator) throws Exception {
                //業務邏輯    
                
                }
            });
            // offset更新
            ((CanCommitOffsets) stream.inputDStream()).commitAsync(offsetRanges);
            // 廣播更新
            instance.unpersist(true);
        });
 

QueryDataUtil.queryShinyDisposition()方法獲取mpp的數據,一分鐘更新一次內存緩存。

補充知識點

foreachRDD、foreachPartition和foreach的不同之處主要在於它們的作用範圍不同,foreachRDD作用於DStream中每一個時間間隔的RDD,foreachPartition作用於每一個時間間隔的RDD中的每一個partition,foreach作用於每一個時間間隔的RDD中的每一個元素。

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