周期性检查网络异常,异步发送告警邮件

总体功能说明

  1. 周期性检测网络是否正常,由于项目目前比较简单,所以没有采用第三方框架;
  2. 异步发送告警邮件;
    1.   邮件发送频率控制:其一解决方案:通过为redis key设置过期时间;

添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

application.yml配置项

spring:  
  mail:
    username: #你用于发送邮件的邮箱账号
    password: #你用于发送邮件的邮箱密码
    host: smtp.xxx #你用于发送邮件的邮箱所支持的smtp域名
    default-encoding: UTF-8
    port: #smtp域名对应的端口号
    properties: #如果smtp域名需要支持ssl的话,增加此配置
      mail:
        smtp:
          ssl:
            enable: true

邮件发送实例代码

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.scheduling.annotation.Async;

public class MailService {

    @Autowired
    private JavaMailSender javaMailSender;

    @Value("${spring.mail.username}")
    private String sendMailer;

    //传参说明:email 接收邮件的邮箱;可根据业务自行灵活配置(如果业务大的话最好提供可灵活配置的功能)
    
    @Async("asyncThreadPool")
    public void sendEmail(String email) {
        
       //发送邮件之前检测redis是否有此邮箱所定义的key存在,有的话不执行以下发送邮件的逻辑,此处省略redis相关代码(判断key是否存在、以邮箱为key的set操作)
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(sendMailer);
        message.setTo(email);
        message.setSubject("邮件主题");
        message.setText("邮件内容");
        message.setSentDate(new Date());
        javaMailSender.send(message);
        log.info("发送邮件成功:{}->{}", sendMailer, email);
    }
}

异步线程池池配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

/**
 * 线程池配置 (线程池参数的配置可根据业务自行调整大小)
 *
 **/
@Configuration
@EnableAsync
public class AsyncThreadPoolConfig {
    // 核心线程池大小
    private int corePoolSize = 50;

    // 最大可创建的线程数
    private int maxPoolSize = 200;

    // 队列最大长度
    private int queueCapacity = 1000;

    // 线程池维护线程所允许的空闲时间
    private int keepAliveSeconds = 300;

    @Bean(name = "asyncThreadPool")
    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置核心线程数
        executor.setCorePoolSize(corePoolSize);
        // 设置最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        // 设置队列容量
        executor.setQueueCapacity(queueCapacity);
        // 设置线程活跃时间(秒)
        executor.setKeepAliveSeconds(keepAliveSeconds);
        // 设置默认线程名称
        executor.setThreadNamePrefix("Thread-");
        // 线程池对拒绝任务(无线程可用)的处理策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        return executor;
    }

}

周期性任务配置

使用ScheduledExecutorService 执行周期的发送任务,简单的实例代码如下:

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledExecutorExample {
  public static void main(String[] args) {
   
    ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();

    // 任务计划每 5 秒运行一次,立即开始
    executor.scheduleWithFixedDelay(new Runnable() {
      public void run() {
         try {
             URL url = new URL("url");//待检测的url
             URLConnection conn = url.openConnection();
             conn.connect(); 
        } catch (IOException e) {
            //执行发送邮件的逻辑
        }
      }
    }, 0, 5, TimeUnit.SECONDS);

    // 10秒后关闭执行者
    executor.schedule(new Runnable() {
      public void run() {
        executor.shutdown();
      }
    }, 10, TimeUnit.SECONDS);
  }
}

 

posted @ 2022-12-23 15:46  shuangman  阅读(49)  评论(0)    收藏  举报