系统间交互时,怎么校验两个系统所在服务器时间是否一致
一、背景知识
- 网络时间协议(NTP):是一种用于同步计算机时钟的协议,通过向时间服务器发送请求,NTP客户端可以自动调整其系统时间,达到毫秒级别的精度。
- 时间同步的重要性:在分布式系统中,时间一致性对于数据同步、日志记录、安全认证等至关重要。时间不一致可能导致数据冲突、日志混乱、认证失败等问题。
二、校验方法
-
接口中传递时间戳
- 在接口调用时,双方系统可以在请求或响应中传递当前的时间戳。
- 接收方收到时间戳后,与自身系统的时间进行比较,计算时间差。
-
设定时间差阈值
- 根据业务需求和网络延迟情况,设定一个合理的时间差阈值(例如,5秒、10秒等)。
- 如果计算出的时间差在阈值范围内,则认为时间一致;否则,认为时间不一致。
-
处理时间不一致的情况
- 如果发现时间不一致,接口可以返回错误提示,要求调用方重新同步时间后再次调用。
- 或者,接口可以在内部处理时间差,例如,对时间戳进行校正,以确保业务逻辑的正确性。
三、代码示例
-
接口中传递时间戳
// 接口中直接传递时间戳校验
@GetMapping("/validate-time")
public String validateTime(@RequestParam("timestamp") long timestamp) {
long currentTime = System.currentTimeMillis();
long timeDifference = Math.abs(currentTime - timestamp);
long threshold = 5000; // 设定时间差阈值为5秒
if (timeDifference <= threshold) {
return "Time is consistent";
} else {
return "Time is inconsistent. Time difference: " + timeDifference + " ms";
}
}
-
接口中传递系统名称和时间的签名校验
// 接口中直接传递系统名称和时间的签名校验
@GetMapping("/validate-sign")
public String validateSign(@RequestParam("sign") String sign) {
String currentMinuteMd5Hex = currentMinuteMd5Hex();
String lastMinuteMd5Hex = lastMinuteMd5Hex();
// 校验精度为分钟,如果两个系统服务器时间相差一分钟以上就会校验不通过
if (StringUtils.equals(currentMinuteMd5Hex, sign) || StringUtils.equals(lastMinuteMd5Hex, sign)) {
return "Sign is consistent";
} else {
return "Sign is inconsistent";
}
}
// 获取上一分钟签名
private String lastMinuteMd5Hex() {
String hexCode = DigestUtils.md5Hex("RULE_SYS").toUpperCase();
Date lastMinute = getLastMinute(-1, Calendar.MINUTE);
String lastMinuteS = DateFormatUtils.format(lastMinute, "yyyyMMddHHmm");
String lastMinuteMd5Hex = DigestUtils.md5Hex(hexCode + lastMinuteS).toUpperCase();
System.out.println(lastMinuteMd5Hex);
return lastMinuteMd5Hex;
}
// 获取上一时间
public Date getLastMinute(int amount, int unit) {
Calendar ca = Calendar.getInstance();
ca.add(unit, amount);
Date lastDay = ca.getTime();
return lastDay;
}
// 获取当前分钟签名
private String currentMinuteMd5Hex() {
String hexCode = DigestUtils.md5Hex("RULE_SYS").toUpperCase();
String formatter = "yyyyMMddHHmm";
SimpleDateFormat sdf = new SimpleDateFormat(formatter);
String nowStr = sdf.format(new Date());
String currentMinuteMd5Hex = DigestUtils.md5Hex(hexCode + nowStr).toUpperCase();
System.out.println(currentMinuteMd5Hex);
return currentMinuteMd5Hex;
}
四、注意事项
- 时间服务器选择:确保两个系统都使用可靠的时间服务器进行时间同步,以提高时间的一致性。
- 网络延迟:考虑网络延迟对时间戳传递的影响,合理设定时间差阈值。
- 系统时钟稳定性:定期检查和维护系统时钟,确保其稳定性和准确性。
- 日志记录:对于时间不一致的情况,记录详细的日志信息,以便后续分析和排查问题。
通过以上方法,可以有效地校验两个系统所在服务器的时间是否一致,确保分布式系统中时间相关业务的正确性和可靠性。