SpringCloud之Nacos
Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。[Se
SpringCloud之Nacos
一、微服务介绍
1. 什么是微服务
2014年,Martin Fowler(马丁·福勒 ) 提出了微服务的概念,定义了微服务是由以单一应用程序构成的小服务,自己拥有自己的进程与轻量化处理,服务依业务功能设计,以全自动的方式部署,与其他服务使用 HTTP API 通信。同时服务会使用最小的规模的集中管理能力,服务可以用不同的编程语言与数据库等组件实现。
马丁·福勒是敏捷联盟的成员,于2001年,同其他16名合著者一起协助创作了“敏捷软件开发宣言”。他负责维护一个bliki网站—一种blog和wiki的混合衍生物,他还使控制反转(Inversion of Control)“依赖注入模式(Dependency Injection)”一词得到普及。
2.架构的演变
随着互联网的发展,网站应用的规模也不断的扩大,进而导致系统架构也在不断的进行变化,从互联网早起到现在,系统架构大体经历了下面几个过程:
- 单体应用架构
把所有功能都集中在一个应用中,统一部署,开发成本、部署成本和维护成本低
- 优点:项目架构简单,适合用户量少的项目,开发成本低,项目部署在一个节点上,维护方便。
- 缺点:功能集中在一个工程中,对于大型项目比一开发和维护,项目模块紧耦合,单点容错率低,无法对不同的模块功能进行针对性的优化和水平拓展
- 垂直应用架构
所谓垂直应用架构,其实就是把之前的单体应用拆分成多个应用,以提升效率,比如电商系统可以拆分成:电商系统、后台系统、CMS系统
- 优点:项目拆分实现了流量分担,解决了并发问题,而且可以针对不同模块进行优化和水平拓展,同时不同的系统之间不会互相影响,提高容错率
- 缺点:系统之间互相存在,无法进行相互调用,系统之间互相独立,会造成一部分功能的冗余
- 分布式架构
随着业务的增加,在垂直应用架构中冗余的业务代码越来越多,就需要将冗余的部分抽取出来,统一做成业务层单独处理,变成一个单独的服务,控制层调用不同的业务层服务就能完成不同的业务功能,具体表现就是一个项目拆分成表现层和服务层两个部分,服务层中包含业务逻辑,表现层只需要处理和页面的交互,业务逻辑都是调用服务层的服务来实现,这就是分布式架构。
- 优点:抽取公共的功能作为服务层,提高代码复用行。
- 缺点:系统间耦合度变高,调用关系错综复杂,难以维护。
- SOA架构
分布式架构中的缺点就是调用复杂,而且当服务越来越多,或者当某一个服务压力过大需要水平拓展和负载均衡,对于资源调度和治理就需要用到治理中心SOA(Service Oriented Architecture)为核心来解决,同时治理中心还可以帮助我们解决服务之间协议不同的问题。
- 优点:使用治理中心(ESB\dubbo)解决了服务见调用关系的自动调节
- 缺点:服务间会有依赖关系,一旦某个环节出错会影响较大(服务雪崩),服务关系复杂,运维、测试部署困难。
- 微服务架构
微服务架构在某种程度上面架构SOA继续发展的下一步,它更加强调服务的“彻底拆分”,目的就是提高效率,微服务架构中,每个服务必须独立部署同时互不影响,微服务架构更加轻巧,轻量级。
微服务架构与SOA架构的不同
- 微服务架构比SOA架构会更加的精细,让专业的人去做专业的。
- 目的是提高效率每个服务之间互不影响,微服务架构中,每个服务需要独立部署
- SOA架构中可能数据库存储会发生共享,微服务强调每个服务都是单独数据库,保证每个服务之间互不影响。
- 微服务项目架构比SOA架构更加适合与互联网公司迅捷开发、快速迭代版本,因为粒度非常精细。
为何使用微服务呢?
微服务就像集群作战,可以提升性能
微服务架构:
- 优点:服务原子化拆分,独立打包、部署和升级,保证每个微服务清晰的任务划分,利于扩展
- 缺点:分布式系统开发的技术成本高(容错、分布式事务等),复杂性更高,每个微服务进行分布式独立部署,当进行模块调用的时候,分布式将会变得更加麻烦。
3.Spring Cloud 发展历史
Spring Cloud netflix -> Spring Cloud Alibaba
- 2020-12-22日Spring 官方博客宣布,
Spring Cloud 2020.0.0
正式发布。2020.0.0
是第一个使用新的版本号命名方案的Spring Cloud 发行版本。在此之前Spring Cloud 使用英国伦敦地铁站的命名方式来命名一个大版本(train version
),如果不按照新的版本号命名的话,本次的版本号应该是Ilford。 - 更新版本没有什么大惊小怪的,但是本次更新却正式开启了Spring Cloud Netflix 体系的终结进程。Netflix 公司是目前微服务落地中最成功的公司。它开源了诸如Eureka 、Hystrix 、Zuul 、Feign 、Ribbon 等等广大开发者所知微服务套件,统称为Netflix OSS 。在当时Netflix OSS 成为微服务组件上事实的标准。但是在2018年Netflix 公司宣布其核心组件Hystrix 、Ribbon 、Zuul 、Eureka 等进入维护状态 ,不再进行新特性开发,只修BUG。这直接影响了Spring Cloud 项目的发展路线,Spring 官方不得不采取了应对措施,在2019年的在 SpringOne 2019 大会中,Spring Cloud 宣布 Spring Cloud Netflix项目进入维护模式 ,并在2020年移除相关的Netflix OSS 组件。
- Spring Cloud Alibaba 成为了主流
4. Spring Cloud Alibaba
https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md
4.1 简介
Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。
依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。
4.2 主要功能
- 服务限流降级 :默认支持 WebServlet、WebFlux, OpenFeign、RestTemplate、Spring Cloud Gateway, Zuul, Dubbo 和 RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。
- 服务注册与发现 :适配 Spring Cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。
- 分布式配置管理 :支持分布式系统中的外部化配置,配置更改时自动刷新。
- 消息驱动能力 :基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。
- 分布式事务 :使用 @GlobalTransactional 注解, 高效并且对业务零侵入地解决分布式事务问题。
- 阿里云对象存储 :阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。
- 分布式任务调度 :提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有 Worker(schedulerx-client)上执行。
- 阿里云短信服务 :覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。
4.3 组件介绍
- [Sentinel] :阿里巴巴源产品,把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
- [Nacos] :一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
- [RocketMQ] :一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。
- [Dubbo] :Apache Dubbo™ 是一款高性能 Java RPC 框架。
- [Seata] :阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。
- [Alibaba Cloud OSS] : 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。
- [Alibaba Cloud SchedulerX]: 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。
- [Alibaba Cloud SMS] : 覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。
4.3 版本说明
https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E
课程中使用的版本
- SpringCloud:2020.0.1
- SpringCloudAlibaba:2021.1
- SpringBoot:2.4.2
- NacosServer:2.2.3
二、Nacos介绍
1. Nacos介绍
Nacos(Naming Configuration Service) 是一个易于使用的动态服务发现、配置和服务管理平台,用于构建云原生应用程序
服务发现是微服务架构中的关键组件之一。Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。
2. 什么是Nacos?
-
Nacos = 注册中心+配置中心组合
-
Nacos支持几乎所有主流类型的“服务”的发现、配置和管理,常见的服务如下:
Kubernetes Service
gRPC & Dubbo RPC Service
Spring Cloud RESTful Service
3. 为何使用Nacos?
为何使用注册中心呢?我们以入住酒店的前台为例子,稍微加以解释。先设想一个没有服务前台的酒店,客人入住需要自己寻找合适居住的房间,客人不知道每个房间的情况,无法确定那个房间是打扫干净可以入住,客人只能逐个房间寻找,如果遇到已经居住房客的房间一定很尴尬,显然这是不正常的情况。正常的情况是酒店会安排服务台,酒店打扫干净可以入住的房间会登记注册到服务台,这样客人来住店,只需要在前台就可以查找到可以入住的房间,这样就无需等待快速的入住。显然,服务器提供发注册和发现机制可以让房客快速找到合适的房间,快速解决入住问题。
采用微服务以后,软件微服务组件各自独立,但最终还要组合为一个整体作为一个软件系统服务于最终客户,这时软件组件之间也需要彼此通讯,彼此调用方法。微服务架构内部发起通讯调用方法的一方成为“服务消费者”,提供远程方法调用的服务器称为“服务提供者”,往往为了提高系统性能,会提供多个服务器作为服务提供者,此时服务消费者找到服务提供者的过程,就类似于用户在找房间的过程。为了帮助服务消费者快速的发现服务提供者,在微服务框架中都会引入注册中心。注册中心类似于酒店的前台,提供在软件服务的注册和发现功能,服务提供者会先在注册中心进行注册,声明可以对外提供服务,而服务消费者只需要在注册中心就可以快速发现找到可以使用的服务,快速使用服务。注册中心实现了服务提供和服务消费的快速撮合功能。
4. 下载和安装
官网网址:https://nacos.io/zh-cn/index.html
官网文档网址:https://nacos.io/zh-cn/docs/quick-start.html
注意:使用官网推荐的稳定版本:
下载地址:https://github.com/alibaba/nacos/releases
下载之后安装过程
-
解压以后找到bin目录
-
执行指令:
Linux/Unix/Mac
启动命令(standalone代表着单机模式运行,非集群模式):
sh startup.sh -m standalone
Windows
启动命令(standalone代表着单机模式运行,非集群模式):
startup.cmd -m standalone
-
结果:
-
得到结果以后为了验证是否成功开启Nacos,我们需要访问:http://localhost:8848/nacos
- 出现此界面表示已经成功启动Nacos,默认的账号密码是:nacos/nacos
- 到这里就是成功开启了Nacos服务了。
5.Nacos持久化配置
Nacos默认自带嵌入式数据库derby,所以我们每次创建一个Nacos实例就会有一个derby,当有多个Nacos节点的时候,就会出现一致性问题,所以Nacos支持了外部数据库统一数据管理MySql。
官网地址:https://nacos.io/zh-cn/docs/deployment.html
修改application.properties文件。把MySQL的配置放开
找到Nacos安装目录下的conf目录中的Sql脚本,然后在数据库中进行执行,先创建db-nacos的数据库
然后重启服务即可
三、注册中心
Nacos可以直接提供注册中心(Eureka)+配置中心(Config),所以它的好处显而易见,我们在前面成功安装和启动了Nacos以后就可以发现Nacos本身就是一个小平台,它要比之前的Eureka更加方便,不需要我们在自己做配置。
服务发现是微服务架构中的关键组件之一。在这样的架构中,手动为每个客户端配置服务列表可能是一项艰巨的任务,并且使得动态扩展极其困难。Nacos Discovery 帮助您自动将您的服务注册到 Nacos 服务器,Nacos 服务器会跟踪服务并动态刷新服务列表。此外,Nacos Discovery 将服务实例的一些元数据,如主机、端口、健康检查 URL、主页等注册到 Nacos。
学习任何知识我们都需要从它的官方文档入手,所以我们直接来看官网给我们提供的文档:https://spring.io/projects/spring-cloud-alibaba#learn
1.创建父项目
首先创建一个Maven的父项目。用来聚合管理。并声明了SpringCloud和SpringCloudAlibaba的版本
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<spring-cloud-alibaba-version>2021.1</spring-cloud-alibaba-version>
<spring-cloud.version>2020.0.1</spring-cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<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.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2.服务提供者
然后创建一个服务提供者的模块。父项目为上面创建的项目,同样是一个SpringBoot项目。pom.xml中的完整依赖信息如下:
<?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>
<groupId>com.boge</groupId>
<artifactId>NacosProviderExample9001</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>NacosProviderExample9001</name>
<parent>
<groupId>com.boge</groupId>
<artifactId>SpringCloudExample</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.4.2</spring-boot.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-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>com.boge.provider.AppProviderStart</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
然后在application.yml
中添加nacos的配置信息
server:
port: 9001
spring:
application:
name: nacos-provider
cloud:
discovery:
server-addr: 127.0.0.1:8848
management:
endpoint:
web:
exposure:
include:'*'
然后在启动类中添加@EnableDiscoveryClient
注解
@EnableDiscoveryClient
@SpringBootApplication
public class AppProviderStart {
public static void main(String[] args) {
SpringApplication.run(AppProviderStart.class, args);
}
}
然后添加提供的服务接口
@RestController
public class DemoController {
@Value("${server.port}")
private String serverPort;
@GetMapping(value = "/bobo")
public String getServerPort(){
return "Hello Nacos Discovery"+serverPort;
}
}
注意需要在父项目中标记:
<modules>
<module>NacosProviderExample9001</module>
</modules>
启动服务我们就可以在Nacos中服务列表中看到注册的服务信息
3.服务消费者
同样的我们再创建一个服务消费者的SpringBoot项目。并添加相关的依赖
<?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>
<groupId>com.boge</groupId>
<artifactId>NacosConsumerExample9101</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>NacosConsumerExample9101</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>com.boge</groupId>
<artifactId>SpringCloudExample</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.4.2</spring-boot.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-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>com.boge.consumer.AppConsumerStart</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
然后在属性文件中添加对应的配置信息
server:
port: 9101
spring:
application:
name: nacos-consumer
cloud:
discovery:
server-addr: localhost:8848
service-url:
nacos-user-service: http://nacos-provider
同样在父项目中记得添加关系
<modules>
<module>NacosProviderExample9001</module>
<module>NacosConsumerExample9101</module>
</modules>
在主启动类中一样添加对应的注解
@EnableDiscoveryClient
@SpringBootApplication
public class AppConsumerStart {
public static void main(String[] args) {
SpringApplication.run(AppConsumerStart.class, args);
}
}
启动消费服务后一样可以在Nacos服务列表中看到注册的服务信息
4.服务调用
上面我们创建了服务的提供者和服务的消费者。但是都只是完成了服务的nacos注册。并没有串联起来。在我们使用的SpringCloudAlibaba2021版本中移除了Ribbon
,因为Ribbon
已经停止更新维护了。使用loadBalancer
作用新的负载均衡器。我们需要添加新的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
然后需要配置RestTemplate
来实现远程调用
@EnableDiscoveryClient
@SpringBootApplication
public class AppConsumerStart {
public static void main(String[] args) {
SpringApplication.run(AppConsumerStart.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
然后在服务调用的接口中的获取RestTemplate对象。并完成相关的逻辑
@RestController
public class DemoController {
@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+"/bobo",String.class);
}
}
说明:getForObject方法的参数的含义
第一个参数url表示被调用的目标Rest接口位置
1. url的第一部分是在Nacos中注册的服务提供者名称,如果多个服务提供者注册相同名称,Ribbon会自动寻找其中一个服务提供者,并且调用接口方法。这个就是负载均衡功能。
2. url后半部是控制器的请求路径。
第二个参数是返回值类型
- JavaBean类型或者JavaBean数组类型,如果控制器返回的是List集合,需要使用数组类型接收。
第三个参数是可变参数
- 是传递给url的动态参数,使用参数时候需要在url上需要使用{1}、{2}、{3}进行参数占位,这样传递的参数就会自动替换占位符。
启动服务后访问测试:http://localhost:9101/consumer/nacos
看到上面的返回信息说明访问成功了。
5.OpenFeign服务调用
OpenFegin是一个声明式的服务调用组件。本质上是封装的Ribbon实现的。
然后添加相关的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
然后创建对应的Feign接口
@FeignClient(name = "nacos-provider")
public interface ProviderService {
@GetMapping(value = "/bobo")
public String getServerPort();
}
然后在启动类中添加@EnableFeignClients(basePackages = "com.boge.consumer.feign")
注解。指定我们存放Feign接口的位置
@EnableFeignClients(basePackages = "com.boge.consumer.feign")
@EnableDiscoveryClient
@SpringBootApplication
public class AppConsumerStart {
public static void main(String[] args) {
SpringApplication.run(AppConsumerStart.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
然后在controller中通过OpenFeign实现服务的远程调用
@RestController
public class DemoController {
@Autowired
private ProviderService providerService;
@GetMapping(value = "consumer/nacos2")
public String getDiscovery2(){
System.err.println("--->"+serverURL);
return restTemplate.getForObject(serverURL+"/bobo",String.class);
}
}
启动服务后访问测试:http://localhost:9101/consumer/nacos2
6.注册中心对比
服务注册与发现框架 | CAP模型 | 控制台管理 | 社区活跃度 |
---|---|---|---|
Eureka | AP | 支持 | 低(2.x版本闭源) |
Zookeeper | CP | 不支持 | 中 |
Consul | CP | 支持 | 高 |
Nacos | AP/CP | 支持 | 高 |
CAP模型
计算机专家 埃里克·布鲁尔(Eric Brewer)于 2000 年在 ACM 分布式计算机原理专题讨论会(简称:PODC)中提出的分布式系统设计要考虑的三个核心要素:
- 一致性(Consistency):同一时刻的同一请求的实例返回的结果相同,所有的数据要求具有强一致性(Strong Consistency)
- 可用性(Availability):所有实例的读写请求在一定时间内可以得到正确的响应
- 分区容错性(Partition tolerance):在网络异常(光缆断裂、设备故障、宕机)的情况下,系统仍能提供正常的服务
以上三个特点就是CAP原则(又称CAP定理),但是三个特性不可能同时满足,所以分布式系统设计要考虑的是在满足P(分区容错性)的前提下选择C(一致性)还是A(可用性),即:CP或AP
CP原则
一致性 + 分区容错性原则
CP 原则属于强一致性原则,要求所有节点可以查询的数据随时都要保持一直(同步中的数据不可查询),即:若干个节点形成一个逻辑的共享区域,某一个节点更新的数据都会立即同步到其他数据节点之中,当数据同步完成后才能返回成功的结果,但是在实际的运行过程中网络故障在所难免,如果此时若干个服务节点之间无法通讯时就会出现错误,从而牺牲了以可用性原则(A),例如关系型数据库中的事务。
AP原则
可用性原则 + 分区容错性原则
AP原则属于弱一致性原则,在集群中只要有存活的节点那么所发送来的所有请求都可以得到正确的响应,在进行数据同步处理操作中即便某些节点没有成功的实现数据同步也返回成功,这样就牺牲一致性原则(C 原则)。
使用场景:对于数据的同步一定会发出指令,但是最终的节点是否真的实现了同步,并不保证,可是却可以及时的得到数据更新成功的响应,可以应用在网络环境不是很好的场景中。
Nacos的AP/CP
Nacos无缝支持一些主流的开源生态,同时再阿里进行Nacos设计的时候重复的考虑到了市场化的运作(市面上大多都是以单一的实现形式为主,例如:Zookeeper使用的是 CP、而 Eureka采用的是AP),在Nacos中提供了两种模式的动态切换。
Nacos 何时选择切换模式
一般来说,如果不需要储存服务界别的信息且服务实例通过nacos-client注册,并能够保持心跳上报,那么就可以选择AP模式。如Spring Cloud 和 Dubbo,都适用于AP模式,AP模式为了服务的可用性减弱了一致性,因此AP模式下只支持注册
临时实例
。如果需要在服务级别编辑或者储存配置信息,那么CP是必须的,K8S服务和DNS服务则是用于CP模式。CP模式下则支持注册
持久化实例
,此时则是以Raft协议为集群运行模式,该模式下注册实例之前必须先注册服务,如果服务不存在,则会返回错误。切换命令(默认是AP):
curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP'
注意:临时和持久化的区别主要在健康检查
失败后的表现,持久化实例健康检查失败后会被标记成不健康,而临时实例会直接从列表中被删除。
四、配置中心
1.基础配置
1.1 添加依赖
我们需要添加Nacos作为配置中心的依赖信息
<dependency>
<groupId> com.alibaba.cloud </groupId>
<artifactId> spring-cloud-starter-alibaba-nacos-config </artifactId>
</dependency>
1.2 配置信息
然后我们需要在bootstrap.yaml
中配置配置中心的相关信息。注意的是这里我们要配置两个,因为Nacos同SpringCloud-config一样,在项目初始化时,要保证先从配置中心进行配置拉取,拉取配置之后,才能保证项目的正常启动。
springboot中配置文件的加载是存在优先级顺序的,bootstrap优先级高于application
分别要配置的是,这里bootstrap.yml配置好了以后,作用是两个,第一个让3377这个服务注册到Nacos中,第二个作用就是去Nacos中去读取指定后缀为yaml的配置文件:
# nacos配置
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格式的配置
application.yml
spring:
profiles:
active: dev # 表示开发环境
1.3 主启动类
在主启动类上添加对应的注解
@EnableDiscoveryClient
@SpringBootApplication
public class AppConfigStart {
public static void main(String[] args) {
SpringApplication.run(AppConfigStart.class, args);
}
}
1.4 业务类
这里的@RefreshScope实现配置自动更新,意思为如果想要使配置文件中的配置修改后不用重启项目即生效,可以使用@RefreshScope配置来实现
@RestController
@RefreshScope //支持Nacos的动态刷新功能
public class ConfigClientController {
@Value("${config.info}")
private String configInfo;
@GetMapping("/config/info")
public String getConfigInfo(){
return configInfo;
}
}
1.5 Nacos的配置规则
在 Nacos Spring Cloud 中,dataId
的完整格式如下(详情可以参考官网 https://nacos.io/zh-cn/docs/quick-start-spring-cloud.html):
${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配置中心添加的配置文件的名字规则和名字为:
s p r i n g . a p p l i c a t i o n . n a m e − {spring.application.name}- spring.application.name−{spring.profiles.active}.${file-extension}
nacos-config-client-dev.yaml
微服务名称-当前环境-文件格式
1.6 配置创建
然后在nacos中添加相关的配置信息
config:
info: nacos config center,version = 1
然后在配置中心就会看到刚刚发布的配置
1.7 自动配置更新
修改Nacos配置,不需要重启项目即可自动刷新.
修改版本号为2,点击发布
测试访问即可,注意在SpringBoot2.4之后需要显示的添加如下的依赖。bootstrap.yaml 才会生效
<!-- SpringBoot2.4之后要让 bootstrap.yaml 文件生效我们需要添加该依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
2.综合应用
2.1 DataID
在实际的开发中我们需要面对各种不同的环境。比如开发环境。测试环境和生产环境。不同的环境下我们的配置信息是有差异的。这时我们就可以通过spring.profile.active
来指定不同的环境来对应不同的配置文件。
比如我们上面的案例是dev
开发环境。那么对应的配置文件的名称就是nacos-config-client-dev.yaml
.然后我们把对应的环境切换到test
测试环境。那么对应的配置文件的名称就是nacos-config-client-test.yaml
.然后我们在nacos中创建该配置文件
项目的spring.profile.active
也需要变动下
然后测试访问
2.2 Group
上面我们通过DataID来配置我们的配置信息。这种场景是把项目中的所有信息都配置在了一个配置文件中。这个会造成配置信息非常多。不便于管理这时我们可以根据配置信息的类别通过Group
来对配置信息进行分组。我们可以把配置信息中的MyBatis
的和数据库
的相关配置信息都单独的区分出来。在创建配置文件的时候指定分组即可。我们前面创建的使用的是默认分组DEFAULT_GROUP
.
MYBATIS
组: 注意:DataID还是一致的
DB
组
然后在项目中我们指定对应的分组即可
测试访问即可:
2.3 namespace
上面的group
方案可以基于配置信息的内容做划分。但是在实际的项目环境中。项目环境是比较复杂的。不同的项目不同的模块会有很多相似或者交叉的。这时我们可以通过namespace
来实现环境之间的隔离。
namespace默认是public
,这个我们不能删除。我们直接新建两个namespace: OA和CRM
上面的命名空间的ID我们是用的自动生成的即可。
在CRM的命名空间下创建配置文件
然后在OA的命名空间下创建配置文件
然后在代码中完成相关的配置
然后在bootstrap.yaml
中配置命名空间
server:
port: 7777
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: MYBATIS # 指定group
namespace: 4445ef5b-1851-40ee-851d-8a811de16134 # 指定 namespace
测试即可看到期望的结果:
2.4 配置拆分
上面的讲解中我们的DataID
还是统一的。我们可以通过group
的方式来拆分不同的配置信息。当然我们还可以通过配置拆分
的形式。我们定义不同类型的配置文件。比如:
然后在项目中我们特别指导改配置信息即可
server:
port: 7777
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: prod # 指定group
namespace: 4445ef5b-1851-40ee-851d-8a811de16134 # 指定 namespace
# 可以配置多个配置集
extension-configs[0]: # 配置拆解
data-id: mybatis-config.yaml
group: prod
refresh: true
访问测试:
搞定!
2.5 三者的关系
命名空间(Namespace)、配置分组(Group)和配置集ID(Data ID)是Nacos中的三个概念,用于进行资源管理和配置管理。
它们的区别和作用如下:
命名空间(Namespace):
定义:用于隔离和管理不同的资源,每个命名空间有唯一的标识符。
作用:资源隔离、权限控制、环境隔离。
配置分组(Group):
定义:用于对配置进行分类管理,每个配置分组有唯一的标识符。
作用:配置分类、配置隔离、动态刷新。
配置集ID(Data ID):
定义:用于唯一标识一个配置集,每个配置集有唯一的Data ID。
作用:配置集的唯一标识、配置集的分类管理、配置集的动态刷新。
在使用Nacos时,可以根据具体的需求和场景,合理使用命名空间、配置分组和配置集ID来进行资源和配置的管理。
五、Nacos集群搭建
1.集群结构
Nacos的集群环境我们采用这种结构:3个Nacos注册中心+1个MySql
2.Nacos集群
我们在windows上安装3个Nacos节点。分配配置相关信息
application.properties: 持久化数据到mysql中
修改 cluster.conf.example
为cluster.conf
然后在里面写上相关的集群节点信息
#2023-12-01T14:34:17.038
192.168.1.111:8848
192.168.1.111:8868
192.168.1.111:8888
这里注意,我们在修改端口的时候一定要有一定的偏移量,因为Nacos2.0本身新增了占用端口,所以我们在设置端口号的时候注意要避开,不要占用端口,以下是官网截图:
三个节点服务。注意不要放在有中文的目录下
然后分配启动三个服务即可
然后分配登录测试
然后把我们前面写的服务提供者和服务消费者注册到nacos中
然后可以看到相关的注册信息
3.Nginx负载均衡
上面我们配置了3个nacos的服务节点。具体调用哪个节点来注册我们可以通过nginx更好的来实现管理。我们下载个windows 版本的nginx:http://nginx.org/en/download.html
修改nginx.conf文件。添加负载均衡
的配置
#user nobody;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream nacos {
server 192.168.1.111:8848;
server 192.168.1.111:8868;
server 192.168.1.111:8888;
}
#gzip on;
server {
listen 80;
server_name 192.168.1.111;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http://nacos;
}
}
}
然后通过start nginx
来启动nginx服务
然后启动成功。同时我们可以在服务中也通过nginx来负载
启动后发现服务也正常的注册成功了
更多推荐
所有评论(0)