zxl
2025-05-26 04b45b8c22594cc5535b164380738a80b0e8cbe2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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 javax.swing.text.DateFormatter;
import java.io.IOException;
import java.net.InetAddress;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
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<Platform> 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秒
                        LocalDateTime localDateTime = LocalDateTime.now();
                        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                        String todayTime = localDateTime.format(dateTimeFormatter);
                        //每次redis累增5s
                        redisTemplate.opsForValue().increment(REDIS_KEY_PREFIX + todayTime + platform.getPlatformIP(), 5);
                        log.warn(platform.getPlatformName() + "平台未ping通");
                    }
                } catch (Exception e) {
                    log.error("检查平台连通性时发生d错误", e);
                }
            });
        }
    }
 
    /**
     * 每小时将redis中的平台离线数据同步到mysql
     *
     */
    public void synToMySQL() {
        List<Platform> 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());
        LocalDateTime localDateTime = LocalDateTime.now();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String todayTime = localDateTime.format(dateTimeFormatter);
        for (Platform platform : platformList) {
            Object outLineTime = redisTemplate.opsForValue().get(REDIS_KEY_PREFIX + todayTime + 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("同步平台离线信息完成");
    }
}