一、Nacos简介
Nacos(Naming和Configuration的前2个字母,s为Service),一个更易于构建云原生应用的动态服务发现、配置管理和服务管理的平台。
注册中心+配置中心的组合。
Nacos = Eureka + Config + Bus。
《Nacos 英文文档》
《Nacos 中文文档》
二、Nacos的下载、安装和使用
本次使用的环境为:nacos-server-1.2.1、windows、jdk1.8。
《nacos-server-1.2.1下载地址(含windows和linux)》
下载、解压之后,启动 \nacos-server-1.2.1\bin 下的 startup.cmd 即可启动。
访问 http://localhost:8848/nacos ,账号密码均为 nacos。
如果不想使用 8848 端口或者不想使用 /nacos ,可以在 conf/application.properties 中进行配置或修改。
三、Nacos做服务注册中心的配置相关
本次采取Maven特有的父子项目模式实现开发,方便代码的汇总和管理。
针对不知道如何创建父子工程的,可以参考以下博客:
《使用eclipse搭建maven多module项目(构建父子项目)》
如果大家使用的是idea,可以参考以下博客:
《idea配置maven环境》
《idea创建多级Springboot父子工程》
3.1、父工程的创建
父工程作为一种公用依赖的汇总和管理,只需要配置好共有的pom即可。
<artifactId>Spring-Cloud-Alibaba-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>cloudalibaba-Consumer-9001</module>
<module>cloudalibaba-Product-9102</module>
</modules>
<properties>
<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>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
<lombok.version>1.16.18</lombok.version>
<druid.version>1.1.16</druid.version>
<druid.spring.boot.starter.version>1.1.10</druid.spring.boot.starter.version>
<spring.boot.version>2.2.2.RELEASE</spring.boot.version>
<spring.cloud.version>Hoxton.SR1</spring.cloud.version>
<spring.cloud.alibaba.version>2.1.0.RELEASE</spring.cloud.alibaba.version>
</properties>
<!-- 子模块继承之后,提供作用:锁定版本 + 子module不用谢groupId和version -->
<dependencyManagement>
<dependencies>
<!--spring boot 2.2.2 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud Hoxton.SR1 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--Spring cloud alibaba 2.1.0.RELEASE -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
<!--第三方maven私服 -->
<repositories>
<repository>
<id>nexus-aliyun</id>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
3.2、消费者子服务
由于大部分的主要依赖信息父项目中均有引入,此处只需要进行单个额外的依赖引入即可。
依赖引入:
<parent>
<groupId>cn.linkpower</groupId>
<artifactId>Spring-Cloud-Alibaba-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<name>cloudalibaba-Consumer-9001</name>
<!-- <groupId>com.eiletxie.springcloud</groupId> <version>0.0.1-SNAPSHOT</version> -->
<artifactId>cloudalibaba-Consumer-9001</artifactId>
<url>http://maven.apache.org</url>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<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>
</dependencies>
编写配置文件信息,指向 Nacos 的注册中心。
## 该服务的端口信息
server:
port: 9001
## 服务别名和nacos服务注册发现地址配置
spring:
application:
name: nacos-consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848
## 监控相关
management.endpoints.web.exposure.include: '*'
创建启动类,添加相关注解信息。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient //使用此注解
public class Application9001 {
public static void main(String[] args) {
SpringApplication.run(Application9001.class, args);
}
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
增加测试类,实现可请求测试。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class TestController {
@Value("${server.port}")
private String port;
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/consumer/nacos/{id}")
public String getPayMent(@PathVariable("id") String id) {
//return "nacos registry,server port:"+port+" \t id:"+id;
//拉取服务信息
String reqUrl = "http://nacos-product/product/getProduct/"+id;
String result = restTemplate.getForObject(reqUrl, String.class);
return result;
}
}
3.3、生产者子服务的创建
引入依赖信息同消费者子服务。
配置文件的编写:
## 该服务的端口信息
server:
port: 9102
## 服务别名和nacos服务注册发现地址配置
spring:
application:
name: nacos-product
cloud:
nacos:
discovery:
server-addr: localhost:8848
## 监控相关
management.endpoints.web.exposure.include: '*'
启动类的编写:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class Application9102 {
public static void main(String[] args) {
SpringApplication.run(Application9102.class, args);
}
}
测试响应接口的编写:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@Value("${server.port}")
private String port;
@RequestMapping("/product/getProduct/{id}")
public String getOrder(@PathVariable("id") String id) {
return "this is product services,port:"+port+"\t id="+id;
}
}
3.4、测试
- 启动nacos本地服务
http://localhost:8848/nacos
账号、密码:nacos - 启动生产者和消费者子服务
- 观察和请求测试
分别启动好nacos和子微服务后,再web界面中显示如下,表示启动注册成功。
变更生产者的服务port信息,再启动一个新的服务,9101。
访问连接进行测试操作:
http://localhost:9001/consumer/nacos/11
spring-cloud-starter-alibaba-nacos-discovery 自带负载均衡。
四、Nacos支持AP和CP的切换
之前谈到过 CAP 理论。
名称 | 英语名 | 含义 |
---|---|---|
高可用性(A) | Availability | 当出现高负载、网络波动情况下,保证服务能及时相应请求。 |
一致性(C) | Consistency | 在分布式系统中,所有节点在同一时间内,必须保证数据完全一致,节点越多,需要同步数据耗时越多 |
分区容错性(P) | Partition tolerance | 相同服务集群部署后,其中一个宕机,整个系统不会受到影响。 |
以及 CAP不能共同存在的说明:
组合 | 含义 | 描述 |
---|---|---|
AP | 高可用、 分区容错 | 为了满足分区容错,则需要某个服务尽量多的集群部署(P); 为了能够及时响应就必须减少数据处理中的耗时时间(A); 数据同步需要时间,机器越多(P),时间越长;时间越长,就越不能满足及时响应请求(A) |
CP | 数据一致性、 分区容错 | 为了满足分区容错,则需要某个服务尽量多的集群部署(P); 机器数目多了,数据一致性(C)就越耗时; 相对能及时响应请求就越难,所以很难保证高可用性(A) |
AC | 高可用性、 数据一致性 | 为了达到高可用,则必须要求及时处理请求,及时响应请求; 为了保持数据一致性,则需要每个机器中某个时刻数据保持一致; 一致性是耗时的操作,高可用又要保证及时响应,机器多了同步数据需要更多的时间,所以需要机器越少才能满足 |
但是,Nacos 本身是支持AP和CP模式的切换的。切换方式如下所示(暂未测试)
curl -X PUT ‘$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP’
五、Nacos做服务配置中心的配置
以前采取全局配置刷新使用的是Config类组件来实现,通过在github(git系列)、文本系列等,刷新已经运行在内存中的项目配置信息。
Nacos 默认整合了Config 的配置相关方式,只需要在Nacos中做配置即可实现刷新操作。
本小节参见文章:《nacos 配置中心官方文档》
5.1、Nacos作为配置中心的基础配置
新建一个微服务,命名为cloudalibaba-config-nacos-client8000
。
由于此处采取的方式为Maven的父子项目工程方式,所以创建项目规则已maven父子项目为准。
依赖信息引入:
<parent>
<artifactId>SpringCloud-Alibaba-Demo</artifactId>
<groupId>cn.linkpower</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>cloudalibaba-config-nacos-client8000</artifactId>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- SpringCloud alibaba nacos config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<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>
</dependencies>
配置文件的编写:
在Springcloud config配置中,由于Springcloud Alibaba需要保证对原生SpringCloud的兼容,依旧采取Springboot默认的优先级规则:
bootstrap.yml 优先级 高于 application.yml。
bootstrap.yml
server:
port: 8000
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址,注册至nacos注册中心上
config:
server-addr: localhost:8848 #Nacos作为配置中心地址
file-extension: yaml #指定yaml格式配置
# prefix: nacosconfigclient ## 当不想使用 spring.application.name 作为文件名时,可以采取此项配置
# group: xiangjiao 配置nacos中的配置文件的分组
application.yml:
## bootstrap的优先级高于application
## 配置开发环境
#spring:
#profiles:
#active: dev #表示开发环境
启动类的编写:
需要将该配置中心注册至注册中心上,同时Nacos自带有配置中心的操作。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class ApplicationConfigClient8000 {
public static void main(String[] args) {
SpringApplication.run(ApplicationConfigClient8000.class,args);
}
}
编写一个测试接口:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RefreshScope //必须标注此注解,才能达到刷新的目的
public class TestController {
//配置文件中不存在,需要从nacos注册中心管理网站上进行获取
@Value("${config.info}")
private String configInfo;
@RequestMapping("/config/getConfigInfo")
public String getConfigInfo() {
return configInfo;
}
}
注意:
并不是说配置完成后,就能直接进行项目的启动操作!!
如果配置完成,未增加配置项时,启动会出现如下报错信息:
5.2、界面操作的细节
可以采取新建的方式,实现创建一个修改后的文件类型
其中,对于 Data ID ,Nacos SpringCloud有专门的命名规范。
${prefix} - ${spring.profile.active}. ${file-extension}
名称 | 描述 |
---|---|
prefix | 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix来配置。 |
spring.profile.active | 即为当前环境对应的 profile,详情可以参考 Spring Boot文档。 注意:当 spring.profile.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 ${ prefix }. ${ file-extension} |
file-exetension | 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 properties 和 yaml 类型。 |
按照 5.1 中的定义规范。
由于没有配置 ${spring.profile.active} 项,程序会默认读取 nacos-config-client.yaml 的配置文件。
在nacos web界面上,创建一个新的配置文件。
5.3、测试一
按照上述 5.1、5.2进行了配置项后,需要对配置的类做测试使用。
[注意:]此处有巨坑!yml和yaml的问题!
启动 nacos-config-client 微服务前,需要进行一项很关键的操作,不然项目启动直接会出现以下报错信息:
nacos 定义的yaml和yml不是一个概念!
准确说yml 和 yaml 两种后缀为同一种文件格式,但是nacos中存在小坑,此处需要注意!
我们修改nacos中的文件格式,保证和nacos-config-client中定义的一样!
再次启动 nacos-config-client 子微服务,观察到启动成功!,访问测试链接,可以获取到对应的结果信息。
http://localhost:8000/config/getConfigInfo
5.4、测试二
修改nacos中的指定文件后,再次刷新能否影响到已经运行的程序?
修改 nacos-config-client.yaml 中的文件信息。
再次刷新接口:
http://localhost:8000/config/getConfigInfo
自带自动刷新!很强大!!!
5.5、使用post请求新增/修改配置文件
除了在nacos中手动创建配置文件增加文件内容的方式外,还能使用 请求 的方式 新增/修改 配置文件。
新增文件
http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=xiangjiao-dev.yaml&group=DEFAULT_GROUP&content=user.name: xiangjiao
请求后,观察navos服务器的信息:
修改并发布刷新配置文件
原配置文件中的内容为:
采取请求的方式获取到的配置信息:
http://localhost:8000/config/getConfigInfo
使用请求,修改并发布修改项:
http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos-config-client.yaml&group=DEFAULT_GROUP&content=config:
info: bunana先生 88888
再次请求,获取nacos中配置中心指定文件的内容:
http://localhost:8000/config/getConfigInfo
5.6、配置文件分组式管理
实际开发生产环境下,存在多种多样的环境,如:测试环境、开发环境、上线环境等。
项目业务也多种多样,不同项目可能使用到相同的注册中心,这些细小的微服务如何达到分区管理?
在Nacos中,namespace默认为public,Group默认为DEFAULT_GROUP。
1、针对开发环境、测试环境、上线环境等,可以分配多个不同的namespace;每个namespace之间是隔离的。
2、Group 可以将不同的微服务划分到不同的组中。
3、Service 就是微服务,一种微服务可以包括多个集群,就像分布式微服务中做多个集群部署等。
- GROUP 分组
设置配置文件中的group属性值,将文件进行不同的分组操作,但两种文件均在同一个namespace下。
修改 nacos-config-client 项目中的配置信息
启动项目,并进行请求测试
http://localhost:8000/config/getConfigInfo
- NameSpace
当创建完成命名空间后,会自动生成一项随机、唯一的标识字符串。
然后,切换test命名空间,创建一个配置文件信息。
修改 nacos-config-client 项目中的配置文件信息。
重启项目,请求测试:
http://localhost:8000/config/getConfigInfo