Skip to content

Commit 8b413db

Browse files
committed
add nacos config sample in springboot
1 parent bb03d61 commit 8b413db

File tree

12 files changed

+897
-0
lines changed

12 files changed

+897
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
- ##### [SpringBoot集成Hmily框架-实现TCC模式柔性事务;](https://github.com/ipipman/JavaSpringBootSamples/tree/master/springboot-hmily-tcc-sample "SpringBoot集成Hmily框架,实现TCC模式柔性事务;")
99
- ##### [SpringBoot集成gRPC框架-实现RPC服务;](https://github.com/ipipman/JavaSpringBootSamples/tree/master/springboot-rpc-grpc-sample "SpringBoot集成gRPC框架,实现RPC服务;")
1010
- ##### [SpringBoot集成Thrift框架-实现RPC服务;](https://github.com/ipipman/JavaSpringBootSamples/tree/master/springboot-rpc-thrift-sample "SpringBoot集成Thrift框架,实现RPC服务;")
11+
- ##### [SpringBoot集成Nacos框架-实现配置中心;](https://github.com/ipipman/JavaSpringBootSamples/tree/master/springboot-nacos-sample "SpringBoot集成Nacos框架-实现配置中心;")
12+
1113

1214
### Dubbo相关实例
1315
- ##### [分布式服务框架Dubbo-基于注解配置的方式](https://github.com/ipipman/JavaSpringBootSamples/tree/master/dubbo-annotation-sample "分布式服务框架Dubbo(基于注解配置的方式)")

springboot-nacos-sample/.gitignore

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
HELP.md
2+
target/
3+
!.mvn/wrapper/maven-wrapper.jar
4+
!**/src/main/**/target/
5+
!**/src/test/**/target/
6+
7+
### STS ###
8+
.apt_generated
9+
.classpath
10+
.factorypath
11+
.project
12+
.settings
13+
.springBeans
14+
.sts4-cache
15+
16+
### IntelliJ IDEA ###
17+
.idea
18+
*.iws
19+
*.iml
20+
*.ipr
21+
22+
### NetBeans ###
23+
/nbproject/private/
24+
/nbbuild/
25+
/dist/
26+
/nbdist/
27+
/.nb-gradle/
28+
build/
29+
!**/src/main/**/build/
30+
!**/src/test/**/build/
31+
32+
### VS Code ###
33+
.vscode/
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* Copyright 2007-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
import java.net.*;
17+
import java.io.*;
18+
import java.nio.channels.*;
19+
import java.util.Properties;
20+
21+
public class MavenWrapperDownloader {
22+
23+
private static final String WRAPPER_VERSION = "0.5.6";
24+
/**
25+
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
26+
*/
27+
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
28+
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
29+
30+
/**
31+
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
32+
* use instead of the default one.
33+
*/
34+
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
35+
".mvn/wrapper/maven-wrapper.properties";
36+
37+
/**
38+
* Path where the maven-wrapper.jar will be saved to.
39+
*/
40+
private static final String MAVEN_WRAPPER_JAR_PATH =
41+
".mvn/wrapper/maven-wrapper.jar";
42+
43+
/**
44+
* Name of the property which should be used to override the default download url for the wrapper.
45+
*/
46+
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
47+
48+
public static void main(String args[]) {
49+
System.out.println("- Downloader started");
50+
File baseDirectory = new File(args[0]);
51+
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
52+
53+
// If the maven-wrapper.properties exists, read it and check if it contains a custom
54+
// wrapperUrl parameter.
55+
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
56+
String url = DEFAULT_DOWNLOAD_URL;
57+
if(mavenWrapperPropertyFile.exists()) {
58+
FileInputStream mavenWrapperPropertyFileInputStream = null;
59+
try {
60+
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
61+
Properties mavenWrapperProperties = new Properties();
62+
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
63+
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
64+
} catch (IOException e) {
65+
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
66+
} finally {
67+
try {
68+
if(mavenWrapperPropertyFileInputStream != null) {
69+
mavenWrapperPropertyFileInputStream.close();
70+
}
71+
} catch (IOException e) {
72+
// Ignore ...
73+
}
74+
}
75+
}
76+
System.out.println("- Downloading from: " + url);
77+
78+
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
79+
if(!outputFile.getParentFile().exists()) {
80+
if(!outputFile.getParentFile().mkdirs()) {
81+
System.out.println(
82+
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
83+
}
84+
}
85+
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
86+
try {
87+
downloadFileFromURL(url, outputFile);
88+
System.out.println("Done");
89+
System.exit(0);
90+
} catch (Throwable e) {
91+
System.out.println("- Error downloading");
92+
e.printStackTrace();
93+
System.exit(1);
94+
}
95+
}
96+
97+
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
98+
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
99+
String username = System.getenv("MVNW_USERNAME");
100+
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
101+
Authenticator.setDefault(new Authenticator() {
102+
@Override
103+
protected PasswordAuthentication getPasswordAuthentication() {
104+
return new PasswordAuthentication(username, password);
105+
}
106+
});
107+
}
108+
URL website = new URL(urlString);
109+
ReadableByteChannel rbc;
110+
rbc = Channels.newChannel(website.openStream());
111+
FileOutputStream fos = new FileOutputStream(destination);
112+
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
113+
fos.close();
114+
rbc.close();
115+
}
116+
117+
}
49.5 KB
Binary file not shown.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
2+
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar

springboot-nacos-sample/README.md

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
# SpringBoot集成Nacos框架-实现配置中心
2+
3+
### 什么是Nacos?
4+
Nacos是阿里开源的一个产品,主要针对微服务架构中的服务发现、配置管理、服务治理的综合性解决方案;
5+
Nacos的四大功能:
6+
> - 服务发现与服务健康检查;
7+
> - 动态配置管理;
8+
> - 动态DNS服务;
9+
> - 服务和源数据管理;
10+
11+
### Zookeeper和Nacos的对比
12+
Nacos在微服务场景中,主要用于配置中心和服务注册中心。这两块功能也是Zookeeper擅长的事情,以下我们分析下两者的不同处。
13+
14+
#### 1.Zookeeper
15+
Zookeeper的功能主要是它的树型节点来实现的。当数据变化的时候或者节点过期的时候,会通过事件触发通知对应的客户端数据变化了,然后客户端再请求ZK获取最新的数据,采用push-pull来做数据更新;
16+
17+
其中ZK最重要的就是它的ZAB协议了(消息广播和消息恢复)
18+
**消息广播**:集群中ZK在数据更新的时候,通过Leader节点将消息广播给其他Follower节点,采用简单的两阶段提交模式,先Request->ACK->Commit,当超过一半的Follower节点响应时,就可以提交更新了;
19+
20+
**奔溃恢复**:当Leader挂了,或者超过半数Follower投票得出Leader不可用,那么会重新选举,这段时间内ZK服务是不可用的。通过最新的XID来选举出新的Leader,选举出来的后将新的Leader中的数据更新给超过半数的Follower节点后,此时才能对外提供服务;
21+
22+
#### 2.Nacos
23+
Nacos中配置中心和注册中心分别是两套实现,和ZK不同。
24+
25+
##### 2.1 对比配置中心
26+
Nacos和Zookeeper都可以作为配置中心,做一些可以实时变化的配置数据存储,然后实时更新线上数据。
27+
**Nacos**:依赖Mysql数据库做数据存储,当数据更新的时候,直接更新数据库的数据,然后将数据更新的信息异步广播给Nacos集群中所有服务节点数据变更,再由Nacos服务节点更新本地缓存,然后将通知客户端节点数据变化。
28+
29+
** Zookeeper**:利用ZK的树型结构做数据存储,当有数据更新的时候,使用过半机制保证各个节点的数据一致性,然后通过ZK的事件机制通知客户端。
30+
31+
这里的差异:
32+
> - 服务器存储的位置不同,分别采用Mysql和ZK本身存储;
33+
>
34+
> - 消息发送,一个采用过半机制保证一致性,另一个异步广播,通过后台线程重试保证;
35+
36+
##### 2.2 对比注册中心
37+
38+
**Nacos**:支持两种方式的注册中心,持久化和非持久化存储服务信息。
39+
40+
> - **非持久化** 直接存储在Nacos服务节点的内存中,并且服务节点采用去中心话的思想,服务节点采用Hash分片存储注册信息;
41+
>
42+
> - **持久化** 使用Raft协议选举Master节点,同样采用过半机制将数据存储在Leader节点上;
43+
>
44+
**Zookeeper**:利用zk的树型结构做数据存储,服务注册和消费信息直接存储在zk树形节点上,集群下同样采用过半机制保证服务节点间一致性;
45+
46+
这里的差异:
47+
48+
> - Nacos同时支持 持久化和非持久化存储,也就是支持CAP原则中的AP和CP特性,Nacos的CP持久化和ZK模式类似。Nacos默认采用AP非持久化,非持久化使用内存存储速度更快,而且Hash分片存储,不利点就是某个服务挂掉,可能出现部分时间调用失败。因为服务调用本身就是实时的,持久化存储起来意义不大,反而及时变化更适合。
49+
50+
51+
### Nacos的基础概念
52+
<img src="https://ipman-blog-1304583208.cos.ap-nanjing.myqcloud.com/dubbo/34201608729038_.pic_hd.jpg" width = "430" height = "300" alt="图片名称" align=center />
53+
54+
#### 命名空间
55+
命名空间(NameSpace)用于不同环境(开发环境、测试环境和生产环境)的配置隔离。不同的命名空间下,可以存在相同名称的配置分组(Group)或配置集。
56+
57+
#### 配置分组
58+
配置分组是对配置集进行分组,不同的配置分组下可以有相同的配置集(DateId)。默认的配置分组名称为 DEFAULT_GROUP。用于区分不同的项目或应用。
59+
60+
#### 配置集
61+
在系统中,一个配置文件通常就是一个配置集,包含了系统各个方面的配置。
62+
63+
64+
### Nacos-Server部署
65+
#### 1.下载安装
66+
```json
67+
//下载编译后的最新zip包
68+
https://github.com/alibaba/nacos/releases
69+
70+
//解压
71+
unzip nacos-server-$version.zip
72+
cd nacos/bin
73+
74+
//启动
75+
sh startup.sh -m standalone
76+
```
77+
78+
#### 2.测试注册中心和配置中心
79+
```json
80+
//服务注册
81+
curl -X POST 'http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=nacos.naming.serviceName&ip=20.18.7.10&port=8080'
82+
83+
//服务发现
84+
curl -X GET 'http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=nacos.naming.serviceName'
85+
86+
//发布配置
87+
curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=HelloWorld"
88+
89+
//获取配置
90+
curl -X GET "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test"
91+
```
92+
93+
#### 3.登录Nacos-Server控制台
94+
<img src="https://ipman-blog-1304583208.cos.ap-nanjing.myqcloud.com/dubbo/1651608729573_.pic.jpg" width = "620" height = "340" alt="图片名称" align=center />
95+
96+
```json
97+
//访问
98+
http://127.0.0.1:8848/nacos
99+
100+
//用户名&密码
101+
nacos
102+
nacos
103+
```
104+
105+
### Springboot集成Nacos为配置中心
106+
#### 1.添加Nacos依赖
107+
```json
108+
<dependency>
109+
<groupId>com.alibaba.boot</groupId>
110+
<artifactId>nacos-config-spring-boot-starter</artifactId>
111+
<version>0.2.1</version>
112+
</dependency>
113+
```
114+
115+
#### 2.配置application.properties
116+
```json
117+
server.port=8080
118+
nacos.config.server-addr=10.211.55.6:8848
119+
```
120+
121+
#### 3.通过@NacosPropertySource 加载 dataId 并设置注册中心,通过 Nacos 的 @NacosValue 注解设置属性值
122+
```json
123+
@Controller
124+
@RequestMapping("config")
125+
//使用 @NacosPropertySource 加载 dataId 为 example 的配置源,并开启自动更新
126+
@NacosPropertySource(dataId = "nacos.cfg.test", autoRefreshed = true)
127+
public class NacosController {
128+
129+
//通过 Nacos 的 @NacosValue 注解设置属性值
130+
@NacosValue(value = "${nacos.test.propertie:null}", autoRefreshed = true)
131+
private String testProperties;
132+
133+
@RequestMapping(value = "/get", method = RequestMethod.GET)
134+
@ResponseBody
135+
public String get() {
136+
return testProperties;
137+
}
138+
}
139+
```
140+
141+
#### 4.在Nacos控制台设置dataId,并发布配置文件
142+
<img src="https://ipman-blog-1304583208.cos.ap-nanjing.myqcloud.com/dubbo/1071608735439_.pic_hd.jpg" width = "720" height = "340" alt="图片名称" align=center />
143+
144+
#### 5.启动SpringBoot项目,通过接口进行测试
145+
```json
146+
curl -i -l http://127.0.0.1:8080/config/get
147+
```
148+
#### 6.在Nacos控制台修改配置,并完成配置推送,再次执行步骤5查看更改后效果
149+

0 commit comments

Comments
 (0)