
- [xxljob版本升级方案](#xxljob版本升级方案)
  - [1、概要](#1概要)
    - [1.1 目的](#11-目的)
    - [1.2 Xray扫描漏洞](#12-xray扫描漏洞)
  - [2、升级内容](#2升级内容)
    - [2.1 客户端代码处理](#21-客户端代码处理)
    - [2.2 数据库更新](#22-数据库更新)
      - [2.2.1 数据库：数据迁移](#221-数据库数据迁移)
      - [xxl\_job\_qrtz\_trigger\_info](#xxl_job_qrtz_trigger_info)
      - [xxl\_job\_qrtz\_trigger\_group](#xxl_job_qrtz_trigger_group)
      - [xxl\_job\_user](#xxl_job_user)
      - [xxl\_job\_qrtz\_locks](#xxl_job_qrtz_locks)
    - [2.3 配置文件升级](#23-配置文件升级)
      - [2.3.1 服务端配置文件升级](#231-服务端配置文件升级)
      - [2.3.2 客户端配置文件升级](#232-客户端配置文件升级)
    - [2.4 服务端升级](#24-服务端升级)
    - [3、测试](#3测试)
    - [4、检查](#4检查)
  - [4、参考文档](#4参考文档)

# xxljob版本升级方案

## 1、概要

### 1.1 目的
现在项目中xxljob版本2.0.1过低，会在进行Xray安全扫描的时候出现漏洞。为了处理上述Xray漏洞，现将协同服务，平台服务，流水线服务，upms服务的xxljob版本从2.0.1升级到2.4.1

### 1.2 Xray扫描漏洞
- XXL-Job 在 v2.3.1 版本之前存在一个服务器端请求伪造（SSRF）漏洞，该漏洞通过组件 /admin/controller/JobLogController.java 被利用。 
- XXL-JOB在2.2.0及其之前版本，在后台任务中存在命令执行漏洞。这个漏洞允许攻击者在后台任务中心通过写入shell命令任务调度来获取服务器权限。

## 2、升级内容

### 2.1 客户端代码处理
- **依赖更新**：修改pom文件，重新添加xxl-job-core2.4.1版本依赖。
- **配置文件调整**：在XxlJobConfig.java文件中修改**xxlJobSpringExecutor**的方法名**setAppName()**为**setAppname()**，添加配置**address**。
- **处理Handler文件**：在2.4.1版本中，xxljob移除了基于类的开发方式，移除了@JobHandler注解和IJobHandler类，并引入了基于方法的开发方式，每个任务对应一个方法，引入了@XxlJob注解。
  - **注解变更**：删除Handler文件中的@JobHandler注解，取消继承IJobHandler类，并且在execute方法上添加@XxlJob注解，支持自动扫描任务并注入到执行器容器。
  - **方法变更**：重构**execute**方法：2.4.1版本更新了该方法，使得默认任务结果为 "成功" 状态，不需要主动设置，于是，修改方法的返回值**ReturnT<String>**为**void**，删除掉其原先的结果返回，修改为**XxlJobHelper.handleFail/handleSuccess**自主设置返回结果。
  - **日志处理**：修改日志处理：修改原先的**XxlJobLogger.log()**为**XxlJobHelper.log()**  
- **执行器初始化修改**：在低版本的xxl-job中，初始化 XxlJobSpringExecutor执行器需要在@Bean中加上```initMethod = "start", destroyMethod = "destroy"```，但是在高版本的xxl-job（如 2.2.0）则需要删除```initMethod = "start", destroyMethod = "destroy"```  
- **参数获取方式修改**：
```java
 /**【优化】任务核心类 “IJobHandler” 的 “execute” 方法取消出入参设计。改为通过 “XxlJobHelper.getJobParam” 获取任务参数并替代方法入参，通过 “XxlJobHelper.handleSuccess/handleFail” 设置任务结果并替代方法出参，示例代码如下；**/
@XxlJob("demoJobHandler")
public void execute() {
String param = XxlJobHelper.getJobParam();    // 获取参数
XxlJobHelper.handleSuccess();                 // 设置任务结果
}

```
[具体处理的jira页面](https://jira.essence.com.cn/browse/DEV-11233)

### 2.2 数据库更新
2.4.1版本对数据库表有所修改
- 通过mysqldump工具导出原先的数据库以作备份处理，比对2个版本的sql文件，整理差异，并编写更新脚本**update.sql**文件[update.sql](./update.sql)
- 本地测试：在本地数据库测试更新，回滚等操作，确保没有问题后，再到生产环境更新。
- 更新步骤：
  - 先使用  ```mysqldump -uroot -p --host=[ip] --port=[端口] --databases --add-locks --no-autocommit paas_basic_task > [path_to_sql_file.sql备份文件]```命令导出备份文件
  - 运行update.sql文件，确认文件运行没问题
  - 如果有问题使用```mysql -u [username] -p[password] paas_basic_task < [path_to_sql_file.sql备份文件]```命令回滚到之前版本

#### 2.2.1 数据库：数据迁移
数据库更新前后表对比 

<table>
  <tr>
    <th>旧表</th>
    <th>新表</th>
    <th>修改列(索引)</th>
    <th>处理</th>
    <th>描述(默认值)</th>
  </tr>
  <tr>
    <td><a href="#xxl_job_qrtz_trigger_info">xxl_job_qrtz_trigger_info</a></td>
    <td><h>xxl_job_info</h></td>
    <td>
      1. <h>job_cron</h><br>
      2. <h>schedule_type</h><br>
      3. <h>schedule_conf</h><br>
      4. <h>misfire_strategy</h><br>
      5. <h>trigger_status</h><br>
      6. <h>trigger_last_time</h><br>
      7. <h>trigger_next_time</h><br>
    </td>
    <td>
      <h>删除</h><br>
      <h>新增</h><br>
      <h>新增</h><br>
      <h>新增</h><br>
      <h>新增</h><br>
      <h>新增</h><br>
      <h>新增</h><br>
    </td>
    <td>
      <h>cron表达式</h><br>
      <h>调度类型(CRON)</h><br>
      <h>调度配置(cron表达式)</h><br>
      <h>调度过期策略(DO_NOTHING)</h><br>
      <h>触发器状态(0, 1)</h><br>
      <h>上次调度时间(重启后生成)</h><br>
      <h>下次调度时间(重启后生成)</h><br>
    </td>
  </tr>
  <tr>
    <td><h>xxl_job_qrtz_trigger_log</h></td>
    <td><h>xxl_job_log</h></td>
    <td>
      1. <h>id</h><br>
      2. <h>alarm_status</h><br>
      3. <h>i_handle_code(索引)</h><br>
    </td>
    <td>
      <h>修改</h><br>
      <h>新增</h><br>
      <h>新增</h><br>
    </td>
    <td>
      <h>主键类型改为long</h><br>
      <h>告警状态(0)</h><br>
      <h></h><br>
    </td>
  </tr>
  <tr>
    <td><h></h></td>
    <td><h>xxl_job_log_report</h></td>
    <td>
      1. <h>id</h><br>
      2. <h>trigger_day</h><br>
      3. <h>running_count</h><br>
      4. <h>suc_count</h><br>
      5. <h>fail_count</h><br>
      6. <h>update_time</h><br>
    </td>
    <td>新增</td>
    <td>
      <h>主键</h><br>
      <h>调度-时间(NULL)</h><br>
      <h>运行中-日志数量('0')</h><br>
      <h>执行成功-日志数量('0')</h><br>
      <h>执行失败-日志数量('0')</h><br>
      <h>更新时间(NULL)</h><br>
    </td>
  </tr>
  <tr>
    <td><h>xxl_job_qrtz_trigger_logglue</h></td>
    <td><h>xxl_job_logglue</h></td>
    <td>
      1. <h>add_time</h><br>
      2. <h>update_time</h><br>
    </td>
    <td>
      <h>修改</h><br>
      <h>修改</h><br>
    </td>
    <td>
      <h>类型从timestamp改为datetime</h><br>
      <h>类型从timestamp改为datetime</h><br>
    </td>
  </tr>
  <tr>
    <td>xxl_job_qrtz_trigger_registry</td>
    <td>xxl_job_registry</td>
    <td>
      1. <h>update_time</h><br>
      2. <h>i_g_k_v(索引)</h>
    </td>
    <td>
      <h>修改</h><br>
      <h>新增</h><br>
    </td>
    <td>
      <h>类型从timestamp改为datetime</h><br>
      <h></h><br>
    </td>
  </tr>
  <tr>
    <td><a href="#xxl_job_qrtz_trigger_group">xxl_job_qrtz_trigger_group</a></td>
    <td>xxl_job_group</td>
    <td>
      1. <h>order</h><br>
      2. <h>update_time</h><br>
    </td>
    <td>
      <h>删除</h><br>
      <h>新增</h><br>
    </td>
    <td>
      <h>排序</h><br>
      <h>更新时间(NULL)</h><br>
    </td>
  </tr>
  <tr>
    <td></td>
    <td><a href="#xxl_job_user">xxl_job_user</a></td>
    <td>
      1. <h>id</h><br>
      2. <h>username</h><br>
      3. <h>password</h><br>
      4. <h>role</h><br>
      5. <h>permission</h><br>
    </td>
    <td>新增</td>
    <td>
      <h>主键</h><br>
      <h>账号(admin)</h><br>
      <h>密码(123456)</h><br>
      <h>角色：0-普通用户、1-管理员</h><br>
      <h>权限：执行器ID列表，多个逗号分割(NULL)</h><br>
    </td>
  </tr>
  <tr>
    <td><a href="#xxl_job_qrtz_locks">xxl_job_qrtz_locks</a></td>
    <td>xxl_job_lock</td>
    <td>
      1. <h>SCHED_NAME</h><br>
      2. <h>LOCK_NAME</h><br>
    </td>
    <td>
      <h>删除</h><br>
      <h>修改</h><br>
    </td>
    <td>
      <h>计划名称</h><br>
      <h>锁名称，修改为lock_name</h><br>
    </td>
  </tr>
  <tr><td>xxl_job_qrtz_blob_triggers</td><td></td><td></td><td>删除</td><td>quartz需要的表，新版本该组件被去掉</td></tr>
  <tr><td>xxl_job_qrtz_calendars</td><td></td><td></td><td>删除</td><td>quartz需要的表，新版本该组件被去掉</td></tr>
  <tr><td>xxl_job_qrtz_cron_triggers</td><td></td><td></td><td>删除</td><td>quartz需要的表，新版本该组件被去掉</td></tr>
  <tr><td>xxl_job_qrtz_fired_triggers</td><td></td><td></td><td>删除</td><td>quartz需要的表，新版本该组件被去掉</td></tr>
  <tr><td>xxl_job_qrtz_paused_trigger_grps</td><td></td><td></td><td>删除</td><td>quartz需要的表，新版本该组件被去掉</td></tr>
  <tr><td>xxl_job_qrtz_scheduler_state</td><td></td><td></td><td>删除</td><td>quartz需要的表，新版本该组件被去掉</td></tr>
  <tr><td>xxl_job_qrtz_simple_triggers</td><td></td><td></td><td>删除</td><td>quartz需要的表，新版本该组件被去掉</td></tr>
  <tr><td>xxl_job_qrtz_simprop_triggers</td><td></td><td></td><td>删除</td><td>quartz需要的表，新版本该组件被去掉</td></tr>
  <tr><td>xxl_job_qrtz_triggers</td><td></td><td></td><td>删除</td><td>quartz需要的表，新版本该组件被去掉</td></tr>
  <tr><td>xxl_job_qrtz_job_details</td><td></td><td></td><td>删除</td><td>quartz需要的表，新版本该组件被去掉</td></tr>
</table>

#### xxl_job_qrtz_trigger_info
- 1. **job_cron**列被新表的**schedule_type**和**schedule_conf**调度类型和调度配置替换，故将**job_cron**中的数据迁移到新表的两列中type为**CRON**，conf为原先的cron表达式
- 2. 表中新增调度过期策略**misfire_strategy**列，对应**XXL_JOB_QRTZ_TRIGGERS**表中**MISFIRE_INSTR**列，对应设置为**DO_NOTHING** [quartz过期处理策略](https://www.quartz-scheduler.org/api/2.1.7/constant-values.html)
- 3. 表中**trigger_status**列默认为0，更新后需要手动触发启动一下服务以此更新数据
- 4. 表中**trigger_next_time****trigger_next_time**两列会在服务启动的时候自动更新，后续启动完成之后检查数据

#### xxl_job_qrtz_trigger_group
- 1. **order**列在新版本被弃用，原先在界面展示执行器顺序是按照order字段的值进行排序`ORDER BY t.order ASC`，现在按照`ORDER BY t.app_name, t.title, t.id ASC`
- 2. **update_time**列是新版本新增的记录执行器更新时间的字段，调用"/update"或者"/save"接口成功会将其设置为当前日期和时间。

#### xxl_job_user
- 新版本新增用户管理：支持在线管理系统用户，存在管理员、普通用户两种角色；默认初始插入一条数据admin以保证初始登录

#### xxl_job_qrtz_locks
- 新版本删除了SCHED_NAME列，但是需要添加数据'schedule_lock'以此确保调度操作的唯一性，防止其他调度进程同时执行。

### 2.3 配置文件升级

项目使用远程配置，根据新版本2.4.1的配置文件对现有的旧配置更新，删除不生效的配置，并保留原先旧配置以作备份。

#### 2.3.1 服务端配置文件升级
使用[新版本配置](https://github.com/xuxueli/xxl-job/blob/2.4.1/xxl-job-admin/src/main/resources/application.properties)对旧版本替换更新  
| 配置                                                        | 处理                                                            |
| :---------------------------------------------------------- | :-------------------------------------------------------------- |
| management.server.servlet.context-path=/actuator            | 新增                                                            |
| management.health.mail.enabled=false                        | 新增                                                            |
| spring.mvc.servlet.load-on-startup=0                        | 新增                                                            |
| spring.freemarker.settings.new_builtin_class_resolver=safer | 新增                                                            |
| 连接池配置                                                  | 从tomcat的JDBC连接池替换成了HikariCP，并且将最大连接数修改为300 |
| email配置                                                   | 从xxl.job.mail修改为spring.email，内容对应修改                  |
| 登录配置                                                    | 删除，新版本添加了用户管理，用户数据存入数据库                  |
| xxl.job.accessToken=default_token                           | 修改                                                            |
| xxl.job.i18n=zh_CN                                          | 修改                                                            |
| xxl.job.triggerpool.fast.max=200                            | 新增                                                            |
| xxl.job.triggerpool.slow.max=100                            | 新增                                                            |
| xxl.job.logretentiondays=30                                 | 新增                                                            |

#### 2.3.2 客户端配置文件升级
使用[新版本配置](https://github.com/xuxueli/xxl-job/blob/2.4.1/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/resources/application.properties)对旧版本替换更新
- 添加配置，xxl.job.executor.address=
### 2.4 服务端升级
对项目原先task库中的xxl-job-admin控制台代码进行更新，使用2.4.1版本对比，之后进行替换处理，并对原先代码进行备份，确保无误后在提交入库

### 3、测试
使用本地配置文件运行xxl-job-admin以作测试。在本地启动devops的各个模块，具体测试，查看是否有数据遗漏，以及任务是否被成功注入添加。确保没有问题之后，再正式上线操作。

### 4、检查
- 对更新后的系统功能进行检查，观察定时任务能否顺利触发，调度能否顺利完成

## 4、参考文档
[xxljob官方文档](https://www.xuxueli.com/xxl-job/)  
[XXLJOB从2.2.0升级到2.4.0步骤](https://blog.csdn.net/qq_34668238/article/details/132069360)  
[xxl-job版本升级客户端详解](https://gitcode.csdn.net/66c6e19ca1ed2f4c853c1015.html?dp_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6NjMzNDY5NCwiZXhwIjoxNzMxODkzOTI0LCJpYXQiOjE3MzEyODkxMjQsInVzZXJuYW1lIjoicXFfNjM2MzIyNDUifQ.5VhMEdO-GdBBLo6xOope-v1WHJ4KeBIgZCBO3PsfVyw&spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7Ebaidujs_baidulandingword%7Eactivity-1-126016551-blog-132069360.235%5Ev43%5Epc_blog_bottom_relevance_base1&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7Ebaidujs_baidulandingword%7Eactivity-1-126016551-blog-132069360.235%5Ev43%5Epc_blog_bottom_relevance_base1&utm_relevant_index=1)  
[xxl-job版本升级](https://gitcode.csdn.net/66c6e20fa0bc797cf7b69dcd.html?dp_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6NjMzNDY5NCwiZXhwIjoxNzMxODkzOTI0LCJpYXQiOjE3MzEyODkxMjQsInVzZXJuYW1lIjoicXFfNjM2MzIyNDUifQ.5VhMEdO-GdBBLo6xOope-v1WHJ4KeBIgZCBO3PsfVyw&spm=1001.2101.3001.6650.6&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Eactivity-6-135046326-blog-132069360.235%5Ev43%5Epc_blog_bottom_relevance_base1&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Eactivity-6-135046326-blog-132069360.235%5Ev43%5Epc_blog_bottom_relevance_base1&utm_relevant_index=11)  
[quartz过期处理策略](https://www.quartz-scheduler.org/api/2.1.7/constant-values.html)  
[Quartz的12张数据库表说明](https://blog.csdn.net/mianyao1004/article/details/105363750)  