Skip to main content

LangChat 定时调度架构设计

🎯 架构概述

LangChat 采用 XXL-Job 作为分布式定时任务调度框架,提供企业级的任务调度、执行、监控和管理能力。

架构特点

  • 分布式设计: 支持多个执行器节点,自动负载均衡和故障转移
  • Web 管理界面: 完整的任务配置、监控和日志查询功能
  • 灵活的调度策略: 支持 CRON 表达式、多种路由策略
  • 高可靠性: 任务持久化、自动重试、执行日志保存
  • 易于扩展: 新模块只需简单配置即可接入
  • Native Admin API: 原生支持 XXL-Job Admin REST API,无需 Admin UI 即可进行全面管理

🏗️ 核心三层架构

┌─────────────────────────────────────────────────────────────────┐
│                    XXL-Job-Admin                               │
│         (Web 管理平台,负责任务配置和监控)                      │
│     [支持 Cookie 会话认证 + Token 认证]                        │
└──────────────────────────┬──────────────────────────────────────┘
                           │ HTTP REST API

          ┌────────────────┴────────────────┐
          │                                 │
    ┌─────▼───────────────────────────────────────────────┐
    │  LangChat 定时调度模块 (langchat-common-scheduler)  │
    │                                                     │
    │  ┌──────────────────────────────────────────────┐  │
    │  │  第1层:REST API 层 (Controller)             │  │
    │  │  POST/PUT/DELETE /aigc/schedule/...         │  │
    │  │  - 任务管理(创建、编辑、删除、启停)        │  │
    │  │  - 执行器管理(创建、编辑、删除、查询)      │  │
    │  │  - 日志查询、统计查询                        │  │
    │  └──────────────────┬───────────────────────────┘  │
    │                     │                               │
    │  ┌──────────────────▼───────────────────────────┐  │
    │  │  第2层:业务逻辑层 (ScheduleJobManager)      │  │
    │  │  - 任务 CRUD、启停、触发                     │  │
    │  │  - 执行器 CRUD                               │  │
    │  │  - 日志查询、统计计算                        │  │
    │  │  - Cron 表达式本地计算                       │  │
    │  └──────────────────┬───────────────────────────┘  │
    │                     │                               │
    │  ┌──────────────────▼───────────────────────────┐  │
    │  │  第3层:XXL-Job 通信层 (XxlJobAdminClient) │  │
    │  │  - 自动登录 & Cookie 会话管理              │  │
    │  │  - HTTP 请求封装(Form/JSON)             │  │
    │  │  - 响应格式规范化                          │  │
    │  │  - 重试和错误处理                          │  │
    │  └──────────────────────────────────────────────┘  │
    └─────────────────────────────────────────────────────┘
          │ 自动注册                   │ 自动注册
          │                            │
    ┌─────▼──────────────┐      ┌─────▼──────────────┐
    │  执行器实例 1       │      │  执行器实例 2       │
    │ (langchat-exec-1) │      │ (langchat-exec-2) │
    └───────────────────┘      └───────────────────┘

📦 模块结构

langchat-common-scheduler

LangChat 的统一任务调度模块,负责与 XXL-Job 集成和提供统一的服务接口。
langchat-common-scheduler/
├── src/main/java/cn/langchat/common/scheduler/
│   ├── config/
│   │   ├── XxlJobProperties.java          # XXL-Job 配置属性
│   │   └── XxlJobAutoConfiguration.java   # Spring Boot 自动配置
│   ├── constant/
│   │   └── JobType.java                   # 任务类型枚举
│   ├── controller/
│   │   └── ScheduleManageController.java  # REST API 入口
│   ├── service/
│   │   ├── ScheduleJobManager.java        # 服务接口定义
│   │   └── impl/
│   │       ├── ScheduleJobManagerImpl.java # XXL-Job 实现
│   │       └── NoOpScheduleJobManager.java# 空实现(未启用时)
│   ├── client/
│   │   ├── XxlJobAdminClient.java         # Admin 通信接口
│   │   └── XxlJobAdminClientImpl.java      # Admin 通信实现
│   ├── model/
│   │   ├── JobExecutionLog.java           # 执行日志模型
│   │   ├── JobExecutionLogDetail.java     # 日志详情
│   │   └── XxlJobLog.java                 # XXL-Job 原始日志
│   └── mapper/
│       └── XxlJobLogMapper.java           # 日志 MyBatis 映射
└── pom.xml

核心类说明

1. JobType.java - 任务类型枚举

定义系统支持的所有任务类型:
public enum JobType {
    WORKFLOW("workflowJobHandler", "工作流定时执行"),
    // 其他模块可按需扩展
}

2. ScheduleJobManager - 统一的任务管理服务

两种实现
  • ScheduleJobManagerImpl: XXL-Job 实现(启用时注册)
  • NoOpScheduleJobManager: 空实现(禁用时注册,防止注入失败)

3. XxlJobAdminClient - XXL-Job Admin 通信层

核心功能
  • 会话管理: 启动时自动登录,获取并缓存 Cookie
  • 认证支持: Cookie 会话认证(优先)+ Token 认证(后备)
  • 多版本兼容: 同时支持 XXL-Job 2.x 和 3.x 版本
  • 格式规范化: 将 XXL-Job 响应统一转换为 DataTables 格式
  • 自动重试: 请求失败时自动重新登录

🔌 REST API 接口规范

任务管理

方法端点功能权限
GET/aigc/schedule/jobs分页查询任务
GET/aigc/schedule/stats全局统计
POST/aigc/schedule/jobs创建任务Admin
PUT/aigc/schedule/jobs/{jobId}编辑任务Admin
DELETE/aigc/schedule/jobs/{jobId}删除任务Admin
POST/aigc/schedule/jobs/{jobId}/enable启用任务Admin
POST/aigc/schedule/jobs/{jobId}/disable禁用任务Admin
POST/aigc/schedule/jobs/{jobId}/trigger手动触发Admin

执行器管理

方法端点功能权限
GET/aigc/schedule/executors分页查询执行器
POST/aigc/schedule/executors创建执行器Admin
PUT/aigc/schedule/executors/{id}编辑执行器Admin
DELETE/aigc/schedule/executors/{id}删除执行器Admin

日志查询

方法端点功能权限
GET/aigc/schedule/logs分页查询日志
GET/aigc/schedule/logs/{logId}/detail获取日志详情

工具接口

方法端点功能权限
GET/aigc/schedule/validate-cron校验 Cron 表达式
GET/aigc/schedule/next-runs计算下次执行时间
GET/aigc/schedule/status获取调度系统状态

🎯 前端管理页面功能

LangChat 的 schedule 管理页面实现了 XXL-Job-Admin 的主要功能,无需使用 Admin UI 即可进行完整的定时任务管理:

任务管理功能

  • 任务列表: 分页查询,支持任务名称、执行器、状态筛选
  • 创建任务: Web 表单,支持 CRON 表达式编辑和实时预览
  • 编辑任务: 修改任务配置(名称、CRON、执行器等)
  • 删除任务: 支持删除确认对话框
  • 启停任务: 快速启用/禁用任务
  • 手动触发: 一键手动执行任务
  • 下次执行预览: 显示基于 CRON 的下 5 次执行时间

执行器管理功能

  • 执行器列表: 分页查询,支持应用名称、标题筛选
  • 创建执行器: 支持自动注册和手动录入两种方式
  • 编辑执行器: 修改标题、注册方式、节点地址
  • 删除执行器: 支持删除确认
  • 在线状态: 实时显示执行器在线/离线状态
  • 节点地址: 可视化显示已注册的执行器节点

日志查询功能

  • 执行日志: 分页查询,支持任务、状态、时间范围筛选
  • 日志详情: 查看完整的执行日志、调度备注、执行结果
  • 执行指标: 展示执行状态、耗时、触发时间、处理时间
  • 执行参数: 显示传递给任务处理器的参数

统计分析功能

  • 全局统计: 显示总任务数、运行中数量、近期失败数
  • 任务统计: 点击任务行查看该任务的所有执行历史

🚀 快速开始

Step 1: 配置 XXL-Job

langchat:
  xxl-job:
    enabled: true
    admin-addresses: http://xxl-job-admin:8080/xxl-job-admin
    appname: langchat-executor
    access-token: default_token
    port: 9999
    log-path: /data/langchat/xxl-job/jobhandler
    log-retention-days: 30

Step 2: 定义 Job Handler

在任何 Spring 组件中定义任务处理方法:
@Component
public class WorkflowJobHandler {

    @XxlJob("workflowJobHandler")
    public void execute() {
        // 获取 XXL-Job 传递的参数
        String workflowId = XxlJobHelper.getJobParam();

        try {
            // 业务逻辑处理
            doBusinessLogic(workflowId);

            // 返回执行结果
            XxlJobHelper.handleSuccess("任务执行成功");
        } catch (Exception e) {
            XxlJobHelper.handleFail("执行失败: " + e.getMessage());
        }
    }

    private void doBusinessLogic(String workflowId) {
        System.out.println("处理工作流: " + workflowId);
    }
}

Step 3: 动态创建任务

@Service
public class WorkflowScheduleService {

    @Autowired
    private ScheduleJobManager scheduleJobManager;

    public void configureWorkflowSchedule(String workflowId, String cronExpr) {
        // 检查 XXL-Job 是否可用
        if (!scheduleJobManager.isScheduleAvailable()) {
            throw new ServiceException("XXL-Job 未配置或不可用");
        }

        // 创建定时任务
        Long xxlJobId = scheduleJobManager.createScheduleJob(
            JobType.WORKFLOW,
            workflowId,
            "工作流-" + workflowId,
            cronExpr,
            workflowId
        );

        // 立即启用
        scheduleJobManager.enableScheduleJob(xxlJobId);
    }
}

🔐 认证机制

  1. 初始化登录: 应用启动时自动调用 /system/login 登录 XXL-Job-Admin
  2. Cookie 缓存: 获取响应头中的 Set-Cookie,缓存会话信息
  3. 请求发送: 后续所有请求自动带上 Cookie 信息
  4. 会话维持: Cookie 在 XXL-Job-Admin 维持会话状态
  5. 自动重试: 若请求失败(会话过期),自动重新登录并重试

后备认证方案

若 Cookie 认证失败,系统自动切换到 Token 认证:
  • 在请求头中附加 X-Access-Token 参数
  • 支持 XXL-Job v2.x 和 v3.x 的 Token 模式

⚙️ 配置说明

本地开发环境 (application-local.yml)

langchat:
  xxl-job:
    enabled: true
    admin-addresses: http://localhost:8080/xxl-job-admin
    appname: langchat-executor
    access-token: default_token
    port: 9999
    log-path: /data/langchat/xxl-job/jobhandler
    log-retention-days: 30

生产环境 (application-prd.yml)

langchat:
  xxl-job:
    enabled: false  # 根据需要启用
    admin-addresses: ${XXL_JOB_ADMIN_ADDRESSES}
    appname: ${XXL_JOB_APPNAME}
    access-token: ${XXL_JOB_ACCESS_TOKEN}
    # ... 其他配置通过环境变量

🔄 工作流示例

场景:为工作流配置定时执行

1. 前端表单输入
   └─► API: POST /workflow/{id}/schedule
       {
         "cronExpression": "0 0 2 * * ?",  // 每天凌晨2点
         "timezone": "Asia/Shanghai"
       }

2. 后端创建任务
   └─► ScheduleJobManager.createScheduleJob(
         JobType.WORKFLOW,
         workflowId,
         "工作流-demo",
         "0 0 2 * * ?",
         workflowId
       )

3. XXL-Job Admin 创建任务
   └─► XxlJobAdminClient 调用 /jobinfo/insert API
       HTTP POST /admin/jobinfo/insert
       {
         "jobGroup": 1,
         "jobDesc": "工作流-demo",
         "scheduleConf": "0 0 2 * * ?",
         "executorHandler": "workflowJobHandler",
         "executorParam": "workflowId"
       }

4. 定时执行触发
   └─► 时间到达 → XXL-Job 调用 JobHandler
       → WorkflowJobHandler.execute()
       → 获取参数、执行工作流业务逻辑
       → 报告结果给 XXL-Job

5. 日志记录
   └─► 执行结果持久化到数据库
       → 可在管理页面查询历史执行记录

🐛 故障排查

执行器无法连接到 XXL-Job-Admin

检查清单
  1. XXL-Job-Admin 服务是否正常运行
  2. 配置的 admin-addresses 是否正确
  3. 网络连接是否正常(尤其是 Docker 容器网络)
  4. 查看应用日志获取详细错误信息

任务没有按时执行

检查清单
  1. 执行器是否已注册(在管理页面查看)
  2. 任务是否已创建并启用
  3. CRON 表达式是否正确(使用校验工具)
  4. Job Handler 名称是否与 @XxlJob 注解一致

任务执行失败

  1. 进入管理页面 → 日志查询
  2. 查看相应任务的执行日志和错误信息
  3. 查看应用的 log 文件

📚 相关文档

📝 最佳实践

  1. 参数传递: 通过 jobParam 传递业务 ID,不要在 JobHandler 中硬编码
  2. 错误处理: 始终使用 XxlJobHelper.handleSuccess/handleFail() 报告结果
  3. 日志记录: 在 Job Handler 中添加足够的日志,便于问题排查
  4. 超时控制: 在配置中设置合理的超时时间
  5. 幂等性: 设计 Job Handler 使其可以安全重试
  6. 资源释放: 确保在异常时正确释放资源
  7. 会话管理: 依赖系统自动维护 Cookie 会话,无需手动处理认证