前言:
这一专栏是应用专栏,对于原理性的不过多赘述,源码的部分小编也会逐渐更新,敬请期待。
一.Nacos介绍
Nacos /nɑ:kəʊs/
是 Dynamic Naming and Configuration Service的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。
二.什么是Nacos
服务(Service)是 Nacos 世界的一等公民。Nacos是注册中心和配置中心。为了让大家更好的理解,我们举一个例子:注册中心就像是酒店的前台一样,如果酒店是没有前台的,那么客人来住店之后就需要自己去找那个房间能去住,最直接的方式就是去按着顺序去看知道找到没有人的房间在入住,Nacos在微服务下,我们将提供远程服务的成为服务提供者,请求服务的成为服务消费者,而消费者在查找符合自己的需要的提供者的过程就像时客户自己去找房间,但是讲过nacos的注册中心,就能加快速度。接下来我们画图解释一下。
三.创建服务提供者。
spring-cloud-alibaba和spring-cloud的版本号是:
<spring-cloud-alibaba-version>2021.1</spring-cloud-alibaba-version>
<spring-cloud.version>2020.0.1</spring-cloud.version>
3.1:依赖注入
Maven依赖:这就是Nacos注册中心的依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
3.2:配置Nacos注册中心配置文件
在application中配置Nacos注册中心
server:
port: 9001
spring:
application:
name: nacos-provider
cloud:
discovery:
server-addr: 127.0.0.1:8848
management:
endpoint:
web:
exposure:
include:'*'
spring: application: name: nacos-provider
这个配置项指定了Spring应用程序的名称为nacos-provider
。在微服务架构中,这个名称用于在Nacos注册中心注册服务,以便其他服务可以发现和调用它
server.post:为了防止端口占用,尽量不要使用8080.
cloud.discovery.server-addr:127.0.0.1:8848 :这个配置项指定了Nacos服务发现的服务器地址和端口。127.0.0.1:8848
表示Nacos服务运行在本地机器的8848端口上。这个配置项用于让Spring Cloud应用程序能够通过Nacos进行服务发现和注册。
management: endpoint: web: exposure: include:'*'
这个配置项指定了Spring Boot Actuator的所有端点(endpoints)都将通过Web API暴露出来。include:'*'
表示所有端点都被启用,包括但不限于/health
、/info
、/beans
等。这个配置项通常用于开发和测试环境中,以便开发者可以方便地监控和管理应用程序。
3.3:在启动类添加注解@EnableDiscoveryClient
@EnableDiscoveryClient
/**
* 为什么要添加这个注解呢
*/
@SpringBootApplication
public class NacosProvoder9001Application {
public static void main(String[] args) {
SpringApplication.run(NacosProvoder9001Application.class, args);
}
}
3.3.1为什么添加注解呢:
@EnableDiscoveryClient
注解的主要作用是启用服务注册与发现功能。使得微服务能够自动注册到服务注册中心,并能够发现和调用其他服务,就像酒店前台帮助客人预订房间一样。
3.4添加服务接口:
@RestController
public class UserController {
@GetMapping("/hdk")
public String getHdk(){
System.out.println("----------------9001 is run ------------");
return "----------------run 9001 ------------------"+"\n"
+"----------------run 9001 ------------------"+"\n"
+ "----------------run 9001 ------------------"+"\n";
}
}
这是服务的提供者,我们别的消费者就是去消费这个提供者的服务,而这个类就是接口。
四.创建服务消费者实现服务调用
4.1创建消费者的服务
创建项目导入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</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>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
4.2添加配置文件:
在添加配置文件时我们要清楚,还是要将消费者的服务注册,在消费,所以配置文件还是和注册时的配置文件相同,
server:
port: 9001
spring:
application:
name: nacos-consumer
cloud:
discovery:
server-addr: 127.0.0.1:8848
management:
endpoint:
web:
exposure:
include:'*'
在消费是我们可以采取两种方式,分别是RestTemplate和OpenFeign的方式,但是我们还是较为多的使用OpenFegin的方式
4.3RestTeplate实现服务调用
使用RestTemplate方式实现服务调用需要导入依赖,达到负载平衡
<!-- 负载平衡--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency>
然后需要配置RestTemplate
来实现远程调用
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
编写接口代码:
@RestController
public class UserController {
@Autowired
private RestTemplate restTemplate;
/**
* 消费者去访问具体服务,这种写法可以实现
* 配置文件和代码的分离
*/
@Value("${service-url.nacos-user-service}")
private String serverURL;
@GetMapping(value = "consumer/nacos")
public String getDiscovery(){
System.err.println(serverURL);
return restTemplate.getForObject(serverURL+"/hdk",String.class);
}
}
配置文件中添加信息,提供URL:
service-url: nacos-user-service: http://nacos-provider#这个路线就是我们在注册服务提供者的路线,同过注册中心找到服务的提供者之后,在调用服务提供者的服务。
4.4OpenFegin的方式实现
导入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</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>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
创建OpenFegin接口文件:
@FeignClient("nacos-provider")
public interface NacosOpenFeignService {
@GetMapping("/hdk")
public String getHdk();
}
在启动类种添加注解
@EnableFeignClients(basePackages = "com.hdk.nacosconsumer9102.config")指明接口文件的位置
调用服务
@RestController
public class UserConsumer {
@Autowired
private NacosOpenFeignService nacosOpenFeignService;
@GetMapping("/user/consumer")
public String getHdk(){
return nacosOpenFeignService.getHdk();
}
}
五.CAP模型
5.1概念:
- 一致性(Consistency) :指在分布式系统中,所有节点的数据保持一致。例如,当一个节点更新数据时,其他所有节点也必须立即看到这个更新。
- 可用性(Availability) :指系统在任何情况下都能响应用户的请求,并返回结果。即使在部分系统组件出现故障的情况下,系统仍然能够继续提供服务。
- 分区容忍性(Partition Tolerance) :指系统能够在网络分区的情况下继续运行。网络分区是指网络连接中断,导致部分节点无法与其它节点通信的情况。
根据微服务的概念和CAP模型概念,我们发现分区容忍性事微服务的核心,但是一致性和可用性确是相互违反的,所以,我们的我们在分区容错性的原则下选择一致性或者是可用性,这就是CP/AP
5.2CP原则:
CP 原则属于强一致性原则,要求所有节点可以查询的数据随时都要保持一直(同步中的数据不可查询),即:若干个节点形成一个逻辑的共享区域,某一个节点更新的数据都会立即同步到其他数据节点之中,当数据同步完成后才能返回成功的结果,但是在实际的运行过程中网络故障在所难免,如果此时若干个服务节点之间无法通讯时就会出现错误,从而牺牲了以可用性原则(A),例如关系型数据库中的事务。
5.3AP原则
AP原则属于弱一致性原则,在集群中只要有存活的节点那么所发送来的所有请求都可以得到正确的响应,在进行数据同步处理操作中即便某些节点没有成功的实现数据同步也返回成功,这样就牺牲一致性原则(C 原则)。
使用场景:对于数据的同步一定会发出指令,但是最终的节点是否真的实现了同步,并不保证,可是却可以及时的得到数据更新成功的响应,可以应用在网络环境不是很好的场景中。
Nacos提供了两种模式的转换。但是默认是AP
六.配置中心
6.1:什么是配置中心:
-
集中管理配置:Nacos配置中心可以将应用程序的配置从代码和本地配置文件中分离出来,实现配置的集中管理和动态更新。这意味着开发者可以将所有配置信息存储在Nacos服务器上,而不是分散在各个服务实例中。
-
动态刷新配置:Nacos支持配置的动态刷新,即当配置发生变化时,服务端会自动通知客户端进行配置更新,无需重启服务。这使得配置变更更加灵活和高效
例子讲解:集中管理就是如果现在班级六十人,但是今天因为天气不好,学校决定停课一天,老师只是要在班级大群里面说一下就行,而不是需要每个人都通知一遍
6.2:结合配置中心讲解bootstrap.yml
注意在SpringBoot2.4之后需要显示的添加如下的依赖。bootstrap.yaml 才会生效
<!-- SpringBoot2.4之后要让 bootstrap.yaml 文件生效我们需要添加该依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
对比一下 bootstrap.yml和application.yml
- bootstrap.yml配置文件的优先级大于application.yml.
- bootstrap.yml:是配值系统级别的,application.yml:是配置应用级别的。例如假设我们使用配置中心,那么配置中心的配置信息就需要放置在bootstrap.yml配置文件中,其实道理很简单。如果我们当前的服务需要配置中心里面的配置,但是配置中心还没有,那这个配置就无法拉取了。
- bootstrap.yml:通常在应用程序启动时首先加载,用于配置Spring Cloud Config服务器的连接信息、应用程序名称和profile等。
-
application.yml:在
bootstrap.yml
之后加载,用于配置应用级别的参数,如数据库连接、服务器端口等。
其实大家可以将他们两者想象为父类子类的关系。在写项目的时候将微服务的组建的配置写在 bootstrap.yml里面,自己的服务需要的写在application里面。下面的代码为大家展示
6.3:Nacos的配置规则
在 Nacos Spring Cloud 中,dataId
的完整格式如下(详情可以参考官网 Nacos Spring Cloud 快速开始):
${prefix}-${spring.profiles.active}.${file-extension}
prefix
默认为spring.application.name
的值,也可以通过配置项spring.cloud.nacos.config.prefix
来配置。
spring.profiles.active
即为当前环境对应的 profile,注意:当spring.profiles.active
为空时,对应的连接符-
也将不存在,dataId 的拼接格式变成${prefix}.${file-extension}
(不能删除)
file-exetension
为配置内容的数据格式,可以通过配置项spring.cloud.nacos.config.file-extension
来配置。目前只支持properties
和yaml
类型。通过 Spring Cloud 原生注解
@RefreshScope
实现配置自动更新:所以根据官方给出的规则我们最终需要在Nacos配置中心添加的配置文件的名字规则和名字为:
${spring.application.name}-${spring.profiles.active}.${file-extension}
nacos-config-client-dev.yaml
6.4:创建配置,展示拉取配置。体现配置中心功能
创建配值文件bootstrap
server: port: 7777 spring: application: name: nacos-config cloud: nacos: discovery: server-addr: localhost:8848 config: server-addr: localhost:8848 file-extension: yaml
file-extension: yaml:指明配置中心中的配置文件的类型是ymal
spring: profiles: active: dev #根据当前环境匹配属于自己的配置文件${prefix}-${spring.profiles.active}.${file-extension}
注解@RefreshScope的作用
注解 @RefreshScope
的作用是实现配置和实例的热加载。具体来说,当使用 @RefreshScope
注解修饰的 Bean 时,Spring Cloud 会对其进行代理,使得在配置变更时,可以在不重启应用的前提下刷新 Bean 中相关的属性值。这样,开发者可以在不停止应用程序的情况下修改配置,从而使应用程序更加灵活和可配置。
6.5:DataID,Group&nameSpace:
DataID
在实际的开发中我们需要面对各种不同的环境。比如开发环境。测试环境和生产环境。不同的环境下我们的配置信息是有差异的。这时我们就可以通过spring.profile.active
来指定不同的环境来对应不同的配置文件。
比如我们上面的案例是dev
开发环境。那么对应的配置文件的名称就是nacos-config-client-dev.yaml
.然后我们把对应的环境切换到test
测试环境。那么对应的配置文件的名称就是nacos-config-client-test.yaml
.然后我们在nacos中创建该配置文件
Group
上面我们通过DataID来配置我们的配置信息。这种场景是把项目中的所有信息都配置在了一个配置文件中。这个会造成配置信息非常多。不便于管理这时我们可以根据配置信息的类别通过Group
来对配置信息进行分组。我们可以把配置信息中的MyBatis
的和数据库
的相关配置信息都单独的区分出来。在创建配置文件的时候指定分组即可。我们前面创建的使用的是默认分组DEFAULT_GROUP
.
namespace
上面的group
方案可以基于配置信息的内容做划分。但是在实际的项目环境中。项目环境是比较复杂的。不同的项目不同的模块会有很多相似或者交叉的。这时我们可以通过namespace
来实现环境之间的隔离。