双时钟系统服务(java)

双时钟系统服务(java)java 开发的双时钟系统 也可以改成多时钟系统 java 时钟同步

大家好,欢迎来到IT知识分享网。

1、描述介绍

2、pom依赖

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.5</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>org.example</groupId> <artifactId>wyt01clockserver</artifactId> <version>0.0.1-SNAPSHOT</version> <name>wyt01clockserver</name> <description>wyt01clockserver</description> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.62</version> </dependency> <!-- swagger-ui依赖 https://springdoc.org/ --> <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <version>2.5.0</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> <finalName>clockserver</finalName> </configuration> </plugin> </plugins> </build> </project> 

3、核心思路介绍 – 同步逻辑介绍

首先是更新当前节点的系统时间

其次是根据同步请求的参数情况,如果同步其它节点的标识设置为true,则从配置文件中获取要同步的主机(也可以自己改成从缓存或者入参中获取)。

最后轮询向每个节点发送同步请求,此时发送的请求参数中的同步标识为false,以此避免无限循环同步。

 @Override public BaseResult setSyncTime(SyncTimeReq request) { //当前节点设置时间 executor.submit(() -> updateSystemDate(request.getDate())); //如果syncFlag标识为true,则遍历所有非当前节点发送同步请求 if (request.getSyncFlag()) { String local = getLocalHost(); String[] hostArr = hostStr.split(","); for (int i = 0; i < hostArr.length; i++) { String host = hostArr[i]; if (host.equalsIgnoreCase(local)) continue; executor.submit(() -> updateOtherSystemDate(host, request.getDate())); } } return BaseResult.success(); }

4、完整代码介绍

4.1 application.yml

spring: application: name: wyt01clockserver server: port: 8183 servlet: context-path: /clockserver clockserver: host: 127.0.0.1 

4.2 controller 

package com.clockserver.controller; import com.alibaba.fastjson.JSONObject; import com.clockserver.bean.BaseResult; import com.clockserver.bean.clock.SyncFactorReq; import com.clockserver.bean.clock.SyncTimeReq; import com.clockserver.service.IClockServerService; import com.clockserver.util.ExceptionUtils; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @Tag(name = "时钟控制类",description = "包含所有时钟控制相关的接口") @RestController @RequestMapping("/clock") public class ClockServerController { private static Logger logger = LoggerFactory.getLogger(ClockServerController.class); @Autowired private IClockServerService clockServerService; @Operation(summary = "获取天文时间接口") @GetMapping("/getAstronomicalTime") public BaseResult getAstronomicalTime(){ return clockServerService.getAstronomicalTime(); } @Operation(summary = "获取时间接口") @GetMapping("/getAnotherTime") public BaseResult getAnotherTime(){ return clockServerService.getAstronomicalTime(); } @Operation(summary = "设置时间系数接口") @PostMapping("/setAnotherTimeFactor") public BaseResult setAnotherTimeFactor(@RequestBody SyncFactorReq request){ logger.info("接收到设置时间系数请求{}", JSONObject.toJSONString(request)); try { BaseResult result = clockServerService.setAnotherTimeFactor(request); return result; }catch (Exception e){ logger.error("设置时间系数异常,异常信息为:",e); return BaseResult.error(ExceptionUtils.getSimpleException(e)); } } @Operation(summary = "设置同步时间接口") @PostMapping("/setSyncTime") public BaseResult setSyncTime(@RequestBody SyncTimeReq request){ logger.info("接收到设置时间请求{}", JSONObject.toJSONString(request)); try { BaseResult result = clockServerService.setSyncTime(request); return result; }catch (Exception e){ logger.error("设置同步时间异常,异常信息为:",e); return BaseResult.error(ExceptionUtils.getSimpleException(e)); } } } 

4.3 service

package com.clockserver.service; import com.clockserver.bean.BaseResult; import com.clockserver.bean.clock.SyncFactorReq; import com.clockserver.bean.clock.SyncTimeReq; public interface IClockServerService { public BaseResult getAstronomicalTime(); public BaseResult getAnotherTime(); public BaseResult setAnotherTimeFactor(SyncFactorReq request); public BaseResult setSyncTime(SyncTimeReq request); }

4.4 serviceImpl

package com.clockserver.service.impl; import com.alibaba.fastjson.JSONObject; import com.clockserver.bean.BaseResult; import com.clockserver.bean.clock.SyncFactorReq; import com.clockserver.bean.clock.SyncTimeReq; import com.clockserver.bean.clock.TimeBean; import com.clockserver.service.IClockServerService; import com.clockserver.util.ExceptionUtils; import jakarta.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import java.net.InetAddress; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @Component public class ClockServerServiceImpl implements IClockServerService { private static Logger logger = LoggerFactory.getLogger(ClockServerServiceImpl.class); @Autowired private RestTemplate restTemplate; @Value("${server.port}") private Integer port; @Value("${clockserver.host}") private String hostStr; //@TODO 如果需要多个作战事件系数,将该系数因子改成map即可,然后每种作战系数各个不同的唯一标识 private volatile long AnotherTimeFactor = 0l; private static ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 0l, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10)); private static String localIp = null; @Override public BaseResult getAstronomicalTime() { long millis = System.currentTimeMillis(); TimeBean timeBean = TimeBean.getTimeBean(millis, millis + AnotherTimeFactor); return BaseResult.success(timeBean); } @Override public BaseResult getAnotherTime() { long millis = System.currentTimeMillis(); TimeBean timeBean = TimeBean.getTimeBean(millis, millis + AnotherTimeFactor); return BaseResult.success(timeBean); } @Override public BaseResult setAnotherTimeFactor(SyncFactorReq request) { //当前节点设置系数 this.AnotherTimeFactor = request.getFactor(); //如果syncFlag标识为true,则遍历所有非当前节点发送同步请求 if (request.getSyncFlag()){ String local = getLocalHost(); String[] hostArr = hostStr.split(","); for (int i = 0; i < hostArr.length; i++) { String host = hostArr[i]; if (host.equalsIgnoreCase(local)) continue; executor.submit(() -> updateOtherSystemFactor(host, request.getFactor())); } } return BaseResult.success(); } @Override public BaseResult setSyncTime(SyncTimeReq request) { //当前节点设置时间 executor.submit(() -> updateSystemDate(request.getDate())); //如果syncFlag标识为true,则遍历所有非当前节点发送同步请求 if (request.getSyncFlag()) { String local = getLocalHost(); String[] hostArr = hostStr.split(","); for (int i = 0; i < hostArr.length; i++) { String host = hostArr[i]; if (host.equalsIgnoreCase(local)) continue; executor.submit(() -> updateOtherSystemDate(host, request.getDate())); } } return BaseResult.success(); } private String getRequestHost() { ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest requests = attr.getRequest(); String remoteHost = requests.getRemoteHost(); return remoteHost; } private void updateSystemDate(String timeStr) { try { logger.info("更新系统时间为{}", timeStr); String timeCommand = "sudo date -s '" + timeStr + "'"; // 以root身份执行命令 String[] command = {"/bin/sh", "-c", timeCommand}; Process process = Runtime.getRuntime().exec(command); process.waitFor(); int exitValue = process.waitFor(); if (exitValue == 0) { logger.info("系统时间已设置为:{}", timeStr); } else { logger.error("设置系统时间失败:{}", timeStr); } } catch (Exception e) { logger.error("设置系统时间异常,异常信息为:", e); } } private void updateOtherSystemDate(String host, String dateStr) { SyncTimeReq req = new SyncTimeReq(); req.setDate(dateStr); String url = "http://" + host + ":" + port + "/clockserver/clock/setSyncTime"; logger.info("执行url[{}]更新系统时间为{}", url, dateStr); BaseResult result = BaseResult.error(); try { result = restTemplate.postForObject(url, req, BaseResult.class); } catch (Exception e) { logger.error("更新{}主机时间异常,异常信息为:", host, e); result.setMsg(ExceptionUtils.getSimpleException(e)); } logger.info("更新主机{}系统时间为{}的结果是{}", host, dateStr, JSONObject.toJSONString(result)); } private void updateOtherSystemFactor(String host, Long factor) { SyncFactorReq req = new SyncFactorReq(); req.setFactor(factor); String url = "http://" + host + ":" + port + "/clockserver/clock/setAnotherTimeFactor"; logger.info("执行url[{}]更新时间系数为{}", url, factor); BaseResult result = BaseResult.error(); try { result = restTemplate.postForObject(url, req, BaseResult.class); } catch (Exception e) { logger.error("更新{}时间系数异常,异常信息为:", host, e); result.setMsg(ExceptionUtils.getSimpleException(e)); } logger.info("更新主机{}时间系数为{}的结果是{}", host, factor, JSONObject.toJSONString(result)); } private String getLocalHost() { if (localIp != null) return localIp; String ip = ""; try { InetAddress inetAddress = InetAddress.getLocalHost(); ip = inetAddress.getHostAddress(); localIp = ip; } catch (Exception e) { logger.error("获取本机ip异常:", e); } return ip; } } 

4.5 其它辅助类

@Data public class BaseResult { private Integer code; private String msg; private Object data; private Boolean success; private BaseResult(Integer code, String msg, Object data, Boolean success) { this.code = code; this.msg = msg; this.data = data; this.success = success; } public static BaseResult success(){ BaseResult result = new BaseResult(200,"success",null,true); return result; } public static BaseResult success(Object data){ BaseResult result = new BaseResult(200,"success",data,true); return result; } public static BaseResult error(){ BaseResult result = new BaseResult(-1,"error",null,false); return result; } public static BaseResult error(String msg){ BaseResult result = new BaseResult(-1,msg,null,false); return result; } } @Data public class SyncFactorReq { private long factor; //时钟偏移量 private Boolean syncFlag = false; // true:同步给其它所有节点 false:不同步给其它节点 } @Data public class SyncTimeReq { private String date; //要同步的时间 "yyyy-MM-dd HH:mm:ss" private Boolean syncFlag = false; // true:同步给其它所有节点 false:不同步给其它节点 } @Data public class TimeBean { private Long astronomicalTime; //天文事件(毫秒级) private Long AnotherTime; //时间(毫秒级) public static TimeBean getTimeBean(Long astronomicalTime,Long AnotherTime){ TimeBean timeBean = new TimeBean(); timeBean.setAstronomicalTime(astronomicalTime); timeBean.setAnotherTime(AnotherTime); return timeBean; } } public class ExceptionUtils { public static String getSimpleException(Exception e) { return e.toString() + ":" + e.getMessage(); } } 

4、总结

上述代码仅仅是一个demo,主要是展示一直多时钟服务的编辑思路。如果想要更稳定的系统,还需要自行完善。比如下面两点改进建议:

2)当前服务是双时钟,如果多时钟怎么改?

当前只存储了一个时钟偏移系数,如果想多时钟系统,可以用map将不同标识的时钟偏移系数存储起来使用。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/129590.html

(0)
上一篇 2025-08-23 12:45
下一篇 2025-08-23 13:10

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信