5. 報警系統(tǒng)QuickAlarm之頻率統(tǒng)計及接口封裝

報警系統(tǒng)QuickAlarm之頻率統(tǒng)計及接口封裝

前面將報警規(guī)則的制定加載解析牵署,以及報警執(zhí)行器的定義加載和擴(kuò)展進(jìn)行了講解,基本上核心的內(nèi)容已經(jīng)完結(jié),接下來剩下內(nèi)容就比較簡單了

  • 報警頻率的統(tǒng)計
  • 報警線程池
  • 對外封裝統(tǒng)一可用的解耦

I. 報警頻率統(tǒng)計

1. 設(shè)計

前面在解析報警規(guī)則時,就有一個count參數(shù)悬而,用來確定具體選擇什么報警執(zhí)行器的核心參數(shù),我們維護(hù)的方法也比較簡單:

  • 針對報警類型锭汛,進(jìn)行計數(shù)統(tǒng)計笨奠,沒調(diào)用一次,則計數(shù)+1
  • 每分鐘清零一次

2. 實(shí)現(xiàn)

因?yàn)槊糠N報警類型唤殴,都維護(hù)一個獨(dú)立的計數(shù)器

定義一個map來存儲對應(yīng)關(guān)系

private ConcurrentHashMap<String, AtomicInteger> alarmCountMap;

每分鐘執(zhí)行一次清零

// 每分鐘清零一把報警計數(shù)
ScheduledExecutorService scheduleExecutorService = Executors.newScheduledThreadPool(1);
scheduleExecutorService.scheduleAtFixedRate(() -> {
    for (Map.Entry<String, AtomicInteger> entry : alarmCountMap.entrySet()) {
        entry.getValue().set(0);
    }
}, 0, 1, TimeUnit.MINUTES);

注意上面的實(shí)現(xiàn)般婆,就有什么問題?

有沒有可能因?yàn)閙ap中的數(shù)據(jù)過大(或者gc什么原因)朵逝,導(dǎo)致每次清零花不少的時間蔚袍,而導(dǎo)致計數(shù)不準(zhǔn)呢? (先不給出回答)

計數(shù)加1操作

/**
 * 線程安全的獲取報警總數(shù) 并自動加1
 *
 * @param key
 * @return
 */
private int getAlarmCount(String key) {
    if (!alarmCountMap.containsKey(key)) {
        synchronized (this) {
            if (!alarmCountMap.containsKey(key)) {
                alarmCountMap.put(key, new AtomicInteger(0));
            }
        }
    }

    return alarmCountMap.get(key).addAndGet(1);
}

II. 報警線程池

目前也只是提供了一個非常簡單的線程池實(shí)現(xiàn)配名,后面的考慮是抽象一個基于forkjoin的并發(fā)框架來處理(主要是最近接觸到一個大神基于forkjoin寫的并發(fā)器組件挺厲害的啤咽,所以等我研究透了,山寨一個)

// 報警線程池
private ExecutorService alarmExecutorService = new ThreadPoolExecutor(3, 5, 60,
        TimeUnit.SECONDS,
        new LinkedBlockingDeque<>(10), 
        new DefaultThreadFactory("sms-sender"),
        new ThreadPoolExecutor.CallerRunsPolicy());

任務(wù)提交執(zhí)行

private void doSend(final ExecuteHelper executeHelper, 
  final AlarmContent alarmContent) {
    alarmExecutorService.execute(() ->
      executeHelper.getIExecute().sendMsg(
        executeHelper.getUsers(), 
        alarmContent.getTitle(), 
        alarmContent.getContent()));
}

III. 接口封裝

這個就沒什么好說的了

public void sendMsg(String key, String content) {
    sendMsg(new AlarmContent(key, null, content));
}


public void sendMsg(String key, String title, String content) {
    sendMsg(new AlarmContent(key, title, content));
}

/**
 * 1. 獲取報警的配置項(xiàng)
 * 2. 獲取當(dāng)前報警的次數(shù)
 * 3. 選擇適當(dāng)?shù)膱缶愋? * 4. 執(zhí)行報警
 * 5. 報警次數(shù)+1
 *
 * @param alarmContent
 */
private void sendMsg(AlarmContent alarmContent) {
    try {
        // get alarm config
        AlarmConfig alarmConfig = confLoader.getAlarmConfig(alarmContent.key);

        // get alarm count
        int count = getAlarmCount(alarmContent.key);
        alarmContent.setCount(count);


        ExecuteHelper executeHelper;
        if (confLoader.alarmEnable()) { // get alarm execute
            executeHelper = AlarmExecuteSelector.getExecute(alarmConfig, count);
        } else {  // 報警關(guān)閉, 則走空報警流程, 將報警信息寫入日志文件
            executeHelper = AlarmExecuteSelector.getDefaultExecute();
        }


        // do send msg
        doSend(executeHelper, alarmContent);
    } catch (Exception e) {
        logger.error("AlarmWrapper.sendMsg error! content:{}, e:{}", alarmContent, e);
    }
}

接口封裝完畢之后如何使用呢渠脉?

我們使用單例模式封裝了唯一對外使用的類AlarmWrapper宇整,使用起來也比較簡單,下面就是一個測試case

@Test
public void sendMsg() throws InterruptedException {
    String key = "NPE";
    String title = "NPE異常";
    String msg = "出現(xiàn)NPE異常了!!!";

    AlarmWrapper.getInstance().sendMsg(key, title, msg);  // 微信報警

    // 不存在異常配置類型, 采用默認(rèn)報警, 次數(shù)較小, 則直接部署出
    AlarmWrapper.getInstance().sendMsg("zzz", "不存在xxx異常配置", "報警嗒嗒嗒嗒");
    
    Thread.sleep(1000);
}

使用起來比較簡單芋膘,就那么一行即可鳞青,從這個使用也可以知道霸饲,整個初始化,就是在這個對象首次被訪問時進(jìn)行

構(gòu)造函數(shù)內(nèi)容如下:

private AlarmWrapper() {
  // 記錄每種異常的報警數(shù)
  alarmCountMap = new ConcurrentHashMap<>();

  // 加載報警配置信息
  confLoader = ConfLoaderFactory.loader();

  // 初始化線程池
  initExecutorService();
}

所有如果你希望在自己的應(yīng)用使用之前就加載好所有的配置臂拓,不妨提前執(zhí)行一下 AlarmWrapper.getInstance()

IV. 小結(jié)

基于此厚脉,整個系統(tǒng)設(shè)計基本上完成,當(dāng)然代碼層面也ok了埃儿,剩下的就是使用手冊了

再看一下我們的整個邏輯器仗,基本上就是下面這個流程了

IMAGE
  1. 提交報警
  • 封裝報警內(nèi)容(報警類型融涣,報警主題童番,報警內(nèi)容)
  • 維護(hù)報警計數(shù)(每分鐘計數(shù)清零,每個報警類型對應(yīng)一個報警計數(shù))
  1. 選擇報警
  • 根據(jù)報警類型選擇報警規(guī)則
  • 根據(jù)報警規(guī)則威鹿,和當(dāng)前報警頻率選擇報警執(zhí)行器
    • 若不開啟區(qū)間映射剃斧,則返回默認(rèn)執(zhí)行器
    • 否則遍歷所有執(zhí)行器的報警頻率區(qū)間,選擇匹配的報警規(guī)則
  1. 執(zhí)行報警
  • 封裝報警任務(wù)忽你,提交線程池
  • 報警執(zhí)行器內(nèi)部實(shí)現(xiàn)具體報警邏輯

V. 其他

相關(guān)博文

  1. 報警系統(tǒng)QuickAlarm總綱
  2. 報警系統(tǒng)QuickAlarm之報警執(zhí)行器的設(shè)計與實(shí)現(xiàn)
  3. 報警系統(tǒng)QuickAlarm之報警規(guī)則的設(shè)定與加載
  4. 報警系統(tǒng)QuickAlarm之報警規(guī)則解析
  5. 報警系統(tǒng)QuickAlarm之頻率統(tǒng)計及接口封裝
  6. 報警系統(tǒng)QuickAlarm使用手冊

項(xiàng)目: QuickAlarm

個人博客: Z+|blog

基于hexo + github pages搭建的個人博客幼东,記錄所有學(xué)習(xí)和工作中的博文,歡迎大家前去逛逛

聲明

盡信書則不如科雳,已上內(nèi)容根蟹,純屬一家之言,因本人能力一般糟秘,見識有限简逮,如發(fā)現(xiàn)bug或者有更好的建議,隨時歡迎批評指正尿赚,我的微博地址: 小灰灰Blog

掃描關(guān)注

QrCode
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末散庶,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子凌净,更是在濱河造成了極大的恐慌悲龟,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冰寻,死亡現(xiàn)場離奇詭異须教,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)斩芭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進(jìn)店門轻腺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人秒旋,你說我怎么就攤上這事约计。” “怎么了迁筛?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵煤蚌,是天一觀的道長耕挨。 經(jīng)常有香客問我,道長尉桩,這世上最難降的妖魔是什么筒占? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮蜘犁,結(jié)果婚禮上翰苫,老公的妹妹穿的比我還像新娘。我一直安慰自己这橙,他們只是感情好奏窑,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著屈扎,像睡著了一般埃唯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上鹰晨,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天墨叛,我揣著相機(jī)與錄音,去河邊找鬼模蜡。 笑死漠趁,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的忍疾。 我是一名探鬼主播闯传,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼膝昆!你這毒婦竟也來了丸边?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤荚孵,失蹤者是張志新(化名)和其女友劉穎妹窖,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體收叶,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡骄呼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了判没。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜓萄。...
    茶點(diǎn)故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖澄峰,靈堂內(nèi)的尸體忽然破棺而出嫉沽,到底是詐尸還是另有隱情,我是刑警寧澤俏竞,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布绸硕,位于F島的核電站堂竟,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏玻佩。R本人自食惡果不足惜出嘹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望咬崔。 院中可真熱鬧税稼,春花似錦、人聲如沸垮斯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽甚脉。三九已至丸升,卻和暖如春铆农,著一層夾襖步出監(jiān)牢的瞬間牺氨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工墩剖, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留猴凹,地道東北人。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓岭皂,卻偏偏與公主長得像郊霎,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子爷绘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容