ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Nacos 2.0.3源码编译实战:IDEA与Maven全流程踩坑记录

Nacos 2.0.3源码编译实战:IDEA与Maven全流程踩坑记录 做微服务这几年注册中心绕不开 Nacos。大多数时候我们直接去官网下载编译好的发行包解压改配置就能用但在有些场景下你会发现自己编译源码这件事根本躲不掉。比如公司安全审计要求产物必须从源码自构建比如你需要在 Nacos 源码里加一些定制逻辑再重新打包再比如你想把 Nacos 作为中间件做深度二次开发顺手还要调试它内部的工作机制。这些需求一旦出现第一步就是把 Nacos 源码在本地编译成可执行 jar 包。网上关于 Nacos 使用的教程非常多但专门讲“如何在 IDEA 里编译 Nacos 2.0.3 源码并成功打包成可执行 jar 包”的文章反而比较零散。我前前后后在不同机器上编过很多次 Nacos 源码从 JDK 版本踩坑到 Maven 检查插件报错从前端模块构建失败到 Windows 下打 tar.gz 失败基本把能踩的坑都踩了一遍。这篇文章就把我的完整流程和排查记录整理出来主要面向两类读者一是需要在本地从源码构建 Nacos 服务器包的人二是准备基于 Nacos 做二次开发、想在 IDEA 里直接跑起源码的人。1. 为什么非要自己编译 Nacos 源码1.1 什么场景下真的需要源码编译先泼一盆冷水如果你只是想把 Nacos 跑起来做注册中心或配置中心直接下载官方编译好的安装包就行没必要折腾源码编译。但下面几种情况源码编译几乎是刚需。第一种是定制化改造。Nacos 2.0.3 作为一个中间件很多企业会改它的鉴权逻辑、权限模型、注册心跳参数甚至自定义服务发现的数据存储。这些改动只能改源码改完以后必须自己走一遍编译打包流程。第二种是安全合规需要。有些公司对生产环境的组件有严格的供应链要求不允许直接使用从网上下载的二进制包必须自己从官方源码构建并保留构建记录和产物校验信息。这个场景下你不仅需要会编译还要能说清楚编译参数和产物结构。第三种是源码级学习与调试。Nacos 内部用了大量自研的分布式一致性协议和网络通信框架直接看源码比看文档理解得深得多。但光看代码不跑起来调试很多细节还是会漏掉这时候在 IDEA 里边编译边打断点就是刚需。1.2 编译前先对齐环境JDK 和 Maven 版本Nacos 2.0.3 官方推荐的编译环境是 JDK 1.8 和 Maven 3.2.5 及以上。官方说得宽泛但实际操作下来版本差异对成功率影响非常大。我个人的建议是如果你不想处理一堆奇怪的编译报错就老老实实用下面这套组合组件推荐版本可选版本注意事项JDK1.88u2018u1912.0.3 对 JDK 11 的兼容性一般JDK 17 会有模块化访问报错Maven3.6.33.5.4 / 3.8.x3.9.x 太新部分老插件会有兼容问题3.2.5 又太老IDEA2021.32022.x主要影响 Maven 插件识别和前端构建工具的配置Git2.x无用来拉取指定 tag 的源码这里重点说一下 JDK 版本。我曾经在一台只装了 JDK 11 的机器上直接编译 Nacos 2.0.3编译本身能过但打出来的包启动时报了一堆模块访问异常比如IllegalAccessError和ClassNotFoundException集中在sun.misc、java.nio相关类上。后来切回 JDK 8问题直接消失。所以如果你不是非要用新特性编译 Nacos 2.0.3 的时候建议 JDK 8 一条路走到底。Maven 版本也有讲究。Nacos 的构建链路里有很多老插件比如maven-assembly-plugin、frontend-maven-plugin这些插件在 Maven 3.9.x 下暴露过一些奇怪的兼容问题表现为“插件执行成功但产物缺失”或者“找不到某个生命周期阶段”。建议用 Maven 3.6.3这是当年绝大多数中间件项目验证过的稳定版本。2. 在 IDEA 中导入源码与第一次尝试2.1 源码导入的正确姿势源码不要从 GitHub 网页直接下载 zip 包虽然也能用但少了 git 信息后续想切版本或对比改动会很麻烦。用命令拉取指定 tag 是最干净的方式git clone https://github.com/alibaba/nacos.git cd nacos git checkout 2.0.3执行完以后你会看到类似下面的目录结构nacos/ ├── address ├── api ├── auth ├── client ├── common ├── config ├── consistency ├── console ├── core ├── distribution ├── naming ├── plugin ├── pom.xml └── ...然后打开 IDEA选择File - Open定位到刚才 clone 下来的nacos目录IDEA 会识别出这是一个 Maven 多模块项目。第一次导入会自动下载依赖这个过程在默认 Maven 仓库配置下会很痛苦因为中央仓库的访问速度实在不理想。强烈建议先确认你的 Mavensettings.xml里配置了阿里云或其他国内镜像源。等所有模块索引加载完毕再看项目结构IDEA 底部状态栏不再刷进度条说明依赖解析基本完成。2.2 导入后最容易被忽略的配置很多人导入源码后直接点编译然后立刻被各种报错糊脸。至少有三件事要做否则后面全是坑。第一设置文件编码为 UTF-8。在 IDEA 的Settings - Editor - File Encodings中把Global Encoding、Project Encoding和Default encoding for properties files全部设为 UTF-8。Nacos 源码里大量中文注释如果系统默认编码是 GBK编译时会出现unmappable character for encoding GBK的报错这是 Windows 平台最常见的问题之一。第二确认 Maven 的 JDK 配置。在 IDEA 的Settings - Build, Execution, Deployment - Build Tools - Maven - Importing里把 JDK for importer 设为 Java 8在Runner - JRE里也要选 Java 8。否则 IDEA 可能用自己默认的 JDK 版本去解析项目导致部分模块亮红。第三检查 Maven 的运行参数。如果机器内存一般建议给 Maven 设置一下构建内存避免编译到一半直接OutOfMemoryError。哪里设置还是在 Maven 设置里往下找Runner - VM Options填入-Xmx2048m。这些准备工作看起来琐碎但确实是决定整条编译链路顺不顺的核心。你前 10 分钟多花点时间后面能少折腾一两个小时。3. Maven 编译打包命令与参数逐个拆解3.1 让官方命令真正能跑起来Nacos 在 GitHub README 里给的构建命令是mvn -Prelease-nacos -Dmaven.test.skiptrue clean install这个命令理论上没问题但如果你真的原封不动地执行很可能会在某个模块卡住。原因在于 Nacos 的构建过程里默认启动了 RAT 许可证检查、Checkstyle 代码风格检查、SpotBugs 静态扫描和单元测试任何一个环节不满足条件都会让构建失败。我实际使用的命令是下面这组也是在多次踩坑后稳定下来的mvn -Prelease-nacos -Dmaven.test.skiptrue -Dspotbugs.skiptrue -Dcheckstyle.skiptrue -Drat.skiptrue clean install拆开看每个参数的含义-Prelease-nacos激活名为release-nacos的 Maven Profile它会启用distribution模块的完整打包流程只有加了它才会生成最终的发行包。-Dmaven.test.skiptrue跳过测试代码的编译和执行。等价于同时设置了maven.test.skip和skipTests比单独用-DskipTests更彻底速度也更快。-Dspotbugs.skiptrue跳过 SpotBugs 静态分析。这个检查非常耗时而且经常因为源码中一些无害的写法报警告然后被插件当成错误阻断构建。-Dcheckstyle.skiptrue跳过代码风格检查。你不改官方源码的话一般没问题但要是有自己的改动很容易因为缩进、import 顺序不符合规范而挂掉。-Drat.skiptrue跳过 Apache RAT 许可证检查。RAT 会检查每个源码文件头是否有 Apache License 声明如果你新增了文件但没写许可证头构建会直接失败。整个命令执行下来在一般性能的机器上需要 10 到 20 分钟取决于网络环境和你本地 Maven 仓库里已有的依赖数量。第一次构建最耗时因为要下载大量依赖。3.2 打包产物在哪里构建成功后发行包会在distribution/target目录下生成主要有两个文件nacos-server-2.0.3.tar.gz nacos-server-2.0.3.zip这两个文件内容一致视你的服务器系统选择其中一个上传即可。解压后目录结构是nacos/ ├── bin/ │ ├── shutdown.cmd │ ├── shutdown.sh │ ├── startup.cmd │ └── startup.sh ├── conf/ │ ├── application.properties │ ├── cluster.conf.example │ ├── nacos-mysql.sql │ └── ... ├── data/ ├── logs/ └── target/ └── nacos-server.jar看到target/nacos-server.jar了吗这个就是我们说的“可执行 jar 包”。启动脚本本质上就是找到这个nacos-server.jar然后用java -jar的方式启动它。所以当你看到有人讨论 Nacos 编译打包生成可执行 jar指的就是这个文件。3.3 提高编译成功率的小参数除了上面那组稳定命令还有几个参数建议见机行事。如果你在编译时提示某些模块依赖的版本找不到可能是本地仓库有损坏的半成品依赖可以先加-U强制更新快照版依赖mvn -U -Prelease-nacos -Dmaven.test.skiptrue -Dspotbugs.skiptrue -Dcheckstyle.skiptrue -Drat.skiptrue clean install如果机器内存够大可以用-T 4开启并行编译让多个模块同时构建节省一些时间mvn -T 4 -Prelease-nacos -Dmaven.test.skiptrue -Dspotbugs.skiptrue -Dcheckstyle.skiptrue -Drat.skiptrue clean install并行编译我建议在确认单线程能编过之后再使用否则报错信息会混杂在一起定位问题反而更麻烦。4. 常见报错与排查记录4.1 JDK 版本引发的报错在编译或启动阶段JDK 版本问题都是高发区而且表现很迷惑。编译阶段最常见的报错是[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project nacos-core: Fatal error compiling: 无效的目标发行版: 11或者反向的[ERROR] 无法访问com.sun.tools.javac...一般情况下都是 IDEA 里 Maven 使用的 JDK 和项目要求的 JDK 不一致导致的。检查顺序File - Project Structure - Project SDK是否为 Java 8再看 Maven Runner 的 JRE 是否为 Java 8两个地方必须保持一致。启动阶段如果用的 JDK 版本过高会看到类似Caused by: java.lang.IllegalAccessError: class com.alibaba.nacos.common.utils.Observer cannot access its superclass sun.misc.Unsafe这种报错在 JDK 11 以上经常出现原因就是 Nacos 2.0.3 内部有些类依赖了早期 JDK 里的sun.misc包后续版本把相关 API 封了。解决办法有两个方向一是换 JDK 8这是最推荐的二是硬着头皮给启动命令加一堆--add-opens参数但即便加上去后续还可能有其他兼容问题冒出来不建议折腾。4.2 Maven 版本与镜像配置问题Maven 3.9.x 在编译 Nacos 2.0.3 时有一个比较典型的报错[ERROR] Failed to execute goal org.apache.maven.plugins:maven-assembly-plugin:3.3.0:single ... The forked VM terminated without properly saying goodbye. VM crash or System.exit called这个报错很容易让人误以为是内存不足但换回 Maven 3.6.3 后再跑就一切正常。我建议你直接在settings.xml里确认一下版本不要用 IDEA 自带的 Maven 或系统里最新安装的 Maven。另一个高频问题就是依赖下载慢或者直接失败报错信息一般是Could not transfer artifact com.alibaba.nacos:nacos-consistency:jar:2.0.3 ... Connection reset这种十有八九是中央仓库网络问题。解决办法是在settings.xml里配置镜像mirror idaliyunmaven/id mirrorOfcentral/mirrorOf name阿里云公共仓库/name urlhttps://maven.aliyun.com/repository/public/url /mirror注意配完镜像后如果依赖还是报错可以删掉本地仓库中对应该依赖的目录再重新构建。因为之前可能已经下载了损坏的半成品文件。4.3 前端控制台构建失败Nacos 2.0.3 的编译过程里控制台模块nacos-console会触发前端资源构建。这个环节用的是frontend-maven-plugin它会自动下载 Node.js 和 npm 来编译前端项目所以非常吃网络。常见报错如下[INFO] Installing node version v12.22.12 [INFO] Downloading https://nodejs.org/dist/v12.22.12/node-v12.22.12-linux-x64.tar.gz ... [ERROR] Could not download node: Connection reset对即便你配了 Maven 镜像这个 Node.js 的下载地址也不会走 Maven 镜像它还是从 nodejs.org 下载。碰到这种问题有几种处理方式。一种是在console/pom.xml里把frontend-maven-plugin的下载地址改成国内镜像。找到node那个configuration把downloadRoot改成https://npmmirror.com/mirrors/node/把npmRegistryURL改成https://registry.npmmirror.com。这种方式能解决问题但改动 pom 文件后后续拉取新代码时要注意冲突。另一种更直接就是在本地手动安装 Node.js并保证node和npm命令在 PATH 里。frontend-maven-plugin如果检测到本地 Node 版本满足要求会跳过下载步骤。还有一种偷懒但凑合的办法如果你对前端控制台没有定制需求核心只要服务端功能可以考虑只编译core、naming、config、common等后端模块不编console。但没有控制台的话Nacos 的运维和查看功能会受到很大影响一般只适合纯接口调用场景不太推荐正式使用。4.4 Windows 下打 tar.gz 包失败在 Windows 上编译 Java 项目打 zip 包通常没问题但打 tar.gz 包时很可能报[ERROR] Failed to execute goal org.apache.maven.plugins:maven-assembly-plugin:... Cannot run program tar: CreateProcess error2, 系统找不到指定的文件原因很简单Windows 默认没有tar命令较新的 Windows 10/11 自带 BSD tar但不一定兼容 Maven 插件调用方式。你可能会想那我把distribution/target里生成的 zip 包拿走去用不就行了话是这么说但 maven-assembly-plugin 在release-nacosprofile 下可能把 tar.gz 生成作为默认目标一旦失败整个distribution模块的构建就挂了所以还是得解决。最省事的方式是安装 Git for Windows它自带的 Git Bash 环境里有tar并且会把相关命令加入系统 PATH。装完以后重新打开 IDEA让它重新读取环境变量再执行打包命令一般就能通过。4.5 内存不足与构建超时Nacos 源码模块多编译时 Maven 进程会加载大量类如果MAVEN_OPTS或 IDEA 里 Maven Runner 的 VM 参数没调大可能出现[ERROR] Java heap space [INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE解决方式前面提过给 Maven 设置-Xmx2048m如果机器内存充足-Xmx4096m也行。这里不建议直接改环境变量里的MAVEN_OPTS到全局只改 IDEA 里 Maven Runner 的 VM Options 就够了避免影响其他项目的构建行为。构建超时多见于首次构建因为需要下载大量依赖如果网络不稳定某个依赖下载卡住整个构建就像死了一样。解决办法是先执行一次简单的mvn dependency:go-offline把依赖尽量拉到本地然后再开始正式构建。这个方法在低网速场景下非常管用。4.6 编译成功但 IDEA 里仍然报红源码能通过 Maven 命令编译但 IDEA 项目里还是有很多类飘红这个问题也经常出现。这时候不要慌多半是 IDEA 的索引和 Maven 模型没有同步。处理办法依次执行点 Maven 工具窗口右上角的Reload All Maven Projects让 IDEA 重新读取所有模块的 pom。执行File - Invalidate Caches / Restart清掉索引缓存。如果还不行退出 IDEA到项目根目录删掉.idea目录重新导入项目。注意删掉.idea目录会丢失你之前的运行配置和窗口布局但这是最后手段一般前两种已经能解决 90% 的问题。4.7 启动时报错端口占用与配置缺失编译打包都通过了解压后在命令行启动还是会遇到问题。最常见的是端口占用java.net.BindException: Address already in use如果 8848 端口被占用要么杀掉占用进程要么修改conf/application.properties里的server.port。改完端口后控制台的访问地址也要对应改。另一种常见问题是在没有做任何配置修改的情况下直接跑单机模式后控制台页面卡在登录页账号密码怎么试都进不去。Nacos 2.0.3 默认开启了控制台登录初始账号和密码是nacos/nacos。如果你使用的是源码默认配置且没有连接外部数据库第一次登录后建议立刻修改默认密码。但如果你连的是外部数据库账号密码由nacos_user表初始化脚本决定默认也是nacos/nacos。还有一类报错在日志里能看到[ERROR] The Nacos cluster initialization failed: [nacos] is not set这个一般指集群配置没有初始化。如果只做单机测试启动时一定要加-m standalone参数sh startup.sh -m standaloneWindows 下对应startup.cmd -m standalone如果不加Nacos 默认按集群模式启动会去读取cluster.conf找不到配置文件就会报错。5. 拿到可执行 jar 包之后的验证与使用5.1 启动与验证打包成功后先别急着把包上传到生产环境本地跑一遍验证是很有必要的。把distribution/target/nacos-server-2.0.3.tar.gz解压进入解压目录执行sh bin/startup.sh -m standalone启动过程中观察日志。Nacos 的日志在logs/目录下重点看两个文件start.out和nacos.log。start.out是启动脚本捕获的标准输出如果启动失败会有异常堆栈正常运行一段时间后里面会看到类似Nacos started successfully in stand alone mode. use embedded storage看到这行基本就说明启动成功了。之后访问http://localhost:8848/nacos能看到控制台登录页面用nacos/nacos登录如果页面正常展示说明整个构建产物没有问题。5.2 修改默认配置如果要在本地验证时接入 MySQL而不是用内置的 Derby 存储需要改conf/application.propertiesspring.datasource.platformmysql db.num1 db.url.0jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncodingutf8connectTimeout1000socketTimeout3000autoReconnecttrueuseUnicodetrueuseSSLfalseserverTimezoneAsia/Shanghai db.userroot db.passwordroot数据库需要提前执行conf/nacos-mysql.sql初始化脚本Nacos 的表结构都在这里面。注意Nacos 2.0.3 对 MySQL 驱动版本比较敏感如果连的 MySQL 版本过高可能会提示驱动类和加密插件不兼容这时需要检查驱动包版本是否符合 Nacos 依赖。5.3 二次开发时在 IDEA 里直接调试如果你不只是想打包还想基于 Nacos 源码做二次开发在 IDEA 里直接调试显然比每次改完都重新打包重启要高效得多。我的做法是找到console模块下的com.alibaba.nacos.Nacos主类然后创建一个 Application 运行配置。在VM options里加-Dnacos.standalonetrue工作目录建议设置为distribution/conf所在的环境或者直接在console模块下看你要加载哪一份配置。为了让 logback 和配置文件能被正确加载有时需要把distribution/conf目录下的内容复制到console/src/main/resources目录下否则部分配置读取不到。然后直接点运行就能在 IDEA 里打断点调试 Nacos 的服务端逻辑。调试状态启动完成后控制台、注册中心、配置中心都可以通过本地端口访问。测试代码直接注册服务、发布配置然后看服务端断点有没有命中整个调试闭环非常顺滑。改完代码后如果还想要一个干净的发行包再执行一次第 3 节里的 Maven 命令即可。6. 过程中最值得记住的几个经验这条路我走过很多次最有感触的是两点。第一编译中间件源码前一定要检查环境尤其是 JDK 和 Maven 版本这两个东西不匹配后面所有报错都是连锁反应。第二不要把 Maven 构建的输出直接当成最终产物先验证、再上传、再使用Nacos 这种带前端模块和存储模块的中间件编译成功不代表运行正常跑一遍启动流程比什么都稳。如果你想长期维护一个 Nacos 二次开发分支建议把构建参数写进项目的README或者写成一个build.sh脚本放到仓库里这样团队里任何一个人拉下代码都能一键构建。另外每次构建完可以把生成的 tar.gz 包名的版本号做一下标记避免和官方 Release 混淆这种细节在安全审计的时候能省很多事。
返回列表