web端通过redis监听订阅实现监测xxljob执行器jar包对应的服务器资源包括内存,cpu使用情况,平均负载

web端通过redis监听订阅实现监测xxljob执行器jar包对应的服务器资源包括内存,cpu使用情况,平均负载



前言

通过redis的监听机制,可以实现监听多个执行器的资源变化
加粗样式


一、xxljob是什么?

XXL-JOB是一个轻量级分布式任务调度平台,主打特点是平台化,易部署,开发迅速、学习简单、轻量级、易扩展,代码仍在持续更新中。

调度中心: 任务调度控制台,平台自身并不承担业务逻辑,只是负责任务的统一管理和调度执行,并且提供任务管理平台
执行器: 负责接收“调度中心”的调度并执行,可直接部署执行器,也可以将执行器集成到现有业务项目中。 通过将任务的调度控制和任务的执行解耦,业务使用只需要关注业务逻辑的开发。
XXL-JOB主要提供了任务的动态配置管理、任务监控和统计报表以及调度日志几大功能模块,支持多种运行模式和路由策略,可基于对应执行器机器集群数量进行简单分片数据处理。

二、使用步骤

这里的结构为web端和executor执行器端都引入公共端core
<dependency> <groupId>ssssss.ssss</groupId> <artifactId>core</artifactId> </dependency>

1.在core公共端定义实体类

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ServerInfoVO {
    /**
     * xxljob名
     */
    private String serverCode;

    /**
     * 服务器ip
     */
    private String serverIp;

    /**
     * cpu使用情况
     */
    private String cpuUse;

    /**
     * 内存情况
     */
    private String menUse;

    /**
     * 平均负载
     */
    private String load;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date updateTime;
}

2.执行器端定义Server类

@Slf4j
@Component
public class Server implements ApplicationRunner {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 发送消息的渠道名
     */
    public static final String CPU_HEART = "CPU_HEART";


    /**
     * 执行器名称,可任意取名,不唯一
     */
    private String title="easy";

    /**
     * 若部署多个执行器,都部署在一个服务器上的话需要改变端口号
     */
    @Value("${xxl.job.executor.port}")
     private String port;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        startup();
    }


    private void startup(){
        try {
            heartbeat();
            log.info("start Quartz server...");
        } catch (Exception e) {
            log.error("start Quartz failed : " + e.getMessage(), e);
        }
    }

    /**
     * 单独开线程执行
     */
    private void heartbeat() {
        ThreadFactory threadFactory = new ThreadFactoryBuilder()
                .setDaemon(true)
                .setNameFormat("executor-heart-Thread")
                .build();
        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1, threadFactory);
        executor.setRemoveOnCancelPolicy(true);

        Runnable heartBeatThread = heartBeatThread();
        /**
         * command:执行线程
         * initialDelay:初始化延时
         * period:前一次执行结束到下一次执行开始的间隔时间(间隔执行延迟时间)
         * unit:计时单位
         * 延迟一分钟,每分钟执行一次任务
         */
        executor.scheduleAtFixedRate(heartBeatThread, 1, 1, TimeUnit.MINUTES);
    }

    /**
     *  heartbeat thread implement
     * @return
     */
    private Runnable heartBeatThread(){
        log.info("start heart beat thread...");
        return () -> {

            ServerInfoVO serverInfoVO = ServerInfoVO.builder()
                    .serverIp(IpUtils.getHost()+"-"+port)//如果在同一服务器部署多个执行器的话ip会重复,所以这里加上了端口
                    .serverCode(title)//执行器名称
                    .cpuUse(OSUtils.cpuUsage()+"%")
                    .menUse(OSUtils.memoryUsage()+"%")
                    .load(OSUtils.loadAverage())
                    .updateTime(new Date())
                    .build();
            //向redis发生消息
            stringRedisTemplate.convertAndSend(CPU_HEART,JSONObject.toJSONString(serverInfoVO));
        };
    }
}

3.在core公共端定义获取服务器资源的工具类OSUtils

@Slf4j
public class OSUtils {

    private static final SystemInfo SI = new SystemInfo();
    private static HardwareAbstractionLayer hal = SI.getHardware();
    public static final String TWO_DECIMAL = "0.00";

    /**
     * whether is windows
     * @return true if windows
     */
    public static boolean isWindows() {
        return getOSName().startsWith("Windows");
    }

    /**
     * get current OS name
     * @return current OS name
     */
    public static String getOSName() {
        return System.getProperty("os.name");
    }


    /**
     * get memory usage
     * Keep 2 decimal
     * @return  percent %
     */
    public static String memoryUsage() {
        GlobalMemory memory = hal.getMemory();
        double memoryUsage = (memory.getTotal() - memory.getAvailable() ) * 0.1 / memory.getTotal() * 10*100;

        DecimalFormat df = new DecimalFormat(TWO_DECIMAL);
        df.setRoundingMode(RoundingMode.HALF_UP);
        return df.format(memoryUsage);
    }


    /**
     * load average
     *
     * @return load average
     */
    public static String loadAverage() {
        double loadAverage =  hal.getProcessor().getSystemLoadAverage(2)[1];
        DecimalFormat df = new DecimalFormat(TWO_DECIMAL);

        df.setRoundingMode(RoundingMode.HALF_UP);
        return df.format(loadAverage);
    }


    /**
     * get cpu usage
     *
     * @return cpu usage
     */
    public static String cpuUsage() {
        CentralProcessor processor = hal.getProcessor();
        double cpuUsage = processor.getSystemCpuLoad()*100;

        DecimalFormat df = new DecimalFormat(TWO_DECIMAL);
        df.setRoundingMode(RoundingMode.HALF_UP);

        return df.format(cpuUsage);
    }



}

4.core公共端创建监听容器RedisListenerConfig

RedisMessageListenerContainer的监听流程:
用于消息监听,需要将 Topic和MessageListener 注册到 RedisMessageListenerContainer 中。
当 Topic 上有消息时,由 RedisMessageListenerContainer 通知 MessageListener,MessageListener通过 onMessage 方法拿到消息后,自行处理。

@Slf4j
@Configuration
public class RedisListenerConfig {
    /**
     * 监听容器
     *
     * @param connectionFactory connectionFactory
     * @return RedisMessageListenerContainer
     */
    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,MessageReceive listenerAdapter){
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.addMessageListener(listenerAdapter,new PatternTopic(RedisChannelConstant.CPU_HEART));
        return container;
    }
}

5.core公共端自定义监听器MessageReceive

通过 onMessage 方法拿到消息后,自行处理,写入我们的处理逻辑。

@Component
public class MessageReceive implements MessageListener {
    @Override
    public void onMessage(Message message, byte[] bytes) {
        try {
            //获取消息转化为实体类。存入map中
            ServerInfoVO serverInfoVO = JSON.parseObject(message.toString(),ServerInfoVO.class);
            ServerHelper.put(serverInfoVO.getServerIp(),serverInfoVO);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

6.core公共端定义获取map中内容ServerHelper类

public class ServerHelper {

    private static final Map<String, ServerInfoVO> maps = new ConcurrentHashMap<>();


    public static void put(String key, ServerInfoVO serverInfoVO) {
        maps.put(key, serverInfoVO);
    }


    public static List<ServerInfoVO> get() {
        List<ServerInfoVO> list = new ArrayList<>();

        Collection<ServerInfoVO> collection = maps.values();
        for (ServerInfoVO serverInfoVO : collection) {
            serverInfoVO.setServerIp(null);
            long differ = new Date().getTime() - Objects.requireNonNull(serverInfoVO.getUpdateTime()).getTime();
            if (differ > 100000) {
                maps.remove(serverInfoVO.getServerCode());
                continue;
            }

            list.add(serverInfoVO);
        }
        return list;
    }

}

7.在web端定义获取资源列表的Control:EsourceMonitorController

public class getResourceMonitorController {
  /**
     * 资源统计-资源监控列表
     */
    @PostMapping("getResourceMonitor")
    public Result getResourceMonitor(){
        return Result.success(ServerHelper.get());
    }
    }

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于SpringBoot实现Redis监听器的问题,可以参考以下步骤: 1. 添加相关依赖 在pom.xml文件中添加如下依赖: ``` <dependency>     <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 2. 创建监听器 创建一个类,实现org.springframework.data.redis.connection.MessageListener接口,并在该类中重写onMessage方法,监听Redis中指定key的变化。 ``` @Component public class RedisMessageListener implements MessageListener { @Override public void onMessage(Message message, byte[] pattern) { // 监听到key的变化后,在这里实现具体的操作 } } ``` 3. 配置监听器 在Spring Boot的配置类中,注入RedisMessageListener,并通过RedisConnectionFactory创建监听器容器,并指定需要监听的key。 ``` @Configuration public class RedisConfig { @Autowired private RedisMessageListener redisMessageListener; @Bean MessageListenerAdapter listenerAdapter() { return new MessageListenerAdapter(redisMessageListener); } @Bean RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(connectionFactory); container.addMessageListener(listenerAdapter(), new PatternTopic("your_key_pattern")); return container; } } ``` 4. 测试 监听器配置完成后,可以通过RedisTemplate向指定key写入数据,验证是否能够监听到key的变化。 以上就是SpringBoot实现Redis监听器的基本步骤。如有疑问,请随时向我提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值