一、什么是定时任务
定时任务是每个业务常见的需求,比如每分钟扫描超时支付的订单,每小时清理一次数据库历史数据,每天统计前一天的数据并生成报表等等。
随着微服务和云计算的兴起,定时任务技术也是发展迅速,不仅能做单机的定时任务,而且在分布式系统下应用也很广泛,成为了业务做兜底、数据处理的第一选择。
二、定时任务为什么需要通知
定时任务现在在业务数据处理中的比重越来越重,如果业务数据处理失败了,需要及时通知到业务方,确保了服务的可靠性和稳定性。同时,好的定时任务通知系统,还能分析任务失败的原因(比如堆栈信息)并通知给业务方,帮助用户快速定位问题。
根据通知的类型,大概可以有以下几类:
- 成功通知:任务执行成功,把结果通知给用户。比如统计前一天的数据并把GaaP结果通过短信等渠道发送给对应负责人。
- 超时通知:任务执行超时,通知用户。
- 失败通知:任务执行失败,通知用户。
- 机器异常通知:运行的机器下线或者繁忙,通知用户。
三、自研定时任务报警通知
如果是自研的定时任务系统,或者使用了开源定时任务框架(比如Quartz),想要增加报警通知能力,我们可以采取什么方案呢?从实时性角度来看,短信和电话通知实时性最高,但是这两种方案需要比较大的成本,比如短信通知需要短信平台。如果没有短信平台,我们也可以采用邮件和webhook通知。
3.1、邮件
每个邮件服务器都由SMTP服务器和POP3服务器构成,其中SMTP服务器负责发邮件的请求,而POP3负责收邮件的请求。通过SMTP与POP3即可实现邮件的收发。
邮件发送原理图
- 配置邮件服务器
以网易163邮件为例,在发送方邮箱设置里,开启POP3/SMTP服务
- 以Java代码为例,发送邮件的demo
importorg.junit.Test; importjavax.mail.Message; importjavax.mail.Session; importjavax.mail.Transport; importjavax.mail.internet.InternetAddress; importjavax.mail.internet.MimeMessage; importjava.io.PrintWriter; importjava.io.StringWriter; importjava.util.Properties; publicclassSendMailDemo { publicstaticvoidmain(String[] args) throwsException { Propertiesprop=newProperties(); prop.setProperty("mail.host","smtp.163.com");//设置发送方邮箱服务器prop.setProperty("mail.transport.protocol","smtp");//邮件发送协议prop.setProperty("mail.smtp.auth","true");//需要验证用户名密码Sessionsession=Session.getDefaultInstance(prop); Transportts=session.getTransport(); StringmailUser="xxx@163.com"; //邮箱的账号StringmailPasswd="123456789"; //邮箱的密码ts.connect("smtp.163.com", mailUser, mailPasswd); MimeMessagemessage=newMimeMessage(session); message.setFrom(newInternetAddress(mailUser)); //收件人的邮箱地址message.setRecipient(Message.RecipientType.TO,newInternetAddress("xxxx@163.com")); //邮件的标题message.setSubject("自定义通知"); message.setContent("<h1 style='color:black'>邮件通知发送成功!</h1>","text/html;charset=UTF-8"); ts.sendMessage(message,message.getAllRecipients()); ts.close(); } }
3. 运行一次,可以收到邮件
3.2、WebHook
钉钉、企业微信、飞书,支持通过webhook方式发送通知到群里。下面以钉钉webhook为例
- 首先在钉钉群里,创建一个机器人
群设置->智能群助手
添加机器人->自定义webhook接入
- 直接通过http调用webhook链接即可,以Java代码为例,demo如下:
/*** @Auther: tangtao* @Date: 2022/8/19 10:46* @Description:发送钉钉通知*/publicclassWebhookDemo { publicstaticvoidmain(String[] args) throwsException { CloseableHttpClienthttpClient=HttpClientBuilder.create().build(); HttpPosthttpPost=newHttpPost("https://oapi.dingtalk.com/robot/send?access_token=fcf4c30596a8b26d76a6d4dcd658b708066e23e877b285c784db2360660c97e0"); httpPost.setHeader("Content-Type", "application/json;charset=utf8"); JSONObjectresult=newJSONObject(); JSONObjecttext=newJSONObject(); text.put("content", "测试钉钉发送定时任务通知"); result.put("text", text); result.put("msgtype", "text"); StringjsonString=JSON.toJSONString(result); StringEntityentity=newStringEntity(jsonString, "UTF-8"); httpPost.setEntity(entity); CloseableHttpResponseresponse=null; response=httpClient.execute(httpPost); HttpEntityresponseEntity=response.getEntity(); System.out.println("响应结果:"+EntityUtils.toString(responseEntity)); } }
3. 运行一次,可以在钉钉群里看到通知消息
四、ElasticJob通知解决方案
ElasticJob是一款基于 Quartz 开发,依赖 Zookeeper 作为注册中心、轻量级、无中心化的分布式任务调度框架,目前已经通过 Apache 开源,使用ElasticJob可以快速实现分布式任务调度。ElasticJob只需配置定时任务的错误处理策略即可实现通知功能。目前ElasticJob支持邮件、钉钉、微信三种通知渠道。
4.1、接入步骤
以钉钉通知为例
- 引入pom
<!--elasticjob--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.2.0.RELEASE</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.2.0.RELEASE</version></dependency><dependency><groupId>org.apache.shardingsphere.elasticjob</groupId><artifactId>elasticjob-lite-spring-boot-starter</artifactId><version>3.0.0-RC1</version></dependency><dependency><groupId>org.apache.shardingsphere.elasticjob</groupId><artifactId>elasticjob-error-handler-dingtalk</artifactId><version>3.0.0-RC1</version></dependency>
- 新增Job
/*** @Auther: tangtao* @Date: 2022/8/17 14:33* @Description: elastic job 失败后发送钉钉通知*/publicclassErrorNoticeDingtalkJobimplementsSimpleJob { publicvoidexecute(finalShardingContextshardingContext) { thrownewRuntimeException(String.format("An exception has occurred in Job, The parameter is %s", shardingContext.getShardingParameter())); } }
- 对定时任务进行配置
jobs: errorNoticeDingtalkJob: elasticJobClass: com.springboottemplate.elasticjob.job.ErrorNoticeDingtalkJoboverwrite: trueshardingTotalCount: 3shardingItemParameters: 0=Beijing,1=Shanghai,2=GuangzhoujobErrorHandlerType: DINGTALKjobBootstrapBeanName: errorNoticeDingtalkBeanprops: dingtalk: webhook: you_webhookkeyword: you_keywordsecret: you_secretconnectTimeout: 3000readTimeout: 5000
4.2、通知功能缺点
ElasticJob没有提供控制台来配置定时任务的通知,需要在配置文件里针对每个任务单独配置,配置成本比较高。而且想要修改定时任务的通知配置,还需要修改配置重启服务才能生效,可维护性低。
五、XXL-JOB通知解决方案
xxl-job,这是出自大众的开源项目,官网上介绍这是一个轻量级分布式任务调度框架,其核心设计目标是开发迅速、学习简单、轻量级、易扩展,与SpringBoot有非常好的集成,而且监控界面就集成在调度中心,界面又简洁,对于企业维护起来成本不高,默认支持失败的邮件告警。这就使很多企业选择xxl-job做调度平台。
5.1、接入步骤
XXL-JOB默认支持失败的邮件告警,只需要在控制台配置对应邮箱即可。
邮件通知也进行了排版:
5.2、其他通知渠道
XXL-JOB可以扩展短信、钉钉等方式,但是需要开发者自己手动实现。如果需要新增一种告警方式,需要新增一个通知类实现 “com.xxl.job.admin.core.alarm.JobAlarm” 接口即可
5.3、对比ElasticJob
XXL-JOB可以通过控制台来配置每个任务的通知配置,动态生效,接入成本低,可维护性高,比ElasticJob方便很多。但是当前版本控制台只支持邮件通知,邮件通知响应速度比较慢,不适合用在核心在线业务的失败通知。
六、Schedulerx2.0企业级通知解决方案
6.1、Schedulerx2.0简介
阿里云任务调度SchedulerX2.0是阿里巴巴自研的基于Akka架构的一站式任务调度平台,兼容开源XXL-JOB、ElasticJob、Quartz(规划中),提供了商业级的通知管理服务。
6.2、通知功能的优势
相对于ElasticJob、XXL-JOB等分布式任务调度框架的通知功能相比,SchedulerX2.0通知功能具有以下几大优势:
- 多元化的通知通道
当前支持短信、电话、邮箱、webhook(钉钉、企业微信、飞书)。
- 丰富的通知类型
- 任务执行失败通知
- 任务执行超时通知
- 无可用机器通知
- 机器繁忙通知
- 任务执行结果通知
- 快速响应
通知内容更全面、更智能的通知管理能力,使通知的响应变得更迅速,提高问题解决的速度,减少因业务异常造成的损失。以失败通知为例,通知内容不仅记录了任务的基本信息,还记录了失败原因,方便运维人员快速定位问题。
- 强大的通知查询功能
SchedulerX2.0支持查询15天内通知历史记录,根据应用、任务、通知类型、通知渠道等多个条件查询的通知信息,能为任务的日常的维护提供参考与指导作用。
- 支持多种通知对象
Schedulerx2.0通知管理目前支持通知联系人与通知联系人组两种通知对象。Schedulerx2.0对通知联
系人进行统一管理,用户可以根据自身需要灵活的配置任务的通知对象,减少了通知对象配置的复杂度。
- 配置简单、学习成本低
SchedulerX2.0无需用户新增任何代码,在控制台上即可完成所有的报警通知配置,上手速度快、难度低、学习成本几乎为零。
- 低成本与免运维
Schedulerx2.0通知管理功能不收取任何费用。其更智能、更全面的通知管理能力可以有效降低系统的运维成本和运维人员的时间成本。
6.3、通知功能核心流程
定时任务在某种状态下会触发通知,通过接入层的统一Api将通知信息发送给SchedulerX2.0的通知管理平台。通知管理平台对通知进行接收、保存。再基于任务的通知配置规则以邮件、短信、语音等方式将定时任务通知推送给用户。
6.4、配置联系人组
目前Schedulerx2.0的定时任务默认使用的是应用的通知渠道与联系人。想要配置任务的通知渠道与联系人只需要配置对应应用的通知渠道以及通知联系人即可。
- 新增联系人
登录Schedulerx2.0控制台>通知管理>通知联系人。在联系人页签,单击新建联系人,填写联系人相关信息即可。
2. 新增联系人组
登录Schedulerx2.0控制台>通知管理>通知联系人。在联系人组页签,单击新建联系组,填写组名称,绑定联系人即可。
- 应用绑定联系人组
登录Schedulerx2.0控制台>应用管理。找到对应的应用,在通知配置中绑定对应的通知联系人组即可。
6.5、配置通知类型
登录Schedulerx2.0控制台>任务管理。新增或者编辑任务时候,在通知配置中选择对应的通知类型即可。
6.6、通知记录查询
SchedulerX2.0支持查询15天内通知记录,根据记录的任务报警信息与通知信息,开发者可以了解到任务一段时间内的健康状态,能为任务的日常的维护提供参考与指导作用。
6.7、与开源方案的对比
XXL-JOB |
ElasticJob |
SchedulerX |
|
通知渠道 |
邮箱 |
邮箱、钉钉、企业微信 |
短信、电话、邮箱、webhook(钉钉、飞书、企业微信) |
可视化配置 |
支持 |
不支持 |
支持 |
通知类型 |
失败通知 |
失败通知 |
|
联系人组 |
不支持 |
不支持 |
支持 |
通知记录查询 |
不支持 |
不支持 |
支持 |