心跳机制
一、需求与背景
经常会有这样的场景:
- 开发或者测试的时候,要测试一个定时任务job,刚好要测试的时候发现,不知道谁把job给执行了?
- 有些业务同一时间只能有一个进程在运行,但是结果并不是预期的,所以需要知道是否有多个进程同时在跑?
- 某些时候可能服务器停掉了,什么时候停的都不知道
- 想知道进程运行多久了,进行一些统计分析
- 等等其他
二、架构与思想
以上问题有很多种解决方案,比如服务发现、心跳、轮询等等,这里选择的是心跳机制。因为心跳机制非常简单,而且也只需要依赖一个数据库表,非常的轻便,适合各个项目。
2.1、守护daemon线程
在服务器启动的时候开启一个守护daemon线程,在守护daemon线程每隔一段时间将关于进程的基本信息存储到数据库表中。
2.2、记录关键信息
heart-beat记录了如下内容:
private String projectPath; // 项目启动路径
private String serverIp; //服务器ip
private Integer processNo;//进程号
private LocalDateTime processStartTime;//进程开启时间
private LocalDateTime heartBeatTime;//心跳当前时间
三、具体使用
在sa-base
项目中的 sa-base.yaml
配置文件中,有关于心跳时间间隔的配置
yaml
# 心跳配置
heart-beat:
interval-seconds: 60
默认是 60秒,时间想改短或者改长都可以。
心跳由于是守护线程去处理,且只有一个线程,数据库操作也非常简单,所以整体性能影响非常非常非常小,所以这个心跳时长可以自由定义。当然,不改也可以,使用默认的 60
秒。
四、实现原理
4.1、开启守护daemon线程
HeartBeatManager.java
java
/**
* 心跳核心调度管理器
*
* @Author 1024创新实验室-主任: 卓大
* @Date 2023-01-09 20:57:24
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright 1024创新实验室 ( https://1024lab.net )
*/
public class HeartBeatManager {
private static final String THREAD_NAME_PREFIX = "sa-heart-beat";
private static final int THREAD_COUNT = 1;
private static final long INITIAL_DELAY = 60 * 1000L;
private ScheduledThreadPoolExecutor threadPoolExecutor;//守护线程池
private IHeartBeatRecordHandler heartBeatRecordHandler;//服务状态持久化处理类
private long intervalMilliseconds;//调度配置信息
public HeartBeatManager(Long intervalMilliseconds,
IHeartBeatRecordHandler heartBeatRecordHandler) {
this.intervalMilliseconds = intervalMilliseconds;
this.heartBeatRecordHandler = heartBeatRecordHandler;
//使用守护线程去处理
this.threadPoolExecutor = new ScheduledThreadPoolExecutor(THREAD_COUNT, r -> {
Thread t = new Thread(r, THREAD_NAME_PREFIX);
if (!t.isDaemon()) {
t.setDaemon(true);
}
return t;
});
// 开始心跳
this.beginHeartBeat();
}
//开启心跳
private void beginHeartBeat() {
HeartBeatRunnable heartBeatRunnable = new HeartBeatRunnable(heartBeatRecordHandler);
threadPoolExecutor.scheduleWithFixedDelay(heartBeatRunnable, INITIAL_DELAY, intervalMilliseconds, TimeUnit.MILLISECONDS);
}
}
4.2、心跳数据
HeartBeatRunnable.java
java
public class HeartBeatRunnable implements Runnable {
private String projectPath;//项目路径
private List<String> serverIps;//服务器ip(多网卡)
private Integer processNo;//进程号
private LocalDateTime processStartTime;//进程开启时间
private IHeartBeatRecordHandler recordHandler;
public HeartBeatRunnable(IHeartBeatRecordHandler recordHandler) {
this.recordHandler = recordHandler;
this.initServerInfo();
}
/**
* 初始化心跳相关信息
*/
private void initServerInfo(){
RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
this.projectPath = System.getProperty("user.dir");
this.serverIps = new ArrayList<>(NetUtil.localIpv4s());
this.processNo = Integer.valueOf(runtimeMXBean.getName().split("@")[0]).intValue();
this.processStartTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(runtimeMXBean.getStartTime()), ZoneId.systemDefault());
}
@Override
public void run() {
HeartBeatRecord heartBeatRecord = new HeartBeatRecord();
heartBeatRecord.setProjectPath(this.projectPath);
heartBeatRecord.setServerIp(StringUtils.join(this.serverIps, ";"));
heartBeatRecord.setProcessNo(this.processNo);
heartBeatRecord.setProcessStartTime(this.processStartTime);
heartBeatRecord.setHeartBeatTime(LocalDateTime.now());
recordHandler.handler(heartBeatRecord);
}
}
更多代码可见sa-base
项目support.heartbeat
包。
联系我们
1024创新实验室-主任:卓大,混迹于各个技术圈,研究过计算机,熟悉点 java,略懂点前端。
1024创新实验室 致力于成为中原领先、国内一流的技术团队, 以AI+数字化为驱动,用技术为产业互联网提供无限可能, 业务如下:
- 教育领域(高职院校数字化、就业创业大数据平台、继续教育平台;在线教育系统、视频直播、题库等,包含:医学、应急管理、成考、专升本等)
- 供应链领域(网络货运平台、大宗贸易进销存ERP、物流管理TMS、B2B电商、仓储WMS、AI提效等)
- 中医领域(诊所数字化管理、互联网医院、AI辅助诊疗、中医适宜技术、在线云问诊、空中药房等)
- AI+软件领域(软件定制外包、开源技术、数据大屏、国产化改造、技术升级换代、人员外包、技术顾问、技术培训等)
加微信: 卓大 拉你入群,一起学习 | 公众号 :六边形工程师 分享:赚钱、代码、生活 | 请 “1024创新实验室” 烩面里加肉 咖啡配胡辣汤,提神又饱腹 | 抖音 : 六边形工程师 直播:赚钱、代码、中医 |