多数据源SpringBoot应用集成ElasticJob3.0.4并实现作业事件追踪【最佳实践】

发布于:2025-02-11 ⋅ 阅读:(54) ⋅ 点赞:(0)

一、#创作灵感#

为了在多数据源的SpringBoot应用中实现ElasticJob3.0.4事件追踪各种捣腾,固写下此笔记以巩固知识要点

二、环境

- SpringBoot 2.7.18   官方下载地址:SpringBoot 2.7.18

- ElasticJob 3.0.4   官方下载地址:ElasticJob 3.0.4

- ElasticJob-UI 3.0.2 图形化工具  官方下载地址:ElasticJob-UI 3.0.2

- Nacos 2.2.3   官方下载地址:Nacos 2.2.3

- Oracle JDK8u202(Oracle JDK8最后一个非商业版本)   下载地址:Oracle JDK8u202

三、POM依赖

    <!--  elasticjob依赖  -->
    <dependency>
        <groupId>org.apache.shardingsphere.elasticjob</groupId>
        <artifactId>elasticjob-lite-spring-boot-starter</artifactId>
        <version>3.0.4</version>
    </dependency>

四、数据源配置

我的配置放在nacos中的,格式是properties

四个数据源配置如下:

# @author brick man
# clickhouse 时序数据库
spring.datasource.clickhouse.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.clickhouse.driver-class-name=com.clickhouse.jdbc.ClickHouseDriver
spring.datasource.clickhouse.jdbc-url=jdbc:clickhouse://********:8123/real_saas_health_degree
spring.datasource.clickhouse.username=saas_health
spring.datasource.clickhouse.password=******
# 是允许连接在连接池中空闲的数量
spring.datasource.clickhouse.minimum-idle=5
# 是允许连接在连接池中空闲的最长时间(以毫秒为单位)
spring.datasource.clickhouse.idle-timeout=600000
# 配置最大池大小
spring.datasource.clickhouse.maximum-pool-size=20
# 配置从池返回的连接的默认自动提交行为。默认值为true
spring.datasource.clickhouse.auto-commit=true
# 连接池的名称
spring.datasource.clickhouse.pool-name=MyHikariCP
# 池中连接关闭后的最长生命周期(以毫秒为单位)
spring.datasource.clickhouse.max-lifetime=1800000
# 是客户端等待连接池连接的最大毫秒数
spring.datasource.clickhouse.connection-timeout=120000
# 开启连接监测泄露 本地网络耗时大设长一点15s,生产可设5s
spring.datasource.clickhouse.leak-detection-threshold=15000
# 测试连接数据库  
spring.datasource.clickhouse.connection-test-query=select version();

# mysql数据库存AI平台主数据
spring.datasource.mysql-ai.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.mysql-ai.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.mysql-ai.jdbc-url=jdbc:mysql://******:3307/sml
spring.datasource.mysql-ai.username=sml
spring.datasource.mysql-ai.password=******

# pg数据库存业务统计数据
spring.datasource.postgresql-gatherds.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.postgresql-gatherds.driver-class-name=org.postgresql.Driver
spring.datasource.postgresql-gatherds.jdbc-url=jdbc:postgresql://******:18921/lte_hjdb
spring.datasource.postgresql-gatherds.username=crm_qry
spring.datasource.postgresql-gatherds.password=******

# mysql数据库存elasticjob事件追踪数据
spring.datasource.mysql-elasticjob.jdbc-url=jdbc:mysql://******:3307/elasticjob?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
spring.datasource.mysql-elasticjob.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.mysql-elasticjob.username=elasticjob
spring.datasource.mysql-elasticjob.password=******

五、ElasticJob追踪配置

# author brick man
# 持久化类型 RDB: relation database -- 关系型数据库
elasticjob.tracing.type=RDB
# 数据源配置前缀,作者这里集成时不知何故未生效,最终通过把MySQL-elasticjob数据源设置为主数据源(@Primary)才集成成功
elasticjob.tracing.data-source=spring.datasource.clickhouse

到这里所有集成工作就已经完成

特别注意:

1、新版本的elasticjob集成时不需要创建作业配置类(老版本需要)

2、作者这里可能因为springboot版本的差异把elasticjob数据源设置为主数据源才成功(希望读者用的springboot3的最新版本,这样会比我幸运)

3、elasticjob的配置可借助intelJ等IDE的配置联想功能查看有哪些配置(官方配置文档这个配置不太好找、配置说明也不一定完备)

六、指定主数据源(非必须)

上面的步骤如果已经集成成功可跳过这一步

条件:ElasticJob使用了上面指定的数据源配置且应用启动不报错(可跳过这一步)

通过@Primary 注解将数据源标记为主数据源

1、数据源配置类

import com.******.nctc.common.configuration.MySQLElasticJobDataSource;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;

/**
 * @Description: MySQL 数据源配置类
 * @Author: brick man
 * @CreateDate: 2024/12/31
 * @Version: 1.0
 */
@Configuration
@MapperScan(basePackages = "com.******.nctc.elasticjob.mapper",
        annotationClass = MySQLElasticJobDataSource.class,
        sqlSessionFactoryRef = "mysqlElasticJobSessionFactory")
public class MySQLElasticJobDataSourceConfig {

    @Bean(name = "mysqlElasticJobDataSource")
    @Primary // 将该数据源标记为主数据源
    @ConfigurationProperties("spring.datasource.mysql-elasticjob")
    public DataSource mysqlElasticJobDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "mysqlElasticJobSessionFactory")
    public SqlSessionFactory mysqlElasticJobSqlSessionFactory(@Qualifier("mysqlElasticJobDataSource") DataSource dataSource) throws Exception {
        MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setSqlInjector(new DefaultSqlInjector());
        sqlSessionFactoryBean.setGlobalConfig(globalConfig);
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        Interceptor[] plugins = {interceptor};
        sqlSessionFactoryBean.setPlugins(plugins);
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource[] resources = resolver.getResources("classpath:mapper/elasticjob/*.xml");
        sqlSessionFactoryBean.setMapperLocations(resources);
        MybatisConfiguration configuration = new MybatisConfiguration();
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setCallSettersOnNulls(true);

        sqlSessionFactoryBean.setConfiguration(configuration);
        return sqlSessionFactoryBean.getObject();
    }

    @Bean("mysqlElasticJobSqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("mysqlElasticJobSessionFactory") SqlSessionFactory sessionFactory) {
        return new SqlSessionTemplate(sessionFactory);
    }
}

2、数据源注解类

import java.lang.annotation.*;

/**
 * @Target({ElementType.TYPE})  表示该注解只在类上生效
 * @Retention(RetentionPolicy.RUNTIME)  表示该注解在运行时有效
 * @Documented 该注解会被包含在 Javadoc 中产生的文档中
 * @author brick man
 * @date 20241231
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MySQLElasticJobDataSource {
}

注意

     作者这里调整了原来的主数据源,为了避免工程现在功能出现问题,需要对所有mapper指定数据源

七、elasticjob-3.0.2-ui

1、下载elasticjob-3.0.2-ui

下载:见前面第二节 环境 的下载连接

2、安装elasticjob-3.0.2-ui

选择适合自己的版本后解压--->修改数据,启动即可(需要jdk8+)

作者用的:elasticjob-3.0.2-lite-ui-bin.tar.gz

-(1) 数据库驱动放ext-lib目录

解压后需要将对应数据库驱动放ext-lib目录

作者这里用的mysql存储,所以把mysql驱动包放ext-lib目录

-(2)修改配置

作者的配置示例:

server.port=8089

# web 控制台张米
auth.username=root
auth.password=******
auth.token_expires_after_seconds=3600

spring.datasource.default.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.default.url=jdbc:mysql://localhost:3306/elasticjob?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
# 数据库张米
spring.datasource.default.username=elasticjob
spring.datasource.default.password=******

spring.jpa.show-sql=false

## Uncomment the following property to allow adding DataSource dynamically.
dynamic.datasource.allowed-driver-classes={'org.h2.Driver','org.postgresql.Driver','com.mysql.cj.jdbc.Driver'}

-(3) start.sh脚本JVM参数调整

-  -Xss参数调整为512k,默认太小,一般启动会报错

-(4) start.sh脚本指定jdk环境变量

- 如果机器上有jdk8+环境变量可跳过

- jdk17会报错因为starts.h脚本中个别jvm参数只有8支持

- 解决覆盖PATH环境变量JDK8环境变量不生效的问题(还是JDK17),如果机器的环境变量是17且采用的是程序全量安装的方式安装(桌面、程序组都有),可参考作者下面的的方式(把java命令替换成jdk8的java脚本的绝对路径)解决

作者修改后的脚本如下:

SERVER_NAME=ShardingSphere-ElasticJob-UI

# 指定JAVA_HOME
export JAVA_HOME=/usr/java/jdk1.8.0_202-amd64
export PATH=/bin:/usr/sbin:/sbin:/usr/local/sbin::$HOME/.local/bin:$JAVA_HOME/bin:/usr/bin
export JAVA_HOME
# 作者上面修改了环境变量(大部分情况下能生效),但服务器上下面这句输出的依然是open jdk17
# 故作者在后面执行java时使用了jdk8的绝对路径
echo `/usr/java/jdk1.8.0_202-amd64/bin/java -version`


cd `dirname $0`
cd ..
DEPLOY_DIR=`pwd`

LOGS_DIR=${DEPLOY_DIR}/logs
if [ ! -d ${LOGS_DIR} ]; then
    mkdir ${LOGS_DIR}
fi

STDOUT_FILE=${LOGS_DIR}/stdout.log

PIDS=`ps -ef | grep java | grep "$DEPLOY_DIR" | grep -v grep | awk '{print $2}'`
if [ -n "$PIDS" ]; then
    echo "ERROR: The $SERVER_NAME already started!"
    echo "PID: $PIDS"
    exit 1
fi

CLASS_PATH=.:${DEPLOY_DIR}/conf:${DEPLOY_DIR}/lib/*:${DEPLOY_DIR}/ext-lib/*
JAVA_OPTS=" -server -Xmx1g -Xms1g -Xmn512m -Xss512k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 "

MAIN_CLASS=org.apache.shardingsphere.elasticjob.lite.ui.Bootstrap
echo "Starting the $SERVER_NAME ..."

#  使用了jdk8的绝对路径解决环境变量问题
nohup /usr/java/jdk1.8.0_202-amd64/bin/java ${JAVA_OPTS} -classpath ${CLASS_PATH} ${MAIN_CLASS} > ${STDOUT_FILE} 2>&1 &
sleep 1
echo "Please check the STDOUT file: $STDOUT_FILE"

3、启动elasticjob-3.0.2-ui

${ElasticjobUI_HOME}/bin/start.sh

4、登陆elasticjob-3.0.2-ui

5、添加注册中心配置

6、查看所有作业

7、作业执行事件追踪

- 历史轨迹

可查看每个作业每次执行的起止时间(从而可计算出耗时)

- 查询耗时超过1分钟的Job名及次数

通过该类查询看是否有耗时超过预期的作业,从而针对性的分析优化

-- 查询耗时超过1分钟的Job名及次数
select job_name,count(0) 
  from JOB_EXECUTION_LOG 
 where complete_time-start_time>60
 group by job_name

八、知识点总结

1、elasticjob数据源的指定(不指定默认使用主数据源)

2、elasticjob不同的版本使用各不相同(一般较新版本使用会更简单,配置更少)

3、elasticjob的配置可借助intelJ等IDE的配置联想功能查看有哪些配置(官方配置文档并不发找、配置说明也不一定完备)

4、java环境变量问题可通过shell脚本中java命令用jdk8的绝对路径代替

九、其他相关重要知识点

1、任务分继承SimpleJob类的任务、继承DataflowJob的任务

2、elasticjob任务分片后同一个实例上运行的多个片是并行执行的。



网站公告

今日签到

点亮在社区的每一天
去签到