Frequency Statistics and Interface Package of Alarm System QuickAlarm

The formulation and loading analysis of alarm rules, as well as the definition, loading and expansion of alarm executors were explained earlier. Basically, the core content has been completed, and the rest of the content is relatively simple.

  • Statistics of alarm frequency
  • Alarm thread pool
  • Unified and available decoupling for external encapsulation

I. Alarm frequency statistics

1. Design

When parsing the alarm rules earlier, there is a count parameter, which is used to determine the core parameters of which alarm executor to choose. Our maintenance method is also relatively simple:

  • For the alarm type, count statistics, if not called once, the count +1
  • reset every minute

2. Implementation

Because each alarm type maintains a separate counter

Define a map to store the correspondence

private ConcurrentHashMap<String, AtomicInteger> alarmCountMap;

Perform a reset every minute

// 每分钟清零一把报警计数
ScheduledExecutorService scheduleExecutorService = Executors.newScheduledThreadPool(1);
scheduleExecutorService.scheduleAtFixedRate(() -> {
    for (Map.Entry<String, AtomicInteger> entry : alarmCountMap.entrySet()) {
        entry.getValue().set(0);
    }
}, 0, 1, TimeUnit.MINUTES);

Pay attention to the above implementation, what is the problem?

Is it possible that because the data in the map is too large (or what is the reason for gc), it takes a lot of time to clear each time, and the count is inaccurate? (do not give an answer first)

Count plus 1 operation

/**
 * 线程安全的获取报警总数 并自动加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. Alarm thread pool

At present, only a very simple thread pool implementation is provided. The latter consideration is to abstract a forkjoin-based concurrency framework to handle (mainly because I recently came into contact with a concurrency component written by a great god based on forkjoin, which is quite powerful, so wait for me to study it thoroughly. , a copycat)

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

Task submission and execution

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

III. Interface Package

There's nothing to say about this

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. 获取报警的配置项
 * 2. 获取当前报警的次数
 * 3. 选择适当的报警类型
 * 4. 执行报警
 * 5. 报警次数+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 {  // 报警关闭, 则走空报警流程, 将报警信息写入日志文件
            executeHelper = AlarmExecuteSelector.getDefaultExecute();
        }


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

How to use the interface after encapsulation?

We use the singleton mode to encapsulate the only external class AlarmWrapper, which is relatively simple to use. The following is a test case

@Test
public void sendMsg() throws InterruptedException {
    String key = "NPE";
    String title = "NPE异常";
    String msg = "出现NPE异常了!!!";

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

    // 不存在异常配置类型, 采用默认报警, 次数较小, 则直接部署出
    AlarmWrapper.getInstance().sendMsg("zzz", "不存在xxx异常配置", "报警嗒嗒嗒嗒");
    
    Thread.sleep(1000);
}

It is relatively simple to use, just one line. From this use, we can know that the entire initialization is performed when the object is accessed for the first time.

The content of the constructor is as follows:

private AlarmWrapper() {
  // 记录每种异常的报警数
  alarmCountMap = new ConcurrentHashMap<>();

  // 加载报警配置信息
  confLoader = ConfLoaderFactory.loader();

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

So if you want to load all the configuration before your application is used, you might as well do it in advanceAlarmWrapper.getInstance()

IV. Summary

Based on this, the entire system design is basically completed, of course, the code level is ok, and the rest is the manual

Let's take a look at our entire logic, which is basically the following process

IMAGE

  1. Submit an alarm
  • Encapsulate alarm content (alarm type, alarm subject, alarm content)
  • Maintenance alarm count (the count is cleared every minute, and each alarm type corresponds to an alarm count)
  1. select alarm
  • Select alarm rules based on alarm type
  • Select the alarm actuator according to the alarm rules and the current alarm frequency
    • If interval mapping is not enabled, the default executor is returned
    • Otherwise, traverse the alarm frequency range of all actuators and select the matching alarm rule
  1. Execute the alarm
  • Encapsulate the alarm task and submit the thread pool
  • The specific alarm logic is realized inside the alarm actuator

V. Other

Related blog posts

  1. Alarm system QuickAlarm general outline
  2. Design and Realization of Alarm Actuator of Alarm System QuickAlarm
  3. Setting and loading of the alarm rules of the alarm system QuickAlarm
  4. Analysis of the alarm rules of the alarm system QuickAlarm
  5. Frequency Statistics and Interface Package of Alarm System QuickAlarm
  6. Alarm System QuickAlarm User Manual

Project: QuickAlarm

Personal blog: Z+|blog

A personal blog based on hexo + github pages, recording all blog posts in study and work, welcome to visit

statement

It is not as good as a letter of faith. The content has been posted, and it is purely from the family. Because of my ability and limited knowledge, if you find bugs or have better suggestions, please feel free to criticize and correct me at any time. My Weibo address: Xiaohuihui Blog

Scan attention

QrCode

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325477239&siteId=291194637