如何单独编译 Nacos 客户端源码并将其注入 Spring Cloud 中

如果你由于 Spring Cloud 应用业务内的问题,需要自定义 Nacos 的客户端部分代码;或者你是开源贡献者,为 Nacos 客户端部分贡献了部分代码,接下来希望能验证修改后的 Nacos 客户端在 Spring Cloud 中的可用性,那么你一定希望知道如何单独编译 Nacos 客户端部分的源码并将其注入至现有的 Spring Cloud 应用/demo 中。

不幸的是,Nacos 官方文档仅提供了服务端的编译安装方法。接下来,这篇博客就将介绍如何将新编译的 Nacos 客户端注入对应的 Spring Cloud Alibaba starter 中,将 starter 中固定版本的 Nacos 客户端替换为你本地编译的 Nacos 客户端。

单独编译 Nacos 客户端源码

首先,克隆 Nacos 主仓库,并进入该文件夹,推荐使用 idea 操作。

1
2
git clone https://github.com/alibaba/nacos.git
cd nacos

找到源代码中的 Nacos 版本并记录下来,这个版本一定是 未发布版本号-SNAPSHOT ,例如目前 Nacos 发布版本是 2.2.3,代码仓库中的 Nacos 版本则是 2.3.0-SNAPSHOT 。具体值需要参考根目录下的 pom.xml 中的 revision 字段:

1
2
3
4
5
6
7
8
9
10
11
...
<properties>
<!-- 就是这个👇 -->
<revision>2.3.0-SNAPSHOT</revision>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
...

接下来,需要使用 Maven 同时本地编译 nacos-clientnacos-commonnacos-api 。切记不要只编译 nacos-client

1
mvn clean install -DskipITs -Dmaven.test.skip=true -pl com.alibaba.nacos:nacos-client -pl com.alibaba.nacos:nacos-common -pl com.alibaba.nacos:nacos-api

随后,版本 2.3.0-SNAPSHOT 的 Nacos 客户端就会被编译到本地的 Maven 仓库中。再次提醒,不要只编译 nacos-client ,Nacos 客户端必须依赖对应版本的 nacos-commonnacos-api 包。

将本地编译完成的 Nacos 客户端注入 Spring Cloud Starter 中

通过 Maven 的 dependencyManagement 机制,我们可以将 Spring Cloud Alibaba Starter 中的 Nacos 客户端版本固定为我们本地编译的版本。

首先,我们需要导入 Nacos 的 Spring Cloud Starter 依赖,配置中心功能与服务注册/发现功能分别对应以下两个依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<properties>
<java.version>11</java.version>
<!--以下三个版本有一一对应关系,不能随意组合-->
<spring.boot.version>2.6.13</spring.boot.version>
<spring-cloud.version>2021.0.5</spring-cloud.version>
<spring.cloud.alibaba.version>2021.0.5.0</spring.cloud.alibaba.version>
<!--nacos 本地编译版本-->
<nacos.version>2.3.0-SNAPSHOT</nacos.version>
</properties>

<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>${spring.cloud.alibaba.version}</version>
</dependency>

<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>${spring.cloud.alibaba.version}</version>
</dependency>
...
</dependencies>

请注意,${spring.cloud.alibaba.version} 必须正确配置,详情可参考 Spring Cloud Alibaba 版本说明文档

随后,配置 dependencyManagement 即可将本地的 Nacos 客户端注入至这两个 Starter 中,替换其默认版本的 Nacos 客户端代码。此处必须将本地编译的 nacos-clientnacos-commonnacos-api 三个包都注入,否则会出现类初始化错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>${nacos.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-common</artifactId>
<version>${nacos.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-api</artifactId>
<version>${nacos.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

至此,我们成功将本地编译的 Nacos 客户端注入至 Spring Cloud 应用中。接下来,我们可以在这个应用中使用或测试新编译的 Nacos 客户端了。

附录:一个完整的 pom.xml 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.13</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.edu.bupt</groupId>
<artifactId>spring-practice</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-practice</name>
<description>spring-practice</description>

<properties>
<java.version>11</java.version>
<!--以下三个版本有一一对应关系,不能随意组合-->
<spring.boot.version>2.6.13</spring.boot.version>
<spring-cloud.version>2021.0.5</spring-cloud.version>
<spring.cloud.alibaba.version>2021.0.5.0</spring.cloud.alibaba.version>
<!--nacos 本地编译版本-->
<nacos.version>2.3.0-SNAPSHOT</nacos.version>
</properties>
<dependencies>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>

<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>${nacos.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-common</artifactId>
<version>${nacos.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-api</artifactId>
<version>${nacos.version}</version>
</dependency>

<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<exclusions>
<exclusion>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</exclusion>
<exclusion>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-common</artifactId>
</exclusion>
<exclusion>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-api</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<exclusions>
<exclusion>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</exclusion>
<exclusion>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-common</artifactId>
</exclusion>
<exclusion>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-api</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

</dependencies>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>${nacos.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-common</artifactId>
<version>${nacos.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-api</artifactId>
<version>${nacos.version}</version>
</dependency>

</dependencies>
</dependencyManagement>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.project-lombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>

</project>