package com.ycl.task; import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; import com.ycl.platform.domain.entity.PlatformOnline; import com.ycl.platform.service.PlatformOnlineService; import com.ycl.system.entity.SysDictData; import com.ycl.system.service.impl.SysDictTypeServiceImpl; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.io.IOException; import java.net.InetAddress; import java.util.Date; import java.util.List; import java.util.Objects; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * 平台在线率定时任务 * * @author:xp * @date:2024/8/3 13:26 */ @Slf4j @RequiredArgsConstructor @Component("platformTask") public class PlatformTask { private final RedisTemplate redisTemplate; private final SysDictTypeServiceImpl dictTypeService; private final PlatformOnlineService platformOnlineService; /** * 该定时任务需要使用redis存储离线时长,并定期同步到mysql中 */ private static final String REDIS_KEY_PREFIX = "platform_online_"; private static final String DICT_TYPE = "platform_online"; private static final ExecutorService executorService = new ThreadPoolExecutor(8, 24, 5000, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10), new ThreadPoolExecutor.CallerRunsPolicy() ); /** * ping平台是否在线 * * @throws IOException */ public void ping() { List platformList = dictTypeService.selectDictDataByType(DICT_TYPE); for (SysDictData platform : platformList) { executorService.submit(() -> { try { Boolean reachable = Boolean.FALSE; for (int tryTimes = 1; tryTimes < 3; tryTimes++) { // 三秒未ping通重试一次,如果不行才扣分 reachable = InetAddress.getByName(platform.getDictValue()).isReachable(3000); if (! reachable && tryTimes == 0) { continue; } if (! reachable) { // 如果ping不通,离线时长加5秒 redisTemplate.opsForValue().increment(REDIS_KEY_PREFIX + platform.getDictValue(), 5); log.warn(platform.getDictLabel() + "平台未ping通"); } } } catch (Exception e) { log.error("检查平台连通性时发生错误", e); } }); } } /** * 每小时将redis中的平台离线数据同步到mysql * */ public void synToMySQL() { List platformList = dictTypeService.selectDictDataByType(DICT_TYPE); // 将java.util.Date转换为java.sql.Date java.sql.Date sqlDate = new java.sql.Date(new Date().getTime()); for (SysDictData platform : platformList) { Object outLineTime = redisTemplate.opsForValue().get(REDIS_KEY_PREFIX + platform.getDictValue()); Integer outlineTimeSed = Objects.isNull(outLineTime) ? 0 : (Integer) outLineTime; PlatformOnline one = new LambdaQueryChainWrapper<>(platformOnlineService.getBaseMapper()) .eq(PlatformOnline::getPlatformIp, platform.getDictValue()) .eq(PlatformOnline::getCreateDate, sqlDate) .one(); if (Objects.isNull(one)) { one = new PlatformOnline(); one.setPlatformIp(platform.getDictValue()); one.setPlatformName(platform.getDictLabel()); one.setCreateDate(sqlDate); one.setTodayOutlineSed(outlineTimeSed); } else { one.setTodayOutlineSed(one.getTodayOutlineSed() + outlineTimeSed); } one.setPlatformIp(platform.getDictValue()); one.setPlatformName(platform.getDictLabel()); one.setCreateDate(sqlDate); platformOnlineService.saveOrUpdate(one); } log.info("同步平台离线信息完成"); } }