Canal 升级 jar 包操作文档(以升级 FastJSON 为例)
文档背景:生产 Canal 集群使用的 FastJSON 版本存在已知反序列化漏洞(如 CVE-2022-25845),需要升级 jar 包修复。本文以 FastJSON 升级为例,完整记录 Canal jar 包升级的流程、命令、验证方式及踩坑记录。
脱敏说明 :本文为脱敏版本,涉及环境地址、域名、IP、账号密码、部署路径等敏感信息均已替换为占位符(
<...>),结构与操作命令完整保留,可直接套用到其他环境。
1. 文档说明
1.1 适用范围
- Canal 1.1.x 系列(canal.deployer + canal.admin)
- 部署方式:二进制 tar.gz 解压部署
- 本文实例环境:Canal 1.1.5,admin manager 管理模式
1.2 环境信息(本文操作环境)
| 项目 | 说明 |
|---|---|
| Canal 版本 | 1.1.5(deployer + admin) |
| 部署目录 | /opt/canal/server(Canal Server) |
/opt/canal/admin(Canal Admin) |
|
| 管理模式 | admin manager 模式(实例配置下发自 admin) |
| admin 地址 | http://<canal-admin域名>:8089 |
| admin 数据库 | <admin数据库主机>:3306 / 库名 <库名> |
| 实例数量 | 多个(如 <实例名> 等) |
1.3 升级前必须知道的两件事
- admin 管理模式 :实例配置(
instance.properties)存在 admin 数据库中,由 admin 下发到 Canal Server。本地conf/目录下默认只有example实例,不要在本地改实例配置(改了不生效)。 - jar 升级不影响消费端:Canal Server 与消费端通过 TCP/Kafka 传输的是 protobuf 格式,不依赖 FastJSON 序列化,升级 Server 侧 jar 不影响下游消费端 SDK。
2. 升级方案选择
方案一:FastJSON 1.2.84(推荐,本次实际采用)
- 1.x 系列的最终修复版本,补齐了主要反序列化漏洞。
- 包名不变 (
com.alibaba.fastjson.*),零代码改动,风险最低。
bash
# 下载地址
https://repo1.maven.org/maven2/com/alibaba/fastjson/1.2.84/fastjson-1.2.84.jar
方案二:FastJSON 2.x(2.0.51)+ 兼容包
- 彻底修复、长期维护,但需要额外引入
fastjson2-extension兼容包才能兼容老包名。 - 老代码如果使用
com.alibaba.fastjson.*包名,必须两个 jar 同时放入 lib。
bash
https://repo1.maven.org/maven2/com/alibaba/fastjson2/fastjson2/2.0.51/fastjson2-2.0.51.jar
https://repo1.maven.org/maven2/com/alibaba/fastjson2/fastjson2-extension/2.0.51/fastjson2-extension-2.0.51.jar
结论:生产环境优先选择方案一(1.2.84),稳定后再评估 2.x。
3. 操作步骤
3.1 升级前检查:确认当前 FastJSON 版本与位置
bash
cd /opt/canal/server
find . -name "fastjson*.jar"
cd /opt/canal/admin
find . -name "fastjson*.jar"
重点:fastjson jar 可能出现在多个位置,必须全部替换,否则类加载优先命中旧版本,升级失效:
server/lib/fastjson-1.2.xx.jar
server/plugin/<插件>/lib/fastjson-1.2.xx.jar # 如有
admin/lib/fastjson-1.2.xx.jar
3.2 停止服务
先停 Canal Server,再停 Canal Admin(升级两个组件时):
bash
cd /opt/canal/server
sh bin/stop.sh
cd /opt/canal/admin
sh bin/stop.sh
# 确认无残留进程
jps -l | grep -i canal
⚠️ 踩坑记录:
stop.sh依赖 PID 文件(logs/canal.*.pid)。若 PID 文件残留(进程被 kill -9 或服务器重启过),stop.sh 会报kill: (xxxxx) - No such process并提示 "is not running",但真实进程仍在。此时必须:
bash# 用 jps 找到真实进程 PID jps -l | grep -i canal kill <真实PID> # 确认停止后再清理残留 PID 文件 rm -f /opt/canal/admin/logs/canal.admin.pid
3.3 备份旧 jar
bash
cd /opt/canal
mkdir -p backup/fastjson-bak
find server admin -name "fastjson*.jar" \
-exec cp -p {} backup/fastjson-bak/ \;
ls -l backup/fastjson-bak/
3.4 下载新版本 jar
有外网环境直接下载:
bash
cd /opt/canal/server/lib
wget https://repo1.maven.org/maven2/com/alibaba/fastjson/1.2.84/fastjson-1.2.84.jar
说明:公共 Maven 中央仓库的 fastjson 1.x 系列版本只发布到 1.2.83,若按上述地址下载不到 1.2.84,请从公司内部 Maven 仓库/离线包获取(实际升级的 1.2.84 jar 来源以实际部署为准),URL 拼接规则一致。
无外网环境(生产常见),在本地下载后 scp 上传:
bash
# 本地执行
scp fastjson-1.2.84.jar <账号>@<服务器>:/opt/canal/server/lib/
3.5 替换所有位置的 jar
bash
cd /opt/canal
# 先列出所有待替换位置(以实际输出为准)
find server admin -name "fastjson*.jar"
# 1. 替换 server/lib
rm -f server/lib/fastjson-*.jar
cp server/lib/fastjson-1.2.84.jar server/lib/
# 2. 替换 plugin 下各插件目录(如有)
for d in server/plugin/*/lib; do
rm -f "$d"/fastjson-*.jar
cp server/lib/fastjson-1.2.84.jar "$d"/
done
# 3. 替换 admin/lib
rm -f admin/lib/fastjson-*.jar
cp server/lib/fastjson-1.2.84.jar admin/lib/
验证替换结果:
bash
find server admin -name "fastjson*.jar" -exec ls -l {} \;
应全部显示为 fastjson-1.2.84.jar,无旧版本残留。
3.6 启动并验证
bash
# 先启动 admin(server 依赖 admin 下发配置)
cd /opt/canal/admin
sh bin/startup.sh
sleep 5
tail -f logs/admin.log
# 再启动 server
cd /opt/canal/server
sh bin/startup.sh
sleep 5
tail -f logs/canal/canal.log
tail -f logs/example/example.log
# 进程确认
jps -l | grep -i canal
重点关注日志是否出现:
ClassNotFoundException: com.alibaba.fastjson.JSON→ 新 jar 未放入对应目录NoSuchMethodException/NoClassDefFoundError→ 有目录仍残留旧 jar,需再清理- 实例日志出现
start successful....、find start position successfully→ 正常
3.7 功能回归验证
- 登录 canal-admin Web,确认各实例状态为「启动」、实例列表正常。
- 在各实例对应的源库执行一条变更(增/删/改),确认下游消费端能正常收到数据。
- 观察 24 小时,确认无 OOM、无异常日志。
4. 常见问题
4.1 stop.sh 报 No such process,但进程还在
见 3.2 踩坑记录:PID 文件残留。用 jps 找真实 PID 手动 kill,并清理 PID 文件。务必等 jps 确认停干净再操作,否则替换 jar 后启动会异常。
4.2 启动报 ClassNotFoundException / NoSuchMethodException
大概率是某个目录的 fastjson jar 没替换到。执行:
bash
find /opt/canal/server /opt/canal/admin -name "fastjson*.jar"
确认所有位置的 jar 版本一致;若混放 1.2.x 与 2.x 的 jar,删除多余的旧版本。
4.3 服务器没有外网 / 没有 mysql 客户端
- 无外网:本地下载后 scp 上传(见 3.4)。
- 无 mysql 客户端(操作 admin 库需要时):
sudo yum install -y mariadb临时安装。
4.4 升级后实例报错,需要回滚
bash
# 停止
sh bin/stop.sh
# 用 3.3 备份的旧 jar 还原
cp backup/fastjson-bak/fastjson-1.2.xx.jar lib/
# 启动
sh bin/startup.sh
5. 经验总结
- 替换前必须完整停服(包括 admin),替换后先 admin 后 server 的顺序启动。
- fastjson jar 位置多 ,一定用
find全量定位后再替换,避免漏替换导致类冲突。 - admin manager 架构下,实例配置在库里不在本地 :不要在本地
conf/改实例配置;升级 jar 也不需要动任何实例配置。 - 升级 jar 包与实例位点(cursor)无关:如果升级后实例报 binlog 相关错误(如 errno 1236),是位点失效问题,不是 jar 升级导致,需按位点重置流程处理(见《Canal GTID 位点失效解决方案》)。
- 升级前务必备份(旧 jar、实例配置),保证可回滚。
附录 A:FastJSON 漏洞背景(为什么升级)
FastJSON 1.2.x 系列存在多个反序列化 RCE 漏洞(如 CVE-2022-25845,com.alibaba.fastjson 1.2.80 及以下受影响),漏洞在 1.2.83/1.2.84 与 2.x 中修复。Canal 内置的 FastJSON 版本较旧(1.2.28 ~ 1.2.58),属于受影响范围,故需升级。实际生产升级采用 FastJSON 1.2.84。
附录 B:本文相关命令速查
bash
# 全量定位 fastjson jar
find /opt/canal -name "fastjson*.jar"
# 停止与确认
sh bin/stop.sh && jps -l | grep -i canal
# 备份
find server admin -name "fastjson*.jar" -exec cp -p {} backup/fastjson-bak/ \;
# 替换(server/lib 示例)
rm -f server/lib/fastjson-*.jar
cp fastjson-1.2.84.jar server/lib/
# 启动与看日志
sh bin/startup.sh
tail -f logs/canal/canal.log