③ Nacos 【服务中心和配置中心】
2.1 Nacos 简介和安装
前四个字母分别为Naming和Configuration的前两个字母,最后的s为Service
Nacos是什么
专业术语:
一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
Nacos:Dynamic Naming and Configuration Service
简单的说:
Nacos就是 注册中心 + 配置中心的组合
Nacos = Eureka + Config + Bus
作用:能替代eureka做服务注册中心、能替代config做服务配置中心
官方文档: https://nacos.io/zh-cn/index.html
学习手册:https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html#_spring_cloud_alibaba_nacos_config
下载地址: Release 1.4.2 (Apr 29th, 2021) · alibaba/nacos (github.com)
各注册中心的对比
安装
- 先从官网下载Nacos
- 解压安装包,直接运行bin目录下的startup.cmd
- 如果启动失败就使用 startup.cmd -m standalone 命令启动, 因为默认启动是cluster模式,我们带参数改为单机版启动就行
- 运行成功后访问http://localhost:8848/nacos
- 登录页面的账号密码全为nacos
2.2 Nacos作为服务注册中心
2.2.1 基于Nacos的服务提供者
- 新建项目父项目springcloud_alibaba
- 导入父依赖
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.cvzhanshi</groupId>
<artifactId>springcloud_alibaba</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<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.18.12</lombok.version>
</properties>
<dependencyManagement>
<dependencies>
<!--springCloud的依赖-->
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud alibaba 2.2.1.RELEASE-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--SpringBoot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
<!--SpringBoot 启动器-->
<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<!--日志测试~-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</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>
</project>
- 新建模块springcloudalibaba-provider-payment9001服务提供者
- 导入依赖
<!--本pom.xml引入nacos-->
<dependencies>
<!--springcloud alibaba 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>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
- 编写配置文件application.yaml
server:
port: 9001
spring:
application:
name: nacos-payment-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848 #配置Nacos地址
management:
endpoints:
web:
exposure:
include: '*' #监控
- 主启动类
/**
* @author cVzhanshi
* @create 2021-07-01 15:15
*/
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain9001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain9001.class,args);
}
}
- 业务类
/**
* @author cVzhanshi
* @create 2021-07-01 15:16
*/
@RestController
public class PaymentController {
@Value("${server.port}")
private String serverPort;
@GetMapping("/payment/nacos/{id}")
public String getPayment(@PathVariable("id") Integer id){
return "nacos registry,serverPort: "+ serverPort+"\t id"+id;
}
}
- 运行nacos和9001模块
- 测试业务
- 添加模块9002和9001除了端口其他一样,为了测试负载均衡,启动9002后就发现一个服务下有两个实例
2.2.2 基于Nacos的服务消费者
- 新建服务消费者模块springcloud-consumer-nacos-order83,导入依赖
<dependencies>
<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>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
- 编写配置文件
server:
port: 83
spring:
application:
name: nacos-order-consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848
#消费者将要去访问的微服务名称(成功注册进nacos的微服务提供者),在这配置了访问的服务,业务类就不用在定义常量了
service-url:
nacos-user-service: http://nacos-payment-provider
- 主启动类
- 因为nacos自动集成了Ribbon,所以配置restTemplate
/**
* @author cVzhanshi
* @create 2021-07-01 16:37
*/
@Configuration
public class ApplicationContextConfig {
@Bean
@LoadBalanced//负载均衡
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
- 主启动类
/**
* @author cVzhanshi
* @create 2021-07-03 16:22
*/
@SpringBootApplication
public class OrderNacosMain83 {
public static void main(String[] args) {
SpringApplication.run(OrderNacosMain83.class,args);
}
}
- 业务类
/**
* @author cVzhanshi
* @create 2021-07-01 16:39
*/
@RestController
public class OrderNacosController {
/*
因为在yaml中配置了service-url.nacos-user-service,
这里不需要再定义要访问微服务名常量,而是通过boot直接读出来
*/
@Value("${service-url.nacos-user-service}")
private String serverURL;
@Resource
private RestTemplate restTemplate;
@GetMapping("/consumer/payment/nacos/{id}")
public String paymentInfo(@PathVariable("id") Long id){
return restTemplate.getForObject(serverURL+"/payment/nacos/"+id,String.class);
}
}
- 测试
发现一个消费者两个服务实例
2.2.3 服务注册中心的对比
Nacos 支持AP 和 CP模式的转换
C是所有节点在同一时间看到的数据是一致的;而A的定义是所有的请求都会受到响应。
何时选择使用何种模式?
一般来说,如果不需要存储服务级别的信息且服务实例是通过nacos-client注册,并能够保持心跳上报,那么就可以选择AP模式。当前主流的服务如SpringCloud和Dubbo服务,都适用与AP模式,AP模式为了服务的可能性而减弱了一致性,因此AP模式下只支持注册临时实例。
如果需要在服务级别编辑或存储配置信息,那么CP是必须,K8S服务和DNS服务则适用于CP模式。CP模式下则支持注册持久化实例,此时则是以Raft协议为集群运行模式,该模式下注册实例之前必须先注册服务,如果服务不出存在,则会返回错误。
用下面命令切换
curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP
2.3 Nacos作为服务配置中心
2.3.1 基础配置
- 新建模块springcloudalibaba-config-nacos-client3377,导入依赖
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<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>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
- 编写配置文件 bootstrap.yaml 和 application.yaml
bootstrap.yaml
#bootstrap.xml
server:
port: 3377
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
config:
server-addr: localhost:8848 #Nacos作为配置中心地址
file-extension: yaml #指定yaml格式的配置
# ${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file.extension}
# nacos-config-client-dev.yaml
application.yaml
#application.yml
spring:
profiles:
active: dev #开发环境
- 主启动类
/**
* @author cVzhanshi
* @create 2021-07-03 16:52
*/
@SpringBootApplication
@EnableDiscoveryClient
public class NacosConfigClientMain3377 {
public static void main(String[] args) {
SpringApplication.run(NacosConfigClientMain3377.class,args);
}
}
- 在Nacos中添加配置信息
Nacos中的匹配规则
p r e f i x − {prefix}- prefix−{spring.profiles.active}.${file-extension}
默认为
prefix
的值,也可以通过配置项
spring.application.name
来配置。
spring.cloud.nacos.config.prefix
即为当前环境对应的 profile。 注意:当
spring.profiles.active
为空时,对应的连接符
spring.profiles.active
也将不存在,dataId 的拼接格式变成
-
${prefix}.${file-extension}
为配置内容的数据格式,可以通过配置项
file-exetension
来配置。目前只支持
spring.cloud.nacos.config.file-extension
和
properties
类型。
yaml
- 运行测试 ,访问 http://localhost:3377/config/info
- 修改nacos中的配置,客户端不重新启动,测试实时更新
2.3.2 分类配置
问题1:
实际开发中,通常一个系统会准备dev开发环境、test测试环境、prod生产环境,如何保证指定环境启动时服务能正确读取到Nacos上相应环境的配置文件呢?
问题2:
一个大型分布式微服务系统会有很多微服务子项目,每个微服务项目又会有相应的开发环境、测试环境、预发环境、正式环境…那怎么对这些微服务配置进行管理呢?
Namespace + Group + Data ID三者关系 :
类似Java中的package名和类名
最外层的namespace是可以用于区分部署环境的,Group和DataID逻辑上区分两个目标对象
默认情况:
Namespace=public,Group=DEFAULT_GROUP,默认Cluster是DEFAULT
Nacos默认的命名空间是public,Namespace主要用来实现隔离
比方说我们现在有三个环境:开发、测试、生产环境,我们就可以创建三个Namespace,不同的Namespace之间是隔离的。
Group默认是DEFAULT_GROUP,Group可以把不同的微服务划分到同一个分组里面去
Service就是微服务,一个Service可以包含多个Cluster(集群),Nacos默认Cluster是DEFAULT,Cluster是对指定微服务的一个虚拟划分
比方说为了容灾,将Service微服务分别部署在了杭州机房和广州机房,这时就可以给杭州机房的Service微服务起一个集群名称(HZ)给广州机房的Service微服务起一个集群名称(GZ),还可以尽量让同一个机房的微服务互相调用,以提升性能。
最后是Instance,就是微服务的实例。
三种方案加载配置
- DataID方案配置:指定spring.profile.active和配置文件的DataID来使不同环境下读取不同的配置
- 默认空间 + 默认分组 + 新建dev和test两个DataID
- 通过spring.profile.active属性就能进行多环境下配置文件的读取
- Group方案:通过Group实现环境区分
- 创建两个分组
- bootstrap 和 application配置修改
bootstrap
#bootstrap.yaml
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
config:
server-addr: localhost:8848 #Nacos作为配置中心地址
file-extension: yaml #指定yaml格式的配置
group: DEV_GROUP
application
#application.yml
spring:
profiles:
active: info #开发环境
- 测试
- 修改分组,再测试
- Namespace方案:
- 新建命名空间
- 在新建的命名空间中创建配置文件
- 修改配置文件
bootstrap.yaml
#bootstrap.xml
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
config:
server-addr: localhost:8848 #Nacos作为配置中心地址
file-extension: yaml #指定yaml格式的配置
group: TEST_GROUP
namespace: d5105f8e-f24f-4cd8-a6a4-b3c88bdd824e
application.yaml
#application.yml
spring:
profiles:
active: dev #开发环境
- 测试
由此我们可以通过配置文件中的namespace、group、active来选择要读取的nacos中的配置文件
2.4 Nacos 集群和持久化
2.4.1 集群和持久化的简介
自己准备搭建集群的结构图
默认Nacos使用嵌入式数据库(derby)实现数据的存储。所以,如果启动多个默认配置下的Nacos节点,数据存储是存在一致性问题的。
为了解决这个问题,Nacos采用了集中式存储的方式来支持集群化部署,目前只支持Mysql的存储
Nacos支持三种部署模式
https://nacos.io/zh-cn/docs/deployment.html
- 单机模式:用于测试和单机试用
- 集群模式:用于生产环境,确保高可用
- 多集群模式:用于多数据中心场景
2.4.2 持久化
Nacos默认自带的是嵌入式数据库derby
derby到mysql切换配置步骤:
- nacos-server-1.1.4\nacos\conf 目录下执行sql脚本
nacos-mysql.sql
- nacos-server-1.1.4\nacos\conf 目录下找到
,添加配置:application.properties
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=xxx
db.password=xxx
2.4.3 Linux搭建Nacos集群
Linux安装nacos
- 在官网上下载好安装包,上传到linux上
- 解压安装包
tar -zxvf nacos-server-1.1.4.tar.gz
- 把解压出来的文件夹复制到/mynacos文件夹中(个人习惯,不动源文件)
- 进入/mynacos/nacos/bin目录中,备份启动文件
重点:集群的配置
- Linux服务器上MySQL数据库配置
在服务器的mysql,新建数据库nacos_config,如何在nacos解压文件的conf下有sql脚本nacos-mysql.sql,执行即可
- application.properties的配置
先备份application.propertiesvim这个文件,添加以下内容cp application.properties application.properties.bf
spring.datasource.platform=mysql db.num=1 db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true db.user=root db.password.0=123456
- Linux服务器上nacos的集群配置cluster. conf
老套路,先备份文件内容修改如下,其中文件中的ip是hostname -i 能识别的ipcp cluster.conf.example cluster.conf
192.168.242.110:3333 192.168.242.110:4444 192.168.242.110:5555
- 编辑Nacos的启动脚本startup.sh,使它能够接受不同的启动端口
修改内容如下
- Nginx的配置,由它作为负载均衡器
修改内容如下,路径用whereis nginx查看,其中的conf/nginx.conf
测试
- 先启动3个nacaos
查询有三个nacos启动成功
- 启动nginx
./nginx -c /usr/local/nginx/conf/nginx.conf
- 浏览器访问nacos
- 登录进去新建一个配置然后查询数据库看看是否有记录添加
- 项目中配置nacos,看看项目服务能不能注册进入nacos集群中
集群搭建完成