
一次改造实战版本对齐、编译报错、语义变化和留痕搜索项目要用 Canal 把 MySQL 的变更增量同步到 Elasticsearch。问题来了下载的 client-adapter客户端适配器默认只支持到 ES 6.4而项目里用的是 ES 7.3。为了版本统一只能对 client-adapter 动手改造。这类改造很容易被写成“改三处版本号再加个.value编译通过就完事”。我的观点是编译通过只说明语法对了不说明语义对了。下面是我认为改造时必须想清楚的六件事。01先确认有没有官方支持再决定要不要“魔改”动源码是最后一招不是第一步。动手前先查一下你用的 Canal 版本或者更新的版本是否已经提供了 ES 7 对应的适配器模块较新的 Canal 版本在 client-adapter 下拆分了不同 ES 版本的模块具体模块名和起始版本以官方 release 说明为准我这里没有逐版本核对。取如果官方已支持直接升级 Canal 版本省掉自己维护一份分叉代码的长期成本。舍因为 Canal 其他版本不兼容现有环境、或需要改动其他逻辑必须停留在当前版本时才走改造路线并清楚自己要维护一个补丁。02改版本号只是开始先找到该改的三处在 canal-master 中打开 client-adapter 模块等 Maven 把依赖更新好然后调整 elasticsearch 模块 pom 文件里与 ES 版本相关的几处旧版本号原文是三处一般是 ES 本体及相关客户端依赖统一改成与集群一致的 7.3.x。版本号要和集群对齐客户端版本与服务端同主版本最稳妥。03打包前先过一关你用的是 JDK 还是 JRE在 canal-master 根目录重新打包mvn clean package -DskipTests如果报No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?意思是 Maven 当前用的是 JRE没有编译器。原文的做法是在mvn.cmd开头加一行set JAVA_HOME...能用但它修改的是 Maven 的启动脚本会影响这台机器上所有项目。更干净的做法把JAVA_HOME设成 JDK 的目录不是 JRE重开命令行后用mvn -v确认输出的 Java home 指向 JDK。如果只想临时生效在当前命令行窗口执行set JAVA_HOME你的JDK路径后再运行 mvn 即可不用改mvn.cmd。另外这里用-DskipTests是因为我们在构建第三方源码不是自己的业务项目可以接受。你自己的项目里不建议养成这个习惯。04编译报错是在帮你找“破坏性变更”升级后编译会报错典型的一条ESAdapter.java中TotalHits无法转换为long。原因是 ES 7 把getTotalHits()的返回值从long改成了TotalHits对象它里面除了命中数value还有一个relation。所以要在后面补上.value// ES 6直接返回 long long total response.getHits().getTotalHits(); // ES 7返回对象取命中数要用 .value long total response.getHits().getTotalHits().value;改完后继续编译。不用从头再来Maven 会在失败时给出续跑提示可以用-rfresume from从失败的模块继续mvn package -DskipTests -rf :失败模块的artifactId编译完成后直接使用打好的 client-adapter 即可。05.value 不是终点语义变化比语法更危险这是我最想强调的一点。.value让代码能编译但 ES 6 到 7 有几处语义变化编译器不会告诉你变化风险检查方法总命中数默认有上限ES 7 默认只精确计数到 1 万relation可能是“大于等于”。如果适配器逻辑用总数做判断比如校验、分页数据超过 1 万就会出错看.value用在哪需要精确总数时查询里设置trackTotalHitsType 被弱化ES 7 起 mapping type 已被弃用统一用_doc。适配器配置里的_type、索引请求里的 type可能产生警告甚至失败检查同步配置文件里的_type以及创建索引、写入文档的代码客户端类型与端口旧版适配器可能用的是 TransportClient走 9300 端口它在 7.x 已被弃用在 8.0 被移除REST 客户端走 9200确认适配器实际使用哪种客户端以及配置里的地址和端口是否对得上判断编译通过后不要立刻宣布完成。真正的验收是跑一遍增量同步而不是看构建成功。编译提示ESAdapter.java:[225,56] 不兼容的类型无法转换为long[ERROR] /canal-master/client-adapter/elasticsearch/src/main/java/com/alibaba/otter/canal/client/adapter/es/ESAdapter.java:[225,56] 不兼容的类型: or g.apache.lucene.search.TotalHits无法转换为long解决方法在getTotalHits后增加value因为ES7后扩大了TotalHits的范围06魔改第三方要有纪律留痕、可回放、有验收**Fork 并留痕**把改动放进你自己的 Git 仓库或补丁文件记录基于哪个版本、改了哪几处、为什么改。下载的源码目录改完就丢半年后没人知道这个包是怎么来的。**固定产物版本**给打出来的包标上版本和构建日期在文档里写明它与官方包的差异。**做回归验收**在测试环境对 MySQL 做一次新增、修改、删除确认 ES 里的文档同步正确再测试一次超过 1 万条数据的场景检查总数逻辑最后看 Canal 和 adapter 的日志里有没有 type 或版本相关的警告。**评估长期成本**以后 Canal 或 ES 再升级你的补丁要不要重新合并是否有精力持续维护。一句话总结升级版本改的不只是版本号。编译通过只是起点语义对齐才是终点先看官方是否已支持改版本号后用编译报错找 API 变化再检查计数上限、type、客户端这些编译器看不到的变化最后用增量同步测试验收并把补丁留痕。说明版本号、模块名和参数以你使用的 Canal 与 Elasticsearch 实际版本为准。