CACHECLOUDV1.0慢日志定时任务创建流程分析

缓存私有云的github地址 https://github.com/sohutv/cachecloud.git ,此处分析的源码是tag1.0的源码,2.0的实现完全不一样。

spring-load.xml中的配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        " default-autowire="byName">

    <!--初始化加载已有实例,测试时禁用-->
    <bean class="com.sohu.cache.init.RedisInitLoad" init-method="init" />
    <bean class="com.sohu.cache.init.MachineInitLoad" init-method="init" />
</beans>

在spring-local.xml中是没有引入这个配置的,测试时禁用了,在这个配置中增加这个引用即和线上一样

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <import resource="classpath:spring/spring-config.xml"/>
    <import resource="classpath:spring/spring-quartz.xml"/>
  	<!-- 增加 spring-load.xml的配置-->
    <import resource="classpath:spring/spring-load.xml"/>
    <import resource="classpath:spring/spring-mybatis.xml"/>
    <import resource="classpath:spring/spring-service.xml"/>
    <import resource="classpath:spring/spring-data.xml"/>
    <import resource="classpath:spring/spring-manage.xml"/>
    <import resource="classpath:spring/spring-mvc.xml"/>
    <import resource="classpath:spring/spring-jmx.xml"/>
    <import resource="classpath:spring/spring-alert.xml"/>
    <import resource="classpath:spring/spring-client-report.xml"/>
    <import resource="classpath:spring/spring-inspector.xml"/>
    <import resource="classpath:spring/spring-gcache.xml"/>
    <import resource="classpath:spring/spring-monitor.xml"/>
    <import resource="classpath:spring/spring-gmq.xml"/>
</beans>

启动后会调用 RedisInitLoad类的init方法,debug判断要去掉,否则本地可能会无法进入部署慢日志收集任务方法

public void init() {
        if (ConstUtils.IS_DEBUG) {
            logger.warn("isDebug=true return");
            return;
        }
        ……省略……

RedisInitLoad类的init方法中调用initByType方法创建慢日志收集的触发器。

private void initByType(int type) {
        List<InstanceInfo> instanceInfoList = instanceDao.getInstListByType(type);
        for (InstanceInfo instanceInfo : instanceInfoList) {
                    instanceInfo.getPort());
            if (TypeUtil.isRedisSentinel(instanceInfo.getType())) {
                continue;
            }
            String host = instanceInfo.getIp();
            int port = instanceInfo.getPort();
            Long appId = instanceInfo.getAppId();
            redisCenter.deployRedisCollection(appId, host, port);
          	//这里给每个实例增加慢日志收集的job
            redisCenter.deployRedisSlowLogCollection(appId, host, port);
        }
        logger.info("init redis type={} deploy instance done.", type);
    }

RedisCenterImpl的deployRedisSlowLogCollection方法部署定时任务

    @Override
    public boolean deployRedisSlowLogCollection(long appId, String host, int port) {
        Assert.isTrue(appId > 0);
        Assert.hasText(host);
        Assert.isTrue(port > 0);
        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put(ConstUtils.HOST_KEY, host);
        dataMap.put(ConstUtils.PORT_KEY, port);
        dataMap.put(ConstUtils.APP_KEY, appId);
        JobKey jobKey = JobKey.jobKey(ConstUtils.REDIS_SLOWLOG_JOB_NAME, ConstUtils.REDIS_SLOWLOG_JOB_GROUP);
        TriggerKey triggerKey = TriggerKey.triggerKey(ObjectConvert.linkIpAndPort(host, port), ConstUtils.REDIS_SLOWLOG_TRIGGER_GROUP + appId);
        boolean result = schedulerCenter.deployJobByCron(jobKey, triggerKey, dataMap, ScheduleUtil.getRandomHourCron(appId), false);
        return result;
    }

SchedulerCenter的实现类SchedulerCenterImpl中,注入了 clusterScheduler,这个bean是在spring-quartz.xml中定义的

    <!-- 分布式QuartzScheduler -->
    <bean id="clusterScheduler" name="clusterScheduler" lazy-init="false" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="dataSource" ref="cacheCloudDB"></property>
        <property name="taskExecutor" ref="quartzThreadPool"/>
        <!--
        <property name="transactionManager" ref="transactionManager"/>
        -->
        <property name="quartzProperties">
            <props>
                <prop key="org.quartz.scheduler.instanceName">CacheCloudScheduler</prop>
                <prop key="org.quartz.scheduler.instanceId">AUTO</prop>
                <prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
                <prop key="org.quartz.jobStore.driverDelegateClass">org.quartz.impl.jdbcjobstore.StdJDBCDelegate</prop>
                <!-- 表名前缀 -->
                <prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
                <prop key="org.quartz.jobStore.isClustered">${isClustered}</prop>
                <prop key="org.quartz.jobStore.clusterCheckinInterval">15000</prop>
                <prop key="org.quartz.jobStore.maxMisfiresToHandleAtATime">120</prop>
                <prop key="org.quartz.jobStore.misfireThreshold">60000</prop>
                <!-- 打开JMX 配置 -->
                <prop key="org.quartz.scheduler.jmx.export">true</prop>
                <prop key="org.quartz.plugin.shutdownHook.class">org.quartz.plugins.management.ShutdownHookPlugin</prop>
                <prop key="org.quartz.plugin.shutdownHook.cleanShutdown">true</prop>
                <prop key="org.terracotta.quartz.skipUpdateCheck">true</prop>
                <!--<prop key="org.quartz.plugin.triggHistory.class">org.quartz.plugins.history.LoggingJobHistoryPlugin</prop>-->

            </props>
        </property>
        <property name="schedulerName" value="CacheCloudScheduler"/>
        <property name="applicationContextSchedulerContextKey" value="applicationContext"/>
        <property name="overwriteExistingJobs" value="true"/>
        <property name="waitForJobsToCompleteOnShutdown" value="false"/>
        <property name="startupDelay" value="10"/>
        <property name="autoStartup" value="true"/>
        <property name="triggers">
            <array>
                <ref bean="cleanUpStatisticsTrigger"/>
                <ref bean="hostInspectorTrigger"/>
                <ref bean="appInspectorTrigger"/>
                <ref bean="appDailyTrigger"/>
            </array>
        </property>
        <property name="jobDetails">
            <array>
                <ref bean="redisJobDetail"/>
                <ref bean="machineJobDetail"/>
                <ref bean="serverJobDetail"/>
                <ref bean="machineMonitorJobDetail"/>
                <ref bean="redisSlowLogJobDetail"/>
                <ref bean="cleanUpStatisticsJobDetail"/>
                <ref bean="inspectorJobDetail"/>
                <ref bean="appDailyJobDetail"/>
            </array>
        </property>

    </bean>

部署定时任务

    @Override
    public boolean deployJobByCron(JobKey jobKey, TriggerKey triggerKey, Map<String, Object> dataMap, String cron, boolean replace) {
        Assert.isTrue(jobKey != null);
        Assert.isTrue(triggerKey != null);
        Assert.isTrue(CronExpression.isValidExpression(cron), "invalid cron = " + cron);
        try {
        		//获取相应的任务执行器
            JobDetail jobDetail = clusterScheduler.getJobDetail(jobKey);
            if (jobDetail == null) {
                logger.error("JobKey {}:{} is not exist", jobKey.getName(), jobKey.getGroup());
                return false;
            }
            //在这里创建定时触发任务
            fireCronTrigger(triggerKey, jobDetail, cron, replace, dataMap);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return false;
        }

        return true;
    }

激活触发器

    private boolean fireCronTrigger(TriggerKey triggerKey, JobDetail jobDetail, String cron, boolean replace, Map<String, Object> dataMap) {
        try {
            boolean isExists = clusterScheduler.checkExists(triggerKey);
            if (isExists) {
                if (replace) {
                    logger.warn("replace trigger={}:{} ", triggerKey.getName(), triggerKey.getGroup());
                    clusterScheduler.unscheduleJob(triggerKey);
                } else {
                    logger.info("exist trigger={}:{} ", triggerKey.getName(), triggerKey.getGroup());
                    return false;
                }
            }
            Date startDate = DateUtils.addSeconds(new Date(), 20);
          	//组建定时任务触发器
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(triggerKey)
                    .forJob(jobDetail)
                    .withSchedule(CronScheduleBuilder.cronSchedule(cron))
                    .startAt(startDate)
                    .build();
            if (dataMap != null && dataMap.size() > 0) {
                trigger.getJobDataMap().putAll(dataMap);
            }
            clusterScheduler.scheduleJob(trigger);
        } catch (SchedulerException e) {
            logger.error(e.getMessage(), e);
            return false;
        }
        return true;
    }

这里看的触发器的时间是每个小时的随机某分钟某秒,直接从实例服务器获取最新100条慢日志

        // 从redis中获取慢查询日志,直接从服务器获取最新100条慢日志
        List<RedisSlowLog> redisLowLogList = getRedisSlowLogs(host, port, 100);
        if (CollectionUtils.isEmpty(redisLowLogList)) {
            return Collections.emptyList();
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值