一、SnailJob介绍

SnailJob 是一款布式任务调度和分布式重试平台

分布式重试

  1. 多模式:本地、远程、混合重试
  2. 多策略:指数退避、固定间隔、CRON、最大重试次数
  3. 异常处理:支持异常白名单/黑名单、自动降级
  4. 死信队列:失败任务自动转入,支持手动回滚
  5. 重试风暴防护:跨服务流量管控、单机重试管控、后台数据管控
  6. 多渠道通知:飞书、钉钉、企业微信、邮件、Webhook
  7. 重试完成回调:支持自定义回调处理
  8. 幂等ID:支持业务幂等ID配置,防止重复执行

任务调度

  1. 多样调度:CRON、秒级、固定频率
  2. 执行模式:集群、广播、静态、Map、MapReduce
  3. 路由策略:轮询、LRU、随机、一致性哈希、第一个、最后一个
  4. 阻塞策略:丢弃、覆盖、并行、恢复
  5. 实时监控:任务状态、执行日志、失败告警
  6. 任务生命周期:暂停、恢复、终止、手动触发
  7. 多任务类型:HTTP、Shell、CMD、PowerShell
  8. API调度:支持OpenAPI远程触发

工作流编排

  1. 可视化流程:仿钉钉工作流编排,所见即所得
  2. 多节点类型:任务节点、决策节点
  3. 流程监控:实时查看流程进度与日志
  4. 阻塞策略:丢弃、覆盖、并行、恢复
  5. 上下文:支持全流程工作流上下文传递
  6. 多样调度:CRON、固定频率
  7. 决策表达式:Spel、Aviator、QL等
  8. 超时管理:支持按需配置执行的超时时间

系统特性

  1. 高可用:分区分桶架构,支持无限水平扩展
  2. 安全权限:多层级权限、租户隔离、操作审计
  3. 多语言支持:Java、Python、Go 原生客户端
  4. 低接入成本:仅依赖数据库,易集成、易维护
  5. 现代UI:可视化管理、实时监控、失败排名
  6. 丰富API:开放API,便于系统集成与自动化
  7. 社区活跃:文档完善、案例丰富、响应及时

可用以消息队列场景、回调、异步场景

项目地址:https://github.com/aizuda/snail-job

使用

  • 客户端JDK版本:JDK17
  • SpringBoot版本: (SpringBoot v3.X),

同类产品对比

二、SnailJob服务器启动

基于版本1.10.0

1、添加maven依赖

<dependency>
    <groupId>com.aizuda</groupId>
    <artifactId>snail-job-server-starter</artifactId>
    <version>${snail-job.version}</version>
</dependency>

2、执行脚本,创建数据库:

SET NAMES utf8mb4;

DROP DATABASE IF EXISTS snail_job;
CREATE DATABASE snail_job;
USE snail_job;

CREATE TABLE `sj_namespace`
(
    `id`          bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `name`        varchar(64)         NOT NULL COMMENT '名称',
    `unique_id`   varchar(64)         NOT NULL COMMENT '唯一id',
    `description` varchar(256)        NOT NULL DEFAULT '' COMMENT '描述',
    `deleted`     tinyint(4)          NOT NULL DEFAULT 0 COMMENT '逻辑删除 1、删除',
    `create_dt`   datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_dt`   datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    PRIMARY KEY (`id`),
    KEY `idx_name` (`name`),
    UNIQUE KEY `uk_unique_id` (`unique_id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COMMENT ='命名空间';

INSERT INTO `sj_namespace` (`id`, `name`, `unique_id`, `create_dt`, `update_dt`, `deleted`)
VALUES (1, 'Default', '764d604ec6fc45f68cd92514c40e9e1a', now(), now(), 0);


CREATE TABLE `sj_group_config`
(
    `id`                bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `namespace_id`      varchar(64)         NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
    `group_name`        varchar(64)         NOT NULL DEFAULT '' COMMENT '组名称',
    `description`       varchar(256)        NOT NULL DEFAULT '' COMMENT '组描述',
    `token`             varchar(64)         NOT NULL DEFAULT 'SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT' COMMENT 'token',
    `group_status`      tinyint(4)          NOT NULL DEFAULT 0 COMMENT '组状态 0、未启用 1、启用',
    `version`           int(11)             NOT NULL COMMENT '版本号',
    `group_partition`   int(11)             NOT NULL COMMENT '分区',
    `id_generator_mode` tinyint(4)          NOT NULL DEFAULT 1 COMMENT '唯一id生成模式 默认号段模式',
    `init_scene`        tinyint(4)          NOT NULL DEFAULT 0 COMMENT '是否初始化场景 0:否 1:是',
    `create_dt`         datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_dt`         datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    PRIMARY KEY (`id`),
    UNIQUE KEY `uk_namespace_id_group_name` (`namespace_id`, `group_name`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 0
  DEFAULT CHARSET = utf8mb4 COMMENT ='组配置'
;

CREATE TABLE `sj_notify_config`
(
    `id`                     bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `namespace_id`           varchar(64)         NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
    `group_name`             varchar(64)         NOT NULL COMMENT '组名称',
    `notify_name`            varchar(64)         NOT NULL DEFAULT '' COMMENT '通知名称',
    `system_task_type`       tinyint(4)          NOT NULL DEFAULT 3 COMMENT '任务类型 1. 重试任务 2. 重试回调 3、JOB任务 4、WORKFLOW任务',
    `notify_status`          tinyint(4)          NOT NULL DEFAULT 0 COMMENT '通知状态 0、未启用 1、启用',
    `recipient_ids`          varchar(128)        NOT NULL COMMENT '接收人id列表',
    `notify_threshold`       int(11)             NOT NULL DEFAULT 0 COMMENT '通知阈值',
    `notify_scene`           tinyint(4)          NOT NULL DEFAULT 0 COMMENT '通知场景',
    `rate_limiter_status`    tinyint(4)          NOT NULL DEFAULT 0 COMMENT '限流状态 0、未启用 1、启用',
    `rate_limiter_threshold` int(11)             NOT NULL DEFAULT 0 COMMENT '每秒限流阈值',
    `description`            varchar(256)        NOT NULL DEFAULT '' COMMENT '描述',
    `create_dt`              datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_dt`              datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    PRIMARY KEY (`id`),
    KEY `idx_namespace_id_group_name_scene_name` (`namespace_id`, `group_name`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 0
  DEFAULT CHARSET = utf8mb4 COMMENT ='通知配置'
;

CREATE TABLE `sj_notify_recipient`
(
    `id`               bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `namespace_id`     varchar(64)         NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
    `recipient_name`   varchar(64)         NOT NULL COMMENT '接收人名称',
    `notify_type`      tinyint(4)          NOT NULL DEFAULT 0 COMMENT '通知类型 1、钉钉 2、邮件 3、企业微信 4 飞书 5 webhook',
    `notify_attribute` varchar(512)        NOT NULL COMMENT '配置属性',
    `description`      varchar(256)        NOT NULL DEFAULT '' COMMENT '描述',
    `create_dt`        datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_dt`        datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    PRIMARY KEY (`id`),
    KEY `idx_namespace_id` (`namespace_id`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 0
  DEFAULT CHARSET = utf8mb4 COMMENT ='告警通知接收人'
;

CREATE TABLE `sj_retry_dead_letter`
(
    `id`              bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `namespace_id`    varchar(64)         NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
    `group_name`      varchar(64)         NOT NULL COMMENT '组名称',
    `group_id`        bigint(20)          NOT NULL COMMENT '组Id',
    `scene_name`      varchar(64)         NOT NULL COMMENT '场景名称',
    `scene_id`        bigint(20)          NOT NULL COMMENT '场景ID',
    `idempotent_id`   varchar(64)         NOT NULL COMMENT '幂等id',
    `biz_no`          varchar(64)         NOT NULL DEFAULT '' COMMENT '业务编号',
    `executor_name`   varchar(512)        NOT NULL DEFAULT '' COMMENT '执行器名称',
    -- jackson 兼容历史数据 预计1.8.0默认改为fury
    `serializer_name` varchar(32)         NOT NULL DEFAULT 'jackson' COMMENT '执行方法参数序列化器名称',
    `args_str`        text                NOT NULL COMMENT '执行方法参数',
    `ext_attrs`       text                NOT NULL COMMENT '扩展字段',
    `create_dt`       datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    PRIMARY KEY (`id`),
    KEY `idx_namespace_id_group_name_scene_name` (`namespace_id`, `group_name`, `scene_name`),
    KEY `idx_idempotent_id` (`idempotent_id`),
    KEY `idx_biz_no` (`biz_no`),
    KEY `idx_create_dt` (`create_dt`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 0
  DEFAULT CHARSET = utf8mb4 COMMENT ='死信队列表'
;

CREATE TABLE `sj_retry`
(
    `id`              bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `namespace_id`    varchar(64)         NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
    `group_name`      varchar(64)         NOT NULL COMMENT '组名称',
    `group_id`        bigint(20)          NOT NULL COMMENT '组Id',
    `scene_name`      varchar(64)         NOT NULL COMMENT '场景名称',
    `scene_id`        bigint(20)          NOT NULL COMMENT '场景ID',
    `idempotent_id`   varchar(64)         NOT NULL COMMENT '幂等id',
    `biz_no`          varchar(64)         NOT NULL DEFAULT '' COMMENT '业务编号',
    `executor_name`   varchar(512)        NOT NULL DEFAULT '' COMMENT '执行器名称',
    `args_str`        text                NOT NULL COMMENT '执行方法参数',
    `ext_attrs`       text                NOT NULL COMMENT '扩展字段',
    -- jackson 兼容历史数据 预计1.8.0默认改为fury
    `serializer_name` varchar(32)         NOT NULL DEFAULT 'jackson' COMMENT '执行方法参数序列化器名称',
    `next_trigger_at` bigint(13)          NOT NULL COMMENT '下次触发时间',
    `retry_count`     int(11)             NOT NULL DEFAULT 0 COMMENT '重试次数',
    `retry_status`    tinyint(4)          NOT NULL DEFAULT 0 COMMENT '重试状态 0、重试中 1、成功 2、最大重试次数',
    `task_type`       tinyint(4)          NOT NULL DEFAULT 1 COMMENT '任务类型 1、重试数据 2、回调数据',
    `bucket_index`    int(11)             NOT NULL DEFAULT 0 COMMENT 'bucket',
    `parent_id`       bigint(20)          NOT NULL DEFAULT 0 COMMENT '父节点id',
    `deleted`         bigint(20)          NOT NULL DEFAULT 0 COMMENT '逻辑删除',
    `create_dt`       datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_dt`       datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    PRIMARY KEY (`id`),
    KEY `idx_biz_no` (`biz_no`),
    KEY `idx_idempotent_id` (`idempotent_id`),
    KEY `idx_retry_status_bucket_index` (`retry_status`, `bucket_index`),
    KEY `idx_parent_id` (`parent_id`),
    KEY `idx_create_dt` (`create_dt`),
    UNIQUE KEY `uk_scene_tasktype_idempotentid_deleted` (`scene_id`, `task_type`, `idempotent_id`, `deleted`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 0
  DEFAULT CHARSET = utf8mb4 COMMENT ='重试信息表'
;

CREATE TABLE `sj_retry_task`
(
    `id`               bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `namespace_id`     varchar(64)         NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
    `group_name`       varchar(64)         NOT NULL COMMENT '组名称',
    `scene_name`       varchar(64)         NOT NULL COMMENT '场景名称',
    `retry_id`         bigint(20)          NOT NULL COMMENT '重试信息Id',
    `ext_attrs`        text                NOT NULL COMMENT '扩展字段',
    `task_status`      tinyint(4)          NOT NULL DEFAULT 1 COMMENT '重试状态',
    `task_type`        tinyint(4)          NOT NULL DEFAULT 1 COMMENT '任务类型 1、重试数据 2、回调数据',
    `operation_reason` tinyint(4)          NOT NULL DEFAULT 0 COMMENT '操作原因',
    `client_info`      varchar(128)                 DEFAULT NULL COMMENT '客户端地址 clientId#ip:port',
    `create_dt`        datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_dt`        datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    PRIMARY KEY (`id`),
    KEY `idx_group_name_scene_name` (`namespace_id`, `group_name`, `scene_name`),
    KEY `task_status` (`task_status`),
    KEY `idx_create_dt` (`create_dt`),
    KEY `idx_retry_id` (`retry_id`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 0
  DEFAULT CHARSET = utf8mb4 COMMENT ='重试任务表'
;

CREATE TABLE `sj_retry_task_log_message`
(
    `id`            bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `namespace_id`  varchar(64)         NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
    `group_name`    varchar(64)         NOT NULL COMMENT '组名称',
    `retry_id`      bigint(20)          NOT NULL COMMENT '重试信息Id',
    `retry_task_id` bigint(20)          NOT NULL COMMENT '重试任务Id',
    `message`       longtext            NOT NULL COMMENT '异常信息',
    `log_num`       int(11)             NOT NULL DEFAULT 1 COMMENT '日志数量',
    `real_time`     bigint(13)          NOT NULL DEFAULT 0 COMMENT '上报时间',
    `create_dt`     datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    PRIMARY KEY (`id`),
    KEY `idx_namespace_id_group_name_retry_task_id` (`namespace_id`, `group_name`, `retry_task_id`),
    KEY `idx_create_dt` (`create_dt`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 0
  DEFAULT CHARSET = utf8mb4 COMMENT ='任务调度日志信息记录表'
;

CREATE TABLE `sj_retry_scene_config`
(
    `id`                  bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `namespace_id`        varchar(64)         NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
    `scene_name`          varchar(64)         NOT NULL COMMENT '场景名称',
    `group_name`          varchar(64)         NOT NULL COMMENT '组名称',
    `scene_status`        tinyint(4)          NOT NULL DEFAULT 0 COMMENT '组状态 0、未启用 1、启用',
    `max_retry_count`     int(11)             NOT NULL DEFAULT 5 COMMENT '最大重试次数',
    `back_off`            tinyint(4)          NOT NULL DEFAULT 1 COMMENT '1、默认等级 2、固定间隔时间 3、CRON 表达式',
    `trigger_interval`    varchar(16)         NOT NULL DEFAULT '' COMMENT '间隔时长',
    `notify_ids`          varchar(128)        NOT NULL DEFAULT '' COMMENT '通知告警场景配置id列表',
    `deadline_request`    bigint(20) unsigned NOT NULL DEFAULT 60000 COMMENT 'Deadline Request 调用链超时 单位毫秒',
    `executor_timeout`    int(11) unsigned    NOT NULL DEFAULT 5 COMMENT '任务执行超时时间,单位秒',
    `route_key`           tinyint(4)          NOT NULL DEFAULT 4 COMMENT '路由策略',
    `block_strategy`      tinyint(4)          NOT NULL DEFAULT 1 COMMENT '阻塞策略 1、丢弃 2、覆盖 3、并行',
    `cb_status`           tinyint(4)          NOT NULL DEFAULT 0 COMMENT '回调状态 0、不开启 1、开启',
    `cb_trigger_type`     tinyint(4)          NOT NULL DEFAULT 1 COMMENT '1、默认等级 2、固定间隔时间 3、CRON 表达式',
    `cb_max_count`        int(11)             NOT NULL DEFAULT 16 COMMENT '回调的最大执行次数',
    `cb_trigger_interval` varchar(16)         NOT NULL DEFAULT '' COMMENT '回调的最大执行次数',
    `owner_id`            bigint(20)          NULL     DEFAULT NULL COMMENT '负责人id',
    `labels`              varchar(512)        NULL     DEFAULT '' COMMENT '标签',
    `description`         varchar(256)        NOT NULL DEFAULT '' COMMENT '描述',
    `create_dt`           datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_dt`           datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    PRIMARY KEY (`id`),
    UNIQUE KEY `uk_namespace_id_group_name_scene_name` (`namespace_id`, `group_name`, `scene_name`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 0
  DEFAULT CHARSET = utf8mb4 COMMENT ='场景配置'
;

CREATE TABLE `sj_server_node`
(
    `id`           bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `namespace_id` varchar(64)         NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
    `group_name`   varchar(64)         NOT NULL COMMENT '组名称',
    `host_id`      varchar(64)         NOT NULL COMMENT '主机id',
    `host_ip`      varchar(64)         NOT NULL COMMENT '机器ip',
    `host_port`    int(16)             NOT NULL COMMENT '机器端口',
    `expire_at`    datetime            NOT NULL COMMENT '过期时间',
    `node_type`    tinyint(4)          NOT NULL COMMENT '节点类型 1、客户端 2、是服务端',
    `ext_attrs`    varchar(256)        NULL     DEFAULT '' COMMENT '扩展字段',
    `labels`       varchar(512)        NULL     DEFAULT '' COMMENT '标签',
    `create_dt`    datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_dt`    datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    PRIMARY KEY (`id`),
    KEY `idx_namespace_id_group_name` (`namespace_id`, `group_name`),
    KEY `idx_expire_at_node_type` (`expire_at`, `node_type`),
    UNIQUE KEY `uk_host_id_host_ip` (`host_id`, `host_ip`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 0
  DEFAULT CHARSET = utf8mb4 COMMENT ='服务器节点'
;

CREATE TABLE `sj_distributed_lock`
(
    `name`       varchar(64)  NOT NULL COMMENT '锁名称',
    `lock_until` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '锁定时长',
    `locked_at`  timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '锁定时间',
    `locked_by`  varchar(255) NOT NULL COMMENT '锁定者',
    `create_dt`  datetime     NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_dt`  datetime     NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
    PRIMARY KEY (`name`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 0
  DEFAULT CHARSET = utf8mb4 COMMENT ='锁定表'
;

CREATE TABLE `sj_system_user`
(
    `id`        bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `username`  varchar(64)         NOT NULL COMMENT '账号',
    `password`  varchar(128)        NOT NULL COMMENT '密码',
    `role`      tinyint(4)          NOT NULL DEFAULT 0 COMMENT '角色:1-普通用户、2-管理员',
    `create_dt` datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_dt` datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    PRIMARY KEY (`id`),
    UNIQUE KEY `uk_username` (`username`) USING BTREE
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COMMENT ='系统用户表';

-- pwd: admin
INSERT INTO `sj_system_user` (username, password, role)
VALUES ('admin', '465c194afb65670f38322df087f0a9bb225cc257e43eb4ac5a0c98ef5b3173ac', 2);

CREATE TABLE `sj_system_user_permission`
(
    `id`             bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `group_name`     varchar(64)         NOT NULL COMMENT '组名称',
    `namespace_id`   varchar(64)         NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
    `system_user_id` bigint(20)          NOT NULL COMMENT '系统用户id',
    `create_dt`      datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_dt`      datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    PRIMARY KEY (`id`),
    UNIQUE KEY `uk_namespace_id_group_name_system_user_id` (`namespace_id`, `group_name`, `system_user_id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COMMENT ='系统用户权限表';

-- 分布式调度DDL
CREATE TABLE `sj_job`
(
    `id`               bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `namespace_id`     varchar(64)         NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
    `biz_id`           varchar(64)         NOT NULL COMMENT '业务ID',
    `group_name`       varchar(64)         NOT NULL COMMENT '组名称',
    `job_name`         varchar(64)         NOT NULL COMMENT '名称',
    `args_str`         text                         DEFAULT NULL COMMENT '执行方法参数',
    `args_type`        tinyint(4)          NOT NULL DEFAULT 1 COMMENT '参数类型 ',
    `next_trigger_at`  bigint(13)          NOT NULL COMMENT '下次触发时间',
    `job_status`       tinyint(4)          NOT NULL DEFAULT 1 COMMENT '任务状态 0、关闭、1、开启',
    `task_type`        tinyint(4)          NOT NULL DEFAULT 1 COMMENT '任务类型 1、集群 2、广播 3、切片',
    `route_key`        tinyint(4)          NOT NULL DEFAULT 4 COMMENT '路由策略',
    `executor_type`    tinyint(4)          NOT NULL DEFAULT 1 COMMENT '执行器类型',
    `executor_info`    varchar(255)                 DEFAULT NULL COMMENT '执行器名称',
    `trigger_type`     tinyint(4)          NOT NULL COMMENT '触发类型 1.CRON 表达式 2. 固定时间',
    `trigger_interval` varchar(255)        NOT NULL COMMENT '间隔时长',
    `block_strategy`   tinyint(4)          NOT NULL DEFAULT 1 COMMENT '阻塞策略 1、丢弃 2、覆盖 3、并行 4、恢复',
    `executor_timeout` int(11)             NOT NULL DEFAULT 0 COMMENT '任务执行超时时间,单位秒',
    `max_retry_times`  int(11)             NOT NULL DEFAULT 0 COMMENT '最大重试次数',
    `parallel_num`     int(11)             NOT NULL DEFAULT 1 COMMENT '并行数',
    `retry_interval`   int(11)             NOT NULL DEFAULT 0 COMMENT '重试间隔(s)',
    `bucket_index`     int(11)             NOT NULL DEFAULT 0 COMMENT 'bucket',
    `resident`         tinyint(4)          NOT NULL DEFAULT 0 COMMENT '是否是常驻任务',
    `notify_ids`       varchar(128)        NOT NULL DEFAULT '' COMMENT '通知告警场景配置id列表',
    `owner_id`         bigint(20)          NULL     DEFAULT NULL COMMENT '负责人id',
    `labels`           varchar(512)        NULL     DEFAULT '' COMMENT '标签',
    `description`      varchar(256)        NOT NULL DEFAULT '' COMMENT '描述',
    `ext_attrs`        varchar(256)        NULL     DEFAULT '' COMMENT '扩展字段',
    `deleted`          tinyint(4)          NOT NULL DEFAULT 0 COMMENT '逻辑删除 1、删除',
    `create_dt`        datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_dt`        datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    PRIMARY KEY (`id`),
    KEY `idx_namespace_id_group_name` (`namespace_id`, `group_name`),
    KEY `idx_job_status_bucket_index` (`job_status`, `bucket_index`),
    KEY `idx_create_dt` (`create_dt`),
    UNIQUE KEY `uk_sj_job_01` (`namespace_id`, `biz_id`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 0
  DEFAULT CHARSET = utf8mb4 COMMENT ='任务信息';

CREATE TABLE `sj_job_log_message`
(
    `id`            bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `namespace_id`  varchar(64)         NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
    `group_name`    varchar(64)         NOT NULL COMMENT '组名称',
    `job_id`        bigint(20)          NOT NULL COMMENT '任务信息id',
    `task_batch_id` bigint(20)          NOT NULL COMMENT '任务批次id',
    `task_id`       bigint(20)          NOT NULL COMMENT '调度任务id',
    `message`       longtext            NOT NULL COMMENT '调度信息',
    `log_num`       int(11)             NOT NULL DEFAULT 1 COMMENT '日志数量',
    `real_time`     bigint(13)          NOT NULL DEFAULT 0 COMMENT '上报时间',
    `ext_attrs`     varchar(256)        NULL     DEFAULT '' COMMENT '扩展字段',
    `create_dt`     datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    PRIMARY KEY (`id`),
    KEY `idx_task_batch_id_task_id` (`task_batch_id`, `task_id`),
    KEY `idx_create_dt` (`create_dt`),
    KEY `idx_namespace_id_group_name` (`namespace_id`, `group_name`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 0
  DEFAULT CHARSET = utf8mb4 COMMENT ='调度日志';

CREATE TABLE `sj_job_task`
(
    `id`             bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `namespace_id`   varchar(64)         NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
    `group_name`     varchar(64)         NOT NULL COMMENT '组名称',
    `job_id`         bigint(20)          NOT NULL COMMENT '任务信息id',
    `task_batch_id`  bigint(20)          NOT NULL COMMENT '调度任务id',
    `parent_id`      bigint(20)          NOT NULL DEFAULT 0 COMMENT '父执行器id',
    `task_status`    tinyint             NOT NULL DEFAULT 0 COMMENT '执行的状态 0、失败 1、成功',
    `retry_count`    int(11)             NOT NULL DEFAULT 0 COMMENT '重试次数',
    `mr_stage`       tinyint                      DEFAULT NULL COMMENT '动态分片所处阶段 1:map 2:reduce 3:mergeReduce',
    `leaf`           tinyint             NOT NULL DEFAULT '1' COMMENT '叶子节点',
    `task_name`      varchar(255)        NOT NULL DEFAULT '' COMMENT '任务名称',
    `client_info`    varchar(128)                 DEFAULT NULL COMMENT '客户端地址 clientId#ip:port',
    `wf_context`     text                         DEFAULT NULL COMMENT '工作流全局上下文',
    `result_message` text                NOT NULL COMMENT '执行结果',
    `args_str`       text                         DEFAULT NULL COMMENT '执行方法参数',
    `args_type`      tinyint             NOT NULL DEFAULT 1 COMMENT '参数类型 ',
    `ext_attrs`      varchar(256)        NULL     DEFAULT '' COMMENT '扩展字段',
    `create_dt`      datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_dt`      datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    PRIMARY KEY (`id`),
    KEY `idx_task_batch_id_task_status` (`task_batch_id`, `task_status`),
    KEY `idx_create_dt` (`create_dt`),
    KEY `idx_namespace_id_group_name` (`namespace_id`, `group_name`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 0
  DEFAULT CHARSET = utf8mb4 COMMENT ='任务实例';

CREATE TABLE `sj_job_task_batch`
(
    `id`                      bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `namespace_id`            varchar(64)         NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
    `group_name`              varchar(64)         NOT NULL COMMENT '组名称',
    `job_id`                  bigint(20)          NOT NULL COMMENT '任务id',
    `workflow_node_id`        bigint(20)          NOT NULL DEFAULT 0 COMMENT '工作流节点id',
    `parent_workflow_node_id` bigint(20)          NOT NULL DEFAULT 0 COMMENT '工作流任务父批次id',
    `workflow_task_batch_id`  bigint(20)          NOT NULL DEFAULT 0 COMMENT '工作流任务批次id',
    `task_batch_status`       tinyint(4)          NOT NULL DEFAULT 0 COMMENT '任务批次状态 0、失败 1、成功',
    `operation_reason`        tinyint(4)          NOT NULL DEFAULT 0 COMMENT '操作原因',
    `execution_at`            bigint(13)          NOT NULL DEFAULT 0 COMMENT '任务执行时间',
    `system_task_type`        tinyint(4)          NOT NULL DEFAULT 3 COMMENT '任务类型 3、JOB任务 4、WORKFLOW任务',
    `parent_id`               varchar(64)         NOT NULL DEFAULT '' COMMENT '父节点',
    `ext_attrs`               varchar(256)        NULL     DEFAULT '' COMMENT '扩展字段',
    `deleted`                 tinyint(4)          NOT NULL DEFAULT 0 COMMENT '逻辑删除 1、删除',
    `create_dt`               datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_dt`               datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    PRIMARY KEY (`id`),
    KEY `idx_job_id_task_batch_status` (`job_id`, `task_batch_status`),
    KEY `idx_create_dt` (`create_dt`),
    KEY `idx_namespace_id_group_name` (`namespace_id`, `group_name`),
    KEY `idx_workflow_task_batch_id_workflow_node_id` (`workflow_task_batch_id`, `workflow_node_id`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 0
  DEFAULT CHARSET = utf8mb4 COMMENT ='任务批次';

CREATE TABLE `sj_job_summary`
(
    `id`               bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `namespace_id`     VARCHAR(64)     NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
    `group_name`       VARCHAR(64)     NOT NULL DEFAULT '' COMMENT '组名称',
    `business_id`      bigint          NOT NULL COMMENT '业务id (job_id或workflow_id)',
    `system_task_type` tinyint(4)      NOT NULL DEFAULT 3 COMMENT '任务类型 3、JOB任务 4、WORKFLOW任务',
    `trigger_at`       datetime        NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '统计时间',
    `success_num`      int             NOT NULL DEFAULT 0 COMMENT '执行成功-日志数量',
    `fail_num`         int             NOT NULL DEFAULT 0 COMMENT '执行失败-日志数量',
    `fail_reason`      varchar(512)    NOT NULL DEFAULT '' COMMENT '失败原因',
    `stop_num`         int             NOT NULL DEFAULT 0 COMMENT '执行失败-日志数量',
    `stop_reason`      varchar(512)    NOT NULL DEFAULT '' COMMENT '失败原因',
    `cancel_num`       int             NOT NULL DEFAULT 0 COMMENT '执行失败-日志数量',
    `cancel_reason`    varchar(512)    NOT NULL DEFAULT '' COMMENT '失败原因',
    `create_dt`        datetime        NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_dt`        datetime        NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    PRIMARY KEY (`id`),
    KEY `idx_namespace_id_group_name_business_id` (`namespace_id`, `group_name`, business_id),
    UNIQUE KEY `uk_trigger_at_system_task_type_business_id` (`trigger_at`, `system_task_type`, `business_id`) USING BTREE
) ENGINE = InnoDB
  AUTO_INCREMENT = 1
  DEFAULT CHARSET = utf8mb4 COMMENT ='DashBoard_Job';

CREATE TABLE `sj_retry_summary`
(
    `id`            bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `namespace_id`  VARCHAR(64)     NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
    `group_name`    VARCHAR(64)     NOT NULL DEFAULT '' COMMENT '组名称',
    `scene_name`    VARCHAR(64)     NOT NULL DEFAULT '' COMMENT '场景名称',
    `trigger_at`    datetime        NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '统计时间',
    `running_num`   int             NOT NULL DEFAULT 0 COMMENT '重试中-日志数量',
    `finish_num`    int             NOT NULL DEFAULT 0 COMMENT '重试完成-日志数量',
    `max_count_num` int             NOT NULL DEFAULT 0 COMMENT '重试到达最大次数-日志数量',
    `suspend_num`   int             NOT NULL DEFAULT 0 COMMENT '暂停重试-日志数量',
    `create_dt`     datetime        NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_dt`     datetime        NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    PRIMARY KEY (`id`),
    KEY `idx_trigger_at` (`trigger_at`),
    UNIQUE KEY `uk_scene_name_trigger_at` (`namespace_id`, `group_name`, `scene_name`, `trigger_at`) USING BTREE
) ENGINE = InnoDB
  AUTO_INCREMENT = 1
  DEFAULT CHARSET = utf8mb4 COMMENT ='DashBoard_Retry';

CREATE TABLE `sj_workflow`
(
    `id`               bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `workflow_name`    varchar(64)         NOT NULL COMMENT '工作流名称',
    `namespace_id`     varchar(64)         NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
    `biz_id`           varchar(64)         NOT NULL COMMENT '业务ID',
    `group_name`       varchar(64)         NOT NULL COMMENT '组名称',
    `workflow_status`  tinyint(4)          NOT NULL DEFAULT 1 COMMENT '工作流状态 0、关闭、1、开启',
    `trigger_type`     tinyint(4)          NOT NULL COMMENT '触发类型 1.CRON 表达式 2. 固定时间',
    `trigger_interval` varchar(255)        NOT NULL COMMENT '间隔时长',
    `next_trigger_at`  bigint              NOT NULL COMMENT '下次触发时间',
    `block_strategy`   tinyint(4)          NOT NULL DEFAULT 1 COMMENT '阻塞策略 1、丢弃 2、覆盖 3、并行',
    `executor_timeout` int(11)             NOT NULL DEFAULT 0 COMMENT '任务执行超时时间,单位秒',
    `description`      varchar(256)        NOT NULL DEFAULT '' COMMENT '描述',
    `flow_info`        text                         DEFAULT NULL COMMENT '流程信息',
    `wf_context`       text                         DEFAULT NULL COMMENT '上下文',
    `notify_ids`       varchar(128)        NOT NULL DEFAULT '' COMMENT '通知告警场景配置id列表',
    `bucket_index`     int(11)             NOT NULL DEFAULT 0 COMMENT 'bucket',
    `version`          int(11)             NOT NULL COMMENT '版本号',
    `owner_id`         bigint(20)          NULL     DEFAULT NULL COMMENT '负责人id',
    `ext_attrs`        varchar(256)        NULL     DEFAULT '' COMMENT '扩展字段',
    `deleted`          tinyint(4)          NOT NULL DEFAULT 0 COMMENT '逻辑删除 1、删除',
    `create_dt`        datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_dt`        datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    PRIMARY KEY (`id`),
    KEY `idx_create_dt` (`create_dt`),
    KEY `idx_namespace_id_group_name` (`namespace_id`, `group_name`),
    UNIQUE KEY `uk_sj_workflow_01` (`namespace_id`, `biz_id`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 0
  DEFAULT CHARSET = utf8mb4 COMMENT ='工作流';

CREATE TABLE `sj_workflow_node`
(
    `id`                   bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `namespace_id`         varchar(64)         NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
    `node_name`            varchar(64)         NOT NULL COMMENT '节点名称',
    `group_name`           varchar(64)         NOT NULL COMMENT '组名称',
    `job_id`               bigint(20)          NOT NULL COMMENT '任务信息id',
    `workflow_id`          bigint(20)          NOT NULL COMMENT '工作流ID',
    `node_type`            tinyint(4)          NOT NULL DEFAULT 1 COMMENT '1、任务节点 2、条件节点',
    `expression_type`      tinyint(4)          NOT NULL DEFAULT 0 COMMENT '1、SpEl、2、Aviator 3、QL',
    `fail_strategy`        tinyint(4)          NOT NULL DEFAULT 1 COMMENT '失败策略 1、跳过 2、阻塞',
    `workflow_node_status` tinyint(4)          NOT NULL DEFAULT 1 COMMENT '工作流节点状态 0、关闭、1、开启',
    `priority_level`       int(11)             NOT NULL DEFAULT 1 COMMENT '优先级',
    `node_info`            text                         DEFAULT NULL COMMENT '节点信息 ',
    `version`              int(11)             NOT NULL COMMENT '版本号',
    `ext_attrs`            varchar(256)        NULL     DEFAULT '' COMMENT '扩展字段',
    `deleted`              tinyint(4)          NOT NULL DEFAULT 0 COMMENT '逻辑删除 1、删除',
    `create_dt`            datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_dt`            datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    PRIMARY KEY (`id`),
    KEY `idx_create_dt` (`create_dt`),
    KEY `idx_namespace_id_group_name` (`namespace_id`, `group_name`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 0
  DEFAULT CHARSET = utf8mb4 COMMENT ='工作流节点';

CREATE TABLE `sj_workflow_task_batch`
(
    `id`                bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `namespace_id`      varchar(64)         NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
    `group_name`        varchar(64)         NOT NULL COMMENT '组名称',
    `workflow_id`       bigint(20)          NOT NULL COMMENT '工作流任务id',
    `task_batch_status` tinyint(4)          NOT NULL DEFAULT 0 COMMENT '任务批次状态 0、失败 1、成功',
    `operation_reason`  tinyint(4)          NOT NULL DEFAULT 0 COMMENT '操作原因',
    `flow_info`         text                         DEFAULT NULL COMMENT '流程信息',
    `wf_context`        text                         DEFAULT NULL COMMENT '全局上下文',
    `execution_at`      bigint(13)          NOT NULL DEFAULT 0 COMMENT '任务执行时间',
    `ext_attrs`         varchar(256)        NULL     DEFAULT '' COMMENT '扩展字段',
    `version`           int(11)             NOT NULL DEFAULT 1 COMMENT '版本号',
    `deleted`           tinyint(4)          NOT NULL DEFAULT 0 COMMENT '逻辑删除 1、删除',
    `create_dt`         datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_dt`         datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    PRIMARY KEY (`id`),
    KEY `idx_job_id_task_batch_status` (`workflow_id`, `task_batch_status`),
    KEY `idx_create_dt` (`create_dt`),
    KEY `idx_namespace_id_group_name` (`namespace_id`, `group_name`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 0
  DEFAULT CHARSET = utf8mb4 COMMENT ='工作流批次';

CREATE TABLE `sj_job_executor`
(
    `id`            bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    `namespace_id`  varchar(64)         NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
    `group_name`    varchar(64)         NOT NULL COMMENT '组名称',
    `executor_info` varchar(256)        NOT NULL COMMENT '任务执行器名称',
    `executor_type` varchar(3)          NOT NULL COMMENT '1:java 2:python 3:go',
    `create_dt`     datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_dt`     datetime            NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    PRIMARY KEY (`id`),
    KEY `idx_namespace_id_group_name` (`namespace_id`, `group_name`),
    KEY `idx_create_dt` (`create_dt`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 0
  DEFAULT CHARSET = utf8mb4 COMMENT ='任务执行器信息';

3、更改配置文件:

3.1、添加日志文件

(logback-plus.xml)

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <property name="log.path" value="./logs/snail-job-server" />
    <property name="console.log.pattern"  value="%cyan(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/>
    <property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{256} - %msg%n"/>


    <!-- 控制台输出 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${console.log.pattern}</pattern>
            <charset>utf-8</charset>
        </encoder>
    </appender>

    <!-- 控制台输出 -->
    <appender name="file_console" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}/console.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志文件名格式 -->
            <fileNamePattern>${log.path}/console.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- 日志最大 1天 -->
            <maxHistory>1</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <!-- 过滤的级别 -->
            <level>INFO</level>
        </filter>
    </appender>

    <appender name="fileInfo" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}/info.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="fileWarn" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}/warn.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${log.path}/warn.%d{yyyy-MM-dd}.log
            </FileNamePattern>
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>


    <appender name="fileError" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}/error.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log
            </FileNamePattern>
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <appender name="asyncInfo" class="ch.qos.logback.classic.AsyncAppender">
        <discardingThreshold>100</discardingThreshold>
        <queueSize>1024</queueSize>
        <appender-ref ref="fileInfo"/>
    </appender>

    <appender name="asyncWarn" class="ch.qos.logback.classic.AsyncAppender">
        <discardingThreshold>100</discardingThreshold>
        <queueSize>1024</queueSize>
        <appender-ref ref="fileWarn"/>
    </appender>

    <appender name="asyncError" class="ch.qos.logback.classic.AsyncAppender">
        <discardingThreshold>100</discardingThreshold>
        <queueSize>1024</queueSize>
        <appender-ref ref="fileError"/>
    </appender>

    <!-- SnailJob appender -->
    <appender name="snailJobLogServerAppender"
              class="com.aizuda.snailjob.server.common.appender.SnailJobServerLogbackAppender">
    </appender>

    <!-- 控制台输出日志级别 -->
    <root level="info">
        <appender-ref ref="console" />
        <appender-ref ref="file_console" />
        <appender-ref ref="asyncInfo"/>
        <appender-ref ref="asyncWarn"/>
        <appender-ref ref="asyncError"/>
        <appender-ref ref="snailJobLogServerAppender"/>
    </root>
</configuration>

3.2、配置application.yml文件

server:
  port: 4001
  servlet:
    context-path: /snail-job

spring:
  datasource:
    name: snail_job
    ## mysql
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/snail_job?useSSL=false&characterEncoding=utf8&useUnicode=true
    username: root
    password: 1203
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      connection-timeout: 30000
      minimum-idle: 5
      maximum-pool-size: 100
      auto-commit: true
      idle-timeout: 30000
      pool-name: snail_job
      max-lifetime: 1800000

# 日志配置
logging:
  config: classpath:logback-plus.xml

snail-job:
  # 服务端节点IP(默认按照`NetUtil.getLocalIpStr()`)
  server-host:
  # 服务端端口号
  server-port: 17888
  # 合并日志默认保存天数
  merge-Log-days: 1
  # 合并日志默认的条数
  merge-Log-num: 500
  # 配置每批次拉取重试数据的大小
  retry-pull-page-size: 100
  # 配置日志保存时间(单位:天)
  log-storage: 7
  # bucket的总数量
  bucket-total: 128
  # Dashboard 任务容错天数
  summary-day: 7
  # 配置负载均衡周期时间
  load-balance-cycle-time: 10
  # 重试任务拉取的并行度
  retry-max-pull-parallel: 2
  rpc-type: grpc

3.3、添加启动类,直接启动

@SpringBootApplication
public class SnailServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(com.aizuda.snailjob.server.SnailJobServerApplication.class, args);
        System.out.println("============================ SnailServerApplication 启动成功 ==================");
    }
}

访问http://localhost:4001/snail-job 用户名:admin 密码: admin

配置空间【zyf-test01】为了满足在不同业务线或环境(如 dev、fat、uat 等)

namespace:  a1NSize1D5jP83Wj0B6Hre094f7kFeHB(可随意输入)

创建执行器组 【test_zyf_group】针对不同模块,可以建立多个分组。

Token: SJ_Wyz3dmsdbDOkDujOTSSoBjGQP1BMsVnj

groupName: test_zyf_group

三、客户端

3.1、添加依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
        <!-- 核心依赖 -->
        <dependency>
            <groupId>com.aizuda</groupId>
            <artifactId>snail-job-client-starter</artifactId>
            <version>${snail-job.version}</version>
        </dependency>
        <!-- 重试模块(若不需要可以不引入) -->
        <dependency>
            <groupId>com.aizuda</groupId>
            <artifactId>snail-job-client-retry-core</artifactId>
            <version>${snail-job.version}</version>
        </dependency>
        <!-- 定时任务(若不需要可以不引入) -->
        <dependency>
            <groupId>com.aizuda</groupId>
            <artifactId>snail-job-client-job-core</artifactId>
            <version>${snail-job.version}</version>
        </dependency>
</dependencies>

3.2、添加注解

在 SpringBoot 启动类上添加 @EnableSnailJob 注解:

// 这里还有另一种写法 @EnableSnailJob("test_sj_group")
// 注解优先级 > 配置文件优先级 
@EnableSnailJob
@SpringBootApplication
public class SnailClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(SnailClientApplication.class, args);
        System.out.println("======================== SnailClientApplication 启动成功===");
    }
}

3.3、配置客户端

server:
  port: 4002
snail-job:
  # 任务调度服务器信息
  server:
    # 服务器IP地址(或域名);集群时建议通过 nginx 做负载均衡
    host: 127.0.0.1
    # 服务器通讯端口(不是后台管理页面服务端口)
    port: 17888
  # 命名空间 【上面配置的空间的唯一标识】
  namespace: a1NSize1D5jP83Wj0B6Hre094f7kFeHB
  # 接入组名【上面配置的组名称】注意: 若通过注解配置了这里的配置不生效
  group: test_zyf_group
  # 接入组 token 【上面配置的token信息】
  token: SJ_Wyz3dmsdbDOkDujOTSSoBjGQP1BMsVnj
  # 客户端绑定IP,必须服务器可以访问到;默认自动推断,在服务器无法调度客户端时需要手动配置
  host: 127.0.0.1
  # 客户端通讯端口,默认 17889
  port: 17889
  retryStrategy: LOCAL_REMOTE
  async: true
  timeout: 60000
  unit: TimeUnit.MILLISECONDS
  # 任务执行线程池配置
  executor:
    core-pool-size: 10
    max-pool-size: 20
    queue-capacity: 100

# 实时日志配置
logging:
  config: classpath:logback-boot.xml

3.4、启动客户端

3.5、功能演示

3.5.1、定时任务示例

Java代码中日志

平台日志:

3.5.2、重试

/**
 * 重试任务(异常触发)
 */
@Retryable(
        scene = "retry-02",    // 场景标识
        localTimes = 3,            // 本地重试3次
        localInterval = 2          // 间隔2秒
)
public void retry02() {
    // 支付处理逻辑
    System.out.println("===========  retry02   执行了");
    throw new RuntimeException("retry02 方法执行异常");
}

执行Controller,调用此方法后,在管理平台页面“重试场景”列表会出现

重试的列表

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐