package com.ycl.task; import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; import com.ycl.platform.domain.entity.Platform; import com.ycl.platform.domain.entity.PlatformOnline; import com.ycl.platform.mapper.PlatformMapper; 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 PlatformMapper platformMapper; 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(16, 64, 5000, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1000), new ThreadPoolExecutor.CallerRunsPolicy() ); /** * ping平台是否在线 * * @throws IOException */ public void ping() { List platformList = new LambdaQueryChainWrapper<>(platformMapper) .isNotNull(Platform::getPlatformIP) .list(); for (Platform platform : platformList) { executorService.submit(() -> { try { Boolean reachable = Boolean.FALSE; for (int tryTimes = 1; tryTimes < 3; tryTimes++) { // 三秒未ping通重试一次,如果不行才扣分 reachable = InetAddress.getByName(platform.getPlatformIP()).isReachable(3000); if (reachable) { break; } } if (!reachable) { // 如果ping不通,离线时长加5秒 redisTemplate.opsForValue().increment(REDIS_KEY_PREFIX + platform.getPlatformIP(), 5); log.warn(platform.getPlatformName() + "平台未ping通"); } } catch (Exception e) { log.error("检查平台连通性时发生d错误", e); } }); } } /** * 每小时将redis中的平台离线数据同步到mysql * */ public void synToMySQL() { List platformList = new LambdaQueryChainWrapper<>(platformMapper) .isNotNull(Platform::getPlatformIP) .list(); // 将java.util.Date转换为java.sql.Date java.sql.Date sqlDate = new java.sql.Date(new Date().getTime()); for (Platform platform : platformList) { Object outLineTime = redisTemplate.opsForValue().get(REDIS_KEY_PREFIX + platform.getPlatformIP()); Integer outlineTimeSed = Objects.isNull(outLineTime) ? 0 : (Integer) outLineTime; PlatformOnline one = new LambdaQueryChainWrapper<>(platformOnlineService.getBaseMapper()) .eq(PlatformOnline::getPlatformId, platform.getId()) .eq(PlatformOnline::getCreateDate, sqlDate) .one(); if (Objects.isNull(one)) { one = new PlatformOnline(); one.setPlatformId(platform.getId()); one.setCreateDate(sqlDate); one.setTodayOutlineSed(outlineTimeSed); } else { one.setTodayOutlineSed(one.getTodayOutlineSed() + outlineTimeSed); } one.setPlatformId(platform.getId()); one.setCreateDate(sqlDate); platformOnlineService.saveOrUpdate(one); } log.info("同步平台离线信息完成"); } }