从零开始调试 Canal:一个真实的踩坑记录
作者:一个刚踩完坑的新手 时间:2026-03-09 背景:想参与 Canal 开源项目的小白
前言
最近想参与开源项目,因为自己的项目用到了这个Canal组件(MySQL binlog 增量订阅组件),所以就选了从它入手。本想着 “不就是拉代码、编译、跑起来嘛”,结果踩了一堆坑。记录下来,给后来者避坑。
第一步:编译项目
坑 1:GPG 签名报错
按照 README 执行:
mvn clean install -DskipTests
结果报错:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-gpg-plugin:3.2.8:sign
只是想本地调试,签什么名啊?
解决:加上 -Dgpg.skip=true
mvn clean install -DskipTests -Dgpg.skip=true
坑 2:PowerShell 解析问题
如果你用 Windows PowerShell,直接复制命令可能报错:
[ERROR] Unknown lifecycle phase ".skip=true"
这是因为 PowerShell 把 -Dgpg.skip=true 解析错了。
解决:用引号包裹参数
mvn clean install "-DskipTests" "-Dgpg.skip=true"
或者直接用 CMD:
mvn clean install -DskipTests -Dgpg.skip=true
坑 3:Java 版本参数报错(Windows 用户专属)
编译通过后,用 startup.bat 启动 Canal Server:
.\startup.bat
结果:
Unrecognized VM option 'PermSize=128m'
Error: Could not create the Java Virtual Machine.
-XX:PermSize 是 Java 7 的参数,Java 8+ 已经改成 MetaspaceSize 了。
解决:修改 deployer/target/canal/bin/startup.bat(注意是 target 里的,不是 src 里的)
# 把这一行
set JAVA_MEM_OPTS= -Xms128m -Xmx512m -XX:PermSize=128m
# 改成
set JAVA_MEM_OPTS= -Xms128m -Xmx512m -XX:MetaspaceSize=128m
教训:开源项目的启动脚本可能年久失修,特别是 Windows 的 .bat 文件。
第二步:配置 MySQL 连接
坑 4:配置不生效
我修改了 deployer/src/main/resources/example/instance.properties:
canal.instance.master.address=ip:3306
canal.instance.dbUsername=root
canal.instance.dbPassword=123456
启动后看日志,发现 Canal 还是在连 127.0.0.1:3306!
内心OS:明明修改了配置为什么还有问题!
解决:原来 Canal 运行时用的是一个独立的 target/canal/conf 目录,不是 src/main/resources!
有两个办法:
- 改
deployer/target/canal/conf/example/instance.properties(临时调试用) - 或者改完 src 的重新打包(正式做法)
我选了第一种,终于看到日志里显示连接 192.168.12.168:13306 了。
日志验证:
2026-03-09 18:39:58.703 [...] find start position successfully,
EntryPosition[...j,ournalName=binlog.000005,position=334...]
看到 find start position successfully 就说明连上 MySQL 了。
第三步:IDE 调试
坑 5:断点打不上
想 debug 看看代码怎么走的,结果 IDE 里打断点没用,显示空心圆圈。
查了半天,发现是 VSCode 的 Java 项目没识别好。
解决:
- 确保安装了 “Extension Pack for Java”
- 执行
mvn clean compile -DskipTests -Dgpg.skip=true生成 class 文件 - 重启 VSCode,等右下角 “Java 项目加载完成” 的提示消失
然后配置 .vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Debug Canal Server",
"request": "launch",
"mainClass": "com.alibaba.otter.canal.deployer.CanalLauncher",
"projectName": "canal.deployer",
"cwd": "${workspaceFolder}/deployer/target/canal",
"vmArgs": [
"-Dcanal.conf=${workspaceFolder}/deployer/target/canal/conf/canal.properties"
]
},
{
"type": "java",
"name": "Debug Canal Client",
"request": "launch",
"mainClass": "com.alibaba.otter.canal.example.SimpleCanalClientTest",
"projectName": "canal.example"
}
]
}
终于能打断点了! 注:这个不太确定,大家最好结合AI工具试试,虽然我是成功了,但不确保其他机子成功。
第四步:理解代码
为了能参与贡献,我开始看 filter 模块的代码。
发现 AviaterRegexFilter 用了一个叫 Aviator 的表达式引擎。简单说就是把正则配置编译成表达式,然后执行。
代码大概长这样:
public boolean filter(String tableName) {
Map<String, Object> env = new HashMap<>();
env.put("pattern", "^test\\..*$|^order\\..*$");
env.put("target", tableName.toLowerCase());
return (Boolean) exp.execute(env); // 执行 Aviator 表达式
}
看了下代码,其实exp.execute就相当于list查找有没有当前字符串,只是用这个Aviator组件包装了一下
调试技巧:
- 在
AviaterRegexFilter构造函数打断点,看 pattern 怎么被处理 - 在
filter()方法打断点,看正则匹配过程
我还发现了一些潜在问题,比如:
- 每次调用都创建 HashMap(性能可优化)
但这些都是后话了,先跑起来再说。
总结:给新手的建议
| 问题 | 解决方案 |
|---|---|
| GPG 签名报错 | 加 -Dgpg.skip=true |
| PowerShell 解析错误 | 参数用引号包裹,或用 CMD |
| Java 参数错误 | 改 PermSize 为 MetaspaceSize |
| 配置不生效 | 改 target/canal/conf 下的文件 |
| 断点打不上 | 确保 Java 项目加载完,配置 launch.json |
关键目录结构:
canal/
├── deployer/src/main/resources/ # 源码配置(改完要重新打包)
├── deployer/target/canal/ # 运行时目录(调试时改这里)
│ ├── bin/startup.bat # Windows 启动脚本
│ ├── conf/canal.properties # 运行时配置
│ └── logs/ # 日志目录
└── filter/src/... # 模块源码(可以调试)
查看日志:
# 服务端日志
cat deployer/target/canal/logs/canal/canal.log
# 实例日志(最重要)
cat deployer/target/canal/logs/example/example.log
参与开源项目第一步总是最难的,但只要跑起来,后面就顺了。
祝大家少踩坑,多贡献!
相关链接
- Canal GitHub:https://github.com/alibaba/canal
- Canal 官方文档:https://github.com/alibaba/canal/wiki