写点什么

SpringCloud Alibaba Nacos 使用详解

作者:牧小农
  • 2022 年 4 月 23 日
  • 本文字数:8816 字

    阅读完需:约 29 分钟

SpringCloud Alibaba Nacos 使用详解

点赞再看,养成习惯,微信搜索【牧小农】关注我获取更多资讯,风里雨里,小农等你,很高兴能够成为你的朋友。项目源码地址:公众号回复 nacos,即可免费获取源码

什么是微服务

在了解 Nacos 之前,我们先来了解一下,什么是微服务?在 2014 年的时候,一位叫 Martin Fowler(马丁·福勒 )的大神,提出了微服务的概念,定义:微服务是由单一应用程序构成的小小服务,拥有独立的进程和轻量化处理,服务依据业务功能设计,用全自动的方式进行部署,能够和其他服务使用 HTTP API 进行通信,同时服务会使用最小的规模进行集中管理,服务可以用不同的编程语言与数据库等组件实现。

架构的演变

记得小农刚工作的时候,那时候的服务大多是单体应用,可能完善一点的,会部署集群,就是一个完整的项目部署多台机器,那么随着互联网的发展,网站应用的承载量和规模也在不断的扩大,从而导致我们的系统架构也在不断的进行变化,从互联网早期到如今,系统架构大体经历了(单体 ——> 垂直——>分布式——>SOA——>微服务),如下图所示:


1、单体架构

在最开始的时候,大多数服务都是单体架构,就是把所有的功能点集中在一个项目(应用)里面,统一开发部署,这种开发、部署以及维护成本都比较低。


  • 这种的好处,就是其项目架构简单,上手容易,适合用户量少的项目,开发成本比较低,因为都部署在一个节点上,维护也方便

  • 缺点就是,所有的功能都集中在一个项目工程里面,随着业务的发展,代码和功能会越来越多,难以支撑一个大的项目进行开发和维护,项目之间模块耦合度高,容错性低,对于不同的功能模块优化和扩展性低。

2、垂直应用架构

所谓的垂直应用架构,就是从单体应用变成多个应用,用来提升效率,比如供应链系统可以拆分为:商品系统、订单系统、履约系统、门户系统、采购系统等等。


  • 其优点就是,项目拆分后实现了流量的分担,一定程度上解决并发问题,针对不同的业务模块可以进行优化和水平拓展,同时不同系统之间不会互相影响,提高容错率。

  • 缺点:系统之间互相存在,无法进行相互调用,系统之间互相独立,会造成一部分功能的冗余。

3、分布式系统

随着业务的增加,在垂直应用架构中冗余的代码越来越多,需要将冗余的代码抽离出来,统一做成单独的业务层进行处理,变成一个单独的服务,控制层调用不用的业务层服务完成不同的业务功能。具体可以理解为一个项目拆分成表现层和服务层两个部分,服务层实现业务逻辑,表现层处理页面交互。


  • 优点:抽取公共的功能作为服务层,能够提高代码的复用率

  • 缺点: 系统之间的耦合度高,调用关系复杂

4、SOA 架构

分布式系统中的缺点就是其调用复杂,当我们的服务越来越多或者当某一个服务压力过大需要进行水平拓展和负载均衡,对于资源的调度和治理就需要用到 SOA(Service Oriented Architecture)为核心来解决,治理中心还可以帮助我们解决服务之间协议不同的问题。


  • 优点:使用治理中心(ESB\dubbo)能够解决服务之间调用管理的自动调用

  • 缺点:服务之间会有一定的依赖关系,如果说某个环节错误会影响较大,服务关系复杂,运维部署困难

5、微服务架构

微服务架构在某种程序上来说是 SOA 架构往下发展的下一步,它更加强服务的“彻底拆分”,目的就是提高效率,微服务架构中,每个服务必须独立部署同时互不影响,微服务架构更加轻巧、轻量级。


微服务架构与 SOA 架构的不同之处


  1. 微服务架构处理更精细,某个模块只处理对应的功能,让专业的人做专业的事

  2. 每个服务都独立部署,服务之间互相不影响

  3. 在 SOA 架构中可能会数据库存储发生共享,而微服务强调每个服务都是独立数据库,保证每个服务之间的连接互不影响

  4. 微服务项目架构比 SOA 架构更适合互联网公司(迅捷开发、更效率的版本迭代、更细粒度)

微服务在生活中的体验

都说艺术来源于生活,那么技术也同样来自于生活!请举例说明例如:我们去撸串的时候,一般只有一两个人,集收银、招待、厨师于一体,而当我们去酒店的时候,会有专门的接待服务员、收银员、厨师、洗碗工等等,让专业的人做专业的事!



微服务的好处在于,能够将服务进行原子化拆分,独立进行打包、部署和升级,能够保证微服务之间清晰的任务划分,有利于扩展,但是微服务分布式系统开发的技术成本比较高,比如要考虑容错、分布式锁、分布式事务等等,复杂性更高。

Nacos 简介

Nacos (Naming Configuration Service) 归属于 Spring Cloud Alibaba 技术栈下,集动态服务发现、配置和服务管理平台,用于构建元原生应用程序。其中 服务发现是微服务架构中的最关键的组件之一 ,Nacos 提供了一组简单易用的特性,可以帮助我们更快速的实现动态服务发现、配置、元数据及流量管理。

什么是 Nacos

注册中心 + 配置中心 = Nacos

为啥使用 Nacos?

注册中心对比

CAP 模型

在这里我们不得不提到一个很重要的理论,就是 CAP 模型,这也是分布式系统设计中考虑的三个核心要素:


  • 一致性(Consistency): 同一时刻的同一请求的实例返回结果相同,所有的数据要求具有强一致性

  • 可用性(Availability): 所有实例的读写请求在一定时间内可以得到正确的响应

  • 分区容错性(Partition tolerance): 在网络异常(光缆断裂、设备故障、宕机)的情况下,系统任然能够提供正常的服务


以上就是 CAP 原则(又称 CAP 定理),但是以上三种情况不可能同时满足,分布式系统设计在考虑满足 P(分区容错性)的前提下选择 C(一致性)还是 A(可用性),也就是我们熟悉的 AP 和 CP

CP 原则(分区容错性+一致性)

CP 原则属于强一致性原则,要求所有节点可以查询的数据随时都要保持一致,若干个节点形成一个逻辑的共享区域,某一个节点更新的数据都会立即同步到其他数据节点之中,当数据同步完成之后才能返回成功的结果,但是在实际的运行过程中网络的故障在所难免,如果这个时候若干个服务节点之间无法通讯时就会出现错误,牺牲可用性原则(A)

AP 原则(分区容错性+可用性)

AP 原则属于弱一致性原则,在集群中只要有存活的节点,那么所发来的所有请求都可以得到正确的详情,在进行数据同步处理操作中即便某些节点没有成功的实现数据同步也返回成功,这样就牺牲了一致性原则(C),可以应用在网络环境不是很好的场景当中。


对于 Nacos 而言,支持 CP 和 AP 两种模式的动态切换,默认为 AP


切换命令:curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP'


Nacos 类似于我们酒店的前台,首先酒店里面的房间打扫干净以后并且符合入住条件的房间会注册到服务台,这样当有客人来就酒店住店,只需要通过前台去查找到可以入驻的房间即可,不需要进行等待,可以快速的入住到酒店


【房间 ——> 服务】【服务台 ——> Nacos】【客人 ——> 用户】


服务器提供的注册和发现机制可以帮助客人更快速的找到合适的房间。如果没有一个没有服务前台的酒店,客人入驻的时候需要自己寻找合适的房间,因为客人不知道每个房间的情况,无法确定哪个房间是服务入住条件的房间,客人只能一个一个去找,费时费力,同时这也是不合理的



在微服务中,软件服务各自独立,但是最终是作为一个整体来服务于客户,软件之间也需要彼此通信和方法调用,微服务架构内部发起通讯调用方法的一方,我们称之为 “服务消费者”,提供远程方法的服务器称之为 “服务提供者”,往往为了提高系统性能,会提供多个服务器作为 服务提供者 ,这个时候服务消费者找服务提供者的过程,就类似于用户在找房间的过程,为了帮助 服务消费者 快速的发现 服务提供者,在微服务框架中都会引入注册中心,注册中心就类似于酒店的前台,提供在软件服务的注册和发现功能,服务提供者 会先在注册中心进行注册,声明可以进行对外提供服务,而服务消费者只需要通过注册中心找到可以使用的服务,就可以快速使用服务了,注册中心实现了服务提供和服务消费的快速配合的功能。

Nacos 搭建

官网地址:https://nacos.io/zh-cn/index.html文档地址:https://nacos.io/zh-cn/docs/quick-start.html下载地址:https://github.com/alibaba/nacos/releases



一般推荐的是我们使用稳定版,官方也会在文档中说明



下载之后解压后就可以使用



执行命令:linux/Mac:


sh startup.sh -m standalone


Windows:


startup.cmd -m standalone


PS:注意 nacos 的文件路径一定要是英文,否则启动会报错


nacos 默认使用的数据库为内嵌的 cmdb,我们也可以创建本地数据库并修改配置文件指向本地数据库即可(推荐)。


启动成功以后,我们访问:http://localhost:8848/nacos用户名密码默认为:nacos/nacos 如下图所示表示我们启动成功!


Nacos 服务端的搭建

Nacos 注册中心

服务发现是微服务架构中的关键组件之一。在这样的架构中,手动为每个客户端配置服务列表可能是一项艰巨的任务,并且使动态扩展变得极其困难。Nacos Discovery 帮助您将服务自动注册到 Nacos 服务器,Nacos 服务器会跟踪服务并动态刷新服务列表。此外,Nacos Discovery 将服务实例的一些元数据,如主机、端口、健康检查 URL、主页等注册到 Nacos


官方 API 文档:https://spring.io/projects/spring-cloud-alibaba#learn


有的同学会说,小农我 english 不太好,别担心,现在浏览器上不是有翻译吗,直接翻译!!!


创建项目

我们需要创建一个聚合工程,这样如果需要添加新的 Nacos 服务,直接添加子模块就可以新建父类项目:spring-cloud-alibaba 新建子类项目:cloud-alibaba-nacos-9001


POM


父类项目


<dependencyManagement>    <dependencies>        <dependency>            <groupId>com.alibaba.cloud</groupId>            <artifactId>spring-cloud-alibaba-dependencies</artifactId>            <version>2021.0.1.0</version>            <type>pom</type>            <scope>import</scope>        </dependency>    </dependencies></dependencyManagement>
复制代码


在子项,引入 Nacos Discovery 进行服务注册/发现


<dependency>   <groupId>com.alibaba.cloud</groupId>    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>
复制代码


YML


server:  port: 9001spring:  application:    name: nacos-provider  cloud:    discovery:      server-addr: localhost:8848
management: endpoint: 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 CloudAlibabaNacos9001Application {
public static void main(String[] args) { SpringApplication.run(CloudAlibabaNacos9001Application.class, args); }}
复制代码


测试类:


/** * @program: spring-cloud-alibaba * @ClassName DemoController * @description: * @author: 牧小农 * @create: 2022-03-27 17:08 * @Version 1.0 **/@RestControllerpublic class DemoController {    @Value("${server.port}")    private String serverPort;
@GetMapping(value = "/muxiaonong") public String getServerPort(){ return "hello Nacos Discovery"+serverPort; }}
复制代码


当我们启动服务以后,就可以看到在服务列表中,看到我们启动服务



参考 cloud-alibaba-nacos-9001 新建一个的服务 cloud-alibaba-nacos-9002

Nacos 消费者负载均衡

新建子类项目:cloud-alibab-consumer-8083Pom


<?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>    <parent>        <groupId>com.muxiaonong</groupId>        <artifactId>spring-cloud-alibaba</artifactId>        <version>0.0.1-SNAPSHOT</version>        <relativePath/> <!-- lookup parent from repository -->    </parent>    <groupId>com.muxiaonong</groupId>    <artifactId>cloud-alibab-consumer-8083</artifactId>    <version>0.0.1-SNAPSHOT</version>    <name>cloud-alibab-consumer-8083</name>    <description>Demo project for Spring Boot</description>    <properties>        <java.version>1.8</java.version>    </properties>    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</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-actuator</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-devtools</artifactId>            <scope>runtime</scope>            <optional>true</optional>        </dependency>        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-loadbalancer</artifactId>            <version>3.1.0</version>        </dependency>
</dependencies>
</project>
复制代码


同时我们也需要在父类项目中添加子类说明


<modules>    <module>cloudalibaba-nacos-9001</module>    <module>cloudalibaba-nacos-9002</module>    <module>cloudalibab-consumer-nacos-8083</module></modules>
复制代码


yml


server:  port: 8083spring:  application:    name: nacos-consumer  cloud:    discovery:      server-addr: localhost:8848
复制代码


启动类


@SpringBootApplication@EnableDiscoveryClientpublic class CloudAlibabConsumer8083Application {
public static void main(String[] args) { SpringApplication.run(CloudAlibabConsumer8083Application.class, args); } }
复制代码


nacos-provider: 服务注册者 nacos-consumer: 服务消费者


服务间的调用

如果我们想要我们创建服务的消费者去调用服务提供者,就需要通过 Ribbon 进行调用。

什么是 Ribbon

Spring Cloud Ribbon 是一个基于 HTTP 和 TCP 客户端负载均衡器,基于 Netflix Ribbon 实现,通过 Spring Cloud 的封装,可以让我们很方便的将面向服务的 Rest 模板请求自动转换成客户端负载均衡服务调用,虽然它知识一个工具类库,不需要进行独立部署,它几乎存在于每一个 Spring Cloud 构建的微服务和基础设施中,对于服务间的调用,AP 网关的请求转发都需要经过 Ribbon 负载均衡来实现,而 Ribbon 的主要作用是:从注册服务器端拿到对应的服务列表后用负载均衡的方式访问对应的服务


因为 Nacos 已经整合了 Ribbon,所以我们如果想要使用,只需要导入 Spring Cloud Alibaba Nacos 的依赖就可以直接使用了。


这个需要注意的是 nacos 自从 2020 版本之后不再整合的是 Netflix,也就没有 ribbon 了,如果报错说找不到服务是因为,你使用了负载均衡算法,但是没有 ribbon 了,它不知道该使用哪个服务。所以这里只需要导入 spring-cloud-starter-loadbalancer 依赖即可


<dependency>   <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-loadbalancer</artifactId>    <version>3.1.0</version></dependency>
复制代码


Ribbon 的基础使用

对于 Ribbon 进行远程调用,我们通常使用 RestTemplate,其中 getForObject 是最常用方法,我们只需要在启动类中添加 RestTemplate 就可以正常使用


   @Bean    @LoadBalanced //nacos集成了ribbon    public RestTemplate getRestTemplate() {        return new RestTemplate();    }
复制代码


当 body 是一个对象时,可以直接这样实现:User result = restTemplate.getForObject(uri, User.class);


不需要关注请求响应除 body 外的其他内容时,该函数就非常好用,可以少一个从 Response 中获取 body 的步骤。提供了三种不同的重载实现


url: 表示被调用的目标 Rest 接口位置,多个服务提供者注册相同名称,Ribbon 会自动寻找其中一个服务提供者,并且调用接口方法。这个就是负载均衡功能 responseType: 返回值类型,JavaBean 类型或者 JavaBean 数组类型 urlVariables: 传递给 url 的动态参数,使用参数时候需要在 url 上需要使用{1}、{2}、{3}进行参数占位,这样传递的参数就会自动替换占位符


getForObject(String url, Class responseType, Object ... urlVariables)getForObject(String url, Class responseType, Map urlVariables)getForObject(URI url, Class responseType)

Nacos 负载均衡

如果想让我们的消费者 consuomer 去调用服务提供者 9001 和 9002,就是使用到我们的负载均衡了。yml


server:  port: 8083spring:  application:    name: nacos-consumer  cloud:    discovery:      server-addr: localhost:8848
# 服务提供者的名称service-url: nacos-user-service: http://nacos-provider
复制代码


启动类上配置 restTemplate


 @Bean @LoadBalanced  public RestTemplate restTemplate(){      return new RestTemplate();  }
复制代码


测试类


import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;/** * @program: spring-cloud-alibaba * @ClassName DemoController * @description: * @author: 牧小农 * @create: 2022-04-04 16:11 * @Version 1.0 **/@RestControllerpublic class DemoController {
@Autowired private RestTemplate restTemplate;
//访问服务名 @Value("${service-url.nacos-user-service}") private String serverURL;
@GetMapping(value = "/consumer/nacos") public String getDiscovery(){ System.out.println(serverURL); return restTemplate.getForObject(serverURL+"/muxiaonong",String.class); }
复制代码


当我们输入:http://localhost:8083/consumer/nacos,就可以看到 9001 和 9002 对应的切换显示了


Nacos 配置中心

上面我们有讲 注册中心 + 配置中心 = Nacos ,前面我们将了注册中心,现在我们来讲一讲如何使用 Nacos 作为他的配置中心

为什么使用 Nacos 配置中心

1、配置属性的动态刷新 2、配置文件的集中管理


我们新建一个子项:cloud-alibaba-config-3377


pom 文件:


 <dependency>    <groupId>com.alibaba.cloud</groupId>    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency>
复制代码


YML 配置:在这里我们需要配置两个,一个是让当前项目注册到 Nacos 中,另外一个是去 Nacos 中读取指定后缀的配置文件 bootstrap.yml


# 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
复制代码


启动类同样添加@EnableDiscoveryClient注解


测试类:


import org.springframework.beans.factory.annotation.Value;import org.springframework.cloud.context.config.annotation.RefreshScope;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;
/** * @program: spring-cloud-alibaba * @ClassName DemoController * @description: * @author: 牧小农 * @create: 2022-04-10 16:02 * @Version 1.0 **/@RestController@RefreshScope //支持Nacos的动态刷新功能public class DemoController {
@Value("${config.info}") private String configInfo;
@GetMapping("/config/info") public String getConfigInfo(){ return configInfo; }}
复制代码

Nacos 的配置规则

官网:https://nacos.io/zh-cn/docs/quick-start-spring-cloud.html


在 Nacos Spring Cloud 中,dataId 的完整格式如下


${prefix}-${spring.profiles.active}.${file-extension}
复制代码


  • prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix 来配置。

  • spring.profiles.active 即为当前环境对应的 profile,详情可以参考 Spring Boot 文档。 注意:当 spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 ${prefix}.${file-extension}

  • file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 properties 和 yaml 类型。


 ${spring.application.name}-${spring.profiles.active}.${file-extension} nacos-config-client-dev.yaml 微服务名称-当前环境-文件格式
复制代码


接下来而我们只需要在 Nacos 平台上去创建配置系项即可





修改 Nacos 配置,不需要重启项目即可自动刷新


通过链接访问即可


小结

创作不易,您的一键三连是我最大的动力!!!


如果有疑问或者不懂的地方,欢迎在下面留言,小农看到了,会第一时间回复大家。


怕什么真理无穷,进一步 有进一步的欢喜,大家加油~

发布于: 刚刚阅读数: 2
用户头像

牧小农

关注

业精于勤荒于嬉,行成于思毁于随。 2019.02.13 加入

公众号【牧小农】

评论

发布
暂无评论
SpringCloud Alibaba Nacos 使用详解_nacos_牧小农_InfoQ写作社区