【微服务 Spring Cloud Alibaba】- Nacos 服务注册中心

news2024/11/27 1:31:02

目录

1. 什么是注册中心?

1.2 注册中心的作用

2. SpringBoot 整合 Nacos 实现服务注册中心

2.1 将服务注册到 Nacos

2.2 实现消费者

3. 服务列表各个参数的含义、作用以及应用场景


1. 什么是注册中心?

注册中心是微服务架构中的一个重要组件,它用于实现服务注册服务发现

【思考一】什么叫服务注册 ? 什么叫服务发现 ?

  • 服务注册就是生产者,它是服务的提供方,它用于将服务存储起来;
  • 服务发现是注册中心将服务列表推送给调用服务的消费者 / 消费者向注册中心拉取服务列表;

Nacos 结合了两者的优势,提供了一个更加灵活和高效的服务发现机制。在默认情况下,Nacos 使用推模式来通知消费者,但消费者仍然会定期拉取服务列表,以应对可能出现的消息丢失或延迟等问题。

【思考二】为什么需要服务注册和服务发现呢 ?服务之间直接调用存在什么问题呢 ?

① 服务注册与服务发现是为了更好的实现服务与服务之间的通信,降低服务与服务间的耦合度(健康检测机制)

② 服务之间直接调用存在的问题:

  1. 每个服务都可能有很多份,那我在调用的时候,就需要写很多份,而且需要一个一个手动分配,工作量太大;
  2. 微服务里边,服务起码得是集群B1,B2,B3......,如果直接写死,当某一天,某些服务挂了,就会引发一系列问题,从而就无法保证系统的高可用。

具体有以下几个问题:

  1. 单点故障:因为调用方直接依赖于特定的服务实例,所以当这个实例不可用时,调用方无法找到其他的可用实例,从而导致整个调用链路中断。

  2. 延迟与超时:当一个服务不可用,调用方可能会因为网络超时而等待很长时间,这会导致用户体验下降,并可能引发其他的连锁故障。

  3. 无法进行负载均衡:如果多个实例都可用,但调用方总是直接调用某一个特定实例,那么这将导致流量分布不均,某些实例可能会过载,而其他实例则处于空闲状态。

  4. 无法进行故障转移:当目标服务实例出现故障时,调用方无法自动切换到其他健康的实例。

  5. 扩展性受限:如果服务需要进行扩展,增加新的实例,调用方可能需要修改代码或配置来适应新的服务地址,这增加了运维的复杂性。

  6. 不透明的依赖关系:如果所有的服务都是直接相互调用,那么很难快速地了解服务之间的依赖关系,这在故障排查时可能会增加很多麻烦。

基于以上问题,所以我们需要使用服务注册于服务发现来更好的实现服务与服务之间的通信!

1.2 注册中心的作用

  • 服务注册:服务实例启动时,将自身注册到注册中心,包括服务名,地址,端口等;
  • 服务发现:消费者向注册中心拉取服务列表 / 注册中心推送服务列表给消费者;
  • 服务健康检测:注册中心会定期检测服务实例的健康状态,并过滤不健康的实例;
  • 服务路由:决定如何将请求分发到合适的服务实例,通常涉及到负载均衡策略;
  • 服务监控:监控服务的状态,如响应时间、错误率等,以便及时发现并处理问题;
  • 服务更新:当服务实例信息变更时,向注册中心发送更新信息通知。

2. SpringBoot 整合 Nacos 实现服务注册中心

2.1 将服务注册到 Nacos

实现之前,Nacos 服务要启动起来,创建好 SpringBoot 多模块项目(一个父模块和两个子模块)

如果不会创建 SpringBoot 多模块项目的,可以去看我的这篇文章:https://blog.csdn.net/xaiobit_hl/article/details/134144828

【实现步骤】

  1. 添加 Nacos discovery 支持 
  2. 配置 Nacos 连接信息
  3. 编写代码(开发接口)

PS:完成以上三步后,当前项目就会自动注册到 Nacos 中!

② Nacos 连接信息

spring:
  application:
    name: nacos-discovery-demo
    # Nacos 服务名 (命名不要使用下划线 _,早期的SpringCloud版本不支持)
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848  # 连哪个 Nacos 的注册中心
        username: nacos
        password: nacos
        # ephemeral: false   # false 设置此服务为永久实例,true 为临时实例
server:
  port: 0  # 动态端口号

③ 实现接口

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private ServletWebServerApplicationContext context; // 用于获取动态端口号

    // 服务
    @RequestMapping("/getnamebyid")
    public String getNameById(Integer id) {
        return "provider-name-" + id +
                " | port:" + context.getWebServer().getPort();
    }
}

PS:接口的实现不重要,重要的是我们能把它注册到注册中心,然后能通过另一个项目,调用到它!

【思考】为什么服务注册到注册中心,需要使用动态端口? 而不使用固定端口?

        只有当用户去使用 Nacos 的时候,才需要使用一个固定的端口号,它不能每次变化,每次变的话,用户就猜不出来这个端口号是多少。

        而对于微服务这边,它只需要将服务注册到注册中心,供消费者来使用,具体端口号是多少,对于程序来说,它不必预先知道。

并且使用动态端口有以下好处:

  1. 灵活性:动态端口允许服务在任何可用的端口上启动,避免了手动配置端口或处理端口冲突的问题。

  2. 高可用性:如果某个端口不可用(被其他进程占用或由于某些原因被阻止),服务可以选择其他任何可用的端口来启动,这增加了服务的高可用性。

  3. 简化配置:不需要为每个服务的实例手动分配和管理固定的端口号。

  4. 支持多实例:动态端口允许在同一台机器上运行多个相同的服务实例,这对于快速扩展和负载均衡很有利。

【测试服务注册中心】

当我们将服务注册到注册中心后,就可以在 Nacos  控制台看到这些信息了:

 

这个时候,我们就可以测试一下微服务里边的接口好不好使,点击操作下面的详情:

我们拿着 IP + 动态端口去访问接口,是可以正常访问得到的:

 【上线下线 Nacos 服务的作用】

        服务的上线与下线通常是指服务实例的动态注册与注销,利用这一特性,可以实现以下几种发布策略:

  1. 灰度发布:灰度发布是指先让部分用户试用新版本,而其它用户还在使用旧版本。通过Nacos,可以将新版本的服务实例注册到Nacos中,然后通过权重配置,让部分用户路由到新的服务实例上。(也可以通过标签配合 geteway 网关规则)

  2. 蓝绿部署:蓝绿部署是一种将新旧版本同时部署的策略,通过路由控制用户流量到不同的版本。通过Nacos的服务注册与发现,可以轻松地实现蓝绿部署:新版本(绿色)可以注册到Nacos,当确认新版本稳定后,可以将流量切换到新版本,同时下线旧版本(蓝色)。

  3. 金丝雀发布:金丝雀发布是灰度发布的一种,它先将新版本发布给一小部分用户,然后根据这部分用户的反馈和系统的表现,决定是否将新版本推广给更多的用户。利用Nacos的权重配置,可以轻松地实现金丝雀发布。

  4. 紧急回滚:如果新版本出现问题,就可以快速地在Nacos中下线新版本的服务实例,同时上线旧版本的服务实例,以此来实现紧急回滚。

PS:当服务被下线时,注册中心在公布服务列表的时候,就不会包含已经下线的服务了,即使它是健康状态。

【点击上线或下线报错问题】

        当点击上线下线如果报错了,或者创建临时实例 / 永久实例,报错了,可以通过以下方法来解决:

① 停止 Nacos 服务 (Ctrl  C 多按几遍)

② 删除 nacos/data 目录下的 protocol 文件夹 (非常好使)

③ 开启 Nacos 服务,再次点击上下线就不会报错了

2.2 实现消费者

【前置工作】

1. 创建一个消费者的 module,在 pom.xml 文件中声明父节点

<parent>
    <groupId>com.example</groupId>
    <artifactId>nacos-discovery-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</parent>

2. 删除不必要的依赖:test,nacos-discovery,java.version 等声明,以及 dependencyManagement 依赖。

3. 在父模块中声明子模块

<modules>
    <module>provider</module>
    <module>consumer</module>
</modules>

【实现步骤】

  1. 添加框架支持 【nacos discovery、spring cloud LoadBalancer、spring cloud OpenFeign】
  2. 配置 Nacos 连接信息
  3. 开启 OpenFeign 功能
  4. 声明 OpenFeign 式的 Service 【生产者的的服务】
  5. 调用服务【调用生产者的服务】

② 配置 Nacos 连信息

spring:
  application:
    name: nacos-consumer-demo
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        username: nacos
        password: nacos
        register-enabled: false  #消费者(不需要将此服务注册到 nacos)
        
server:
  port: 8080  # 使用固定端口

③ 开启 OpenFeign 功能

@SpringBootApplication
@EnableFeignClients   // 开启 OpenFeign
public class ConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }

}

PS:在启动类上加上 @EnableFeignClients  注解!

④ 声明 OpenFeign 式的 Service

@Service
@FeignClient("nacos-discovery-demo") //调用nacos中的nacos-discovery-demo服务
public interface UserService {

    @RequestMapping("/user/getnamebyid")  // 调用生产者的接口
    public String getNameById(@RequestParam("id") Integer id); //@RequestParam
}

方法中的参数最好添加 @RequestParam 注解,否则可能拿不到参数。

⑤ 调用服务

@RestController // 消费者
public class BusinessController {

    @Autowired
    private UserService userService;

    @RequestMapping("/getnamebyid")
    public String getNameById(Integer id) {
        return userService.getNameById(id);
    }
}

 【测试消费者】

开启两个生产者和一个消费者(测试负载均衡默认的轮询方式)

根据配置信息,使用 localhost:8080/getnamebyid?id=2 进行访问>>

第一次访问:

 

刷新后:(轮询的方式)

3. 服务列表各个参数的含义、作用以及应用场景

1. 服务名:服务的唯一标识符,用于区分不同的服务,对应我们配置文件写的 spring.application.name.

2. 分组名称:服务的分组标识,用于将服务进行逻辑隔离的。我们可以根据不同的环境或用途为服务设置不同的分组,例如“测试组”、“开发组”、“生产组”等。这样的隔离机制有助于管理和维护服务。

3. 集群数目:在一个服务内,可以有多个集群,每个集群下有多个服务实例。

4. 实例数:当前服务注册到Nacos的总实例数量,包括健康和不健康的实例。

5. 健康实力数:可以正常提供服务,没有故障的实例。

6. 触发保护阈值:它是一个 0-1 之间的数,表示当健康实例数低于此阈值时,Nacos会阻止所有服务实例的自动注销,以保护剩余的健康实例。(可以在服务详情里面的编辑服务中进行设置)

为什么要有保护阈值 ?

        它是为了防止服务雪崩的。比如说服务集群里边原本有 1000 个实例,但是现在有 999 个实例都挂了,只剩下一个实例了,那么原本 1000 个人干的活,现在就只剩一个人了,如果我们再把所有的活再派给这一个人来干,那么这个人他肯定也不在了,他肯定离职了。对于咱们系统来说也是一样,如果集群实例数太少的话,这时候还把所有的流量分发过去,那就会造成服务瘫痪,进而造成上游调用这个服务的整体瘫痪,进而造成服务雪崩。所以需要保护阈值。

保护阈值它是如何防止服务雪崩的 ?

        想要解决服务雪崩,无非就是加锁排队,但是 Nacos 它本身又不做限流,只有注册中心和配置中心,那它是怎么做到既没有限流功能,又要保证不会发生雪崩问题的呢?它的做法是 "躺平",当保护阈值为 true 的时候,它会将所有的请求分发给所有的服务实例(不管健康与否),即使有些服务实例已经挂掉了,以此来保护所剩无几的健康实例!

【保护阈值演示案例】

① 准备两个永久服务实例,一个消费者,然后停掉一个服务

如何快速创建相同实例 >>

  

PS:永久实例 - 对应配置文件中的 ephemeral: false

② 将保护阈值设置为 0.5,这时保护阈值就变为 true 了

③ 使用消费者调用服务

例如:localhost:8080/getnamebyid?id=2

        当我们更改了权重,阈值等参数,它默认是会有缓存的,感知不到,所以需要重启消费者才能看到 nacos 的防止雪崩的策略。

重启消费者后 >>

第一次访问:

第二次访问:

PS:第三次访问和第一次访问一样,第四次访问又报错,这就是 Nacos 的一个解决服务雪崩的手段!

【服务详情中的一些参数的含义】

1. 元数据:与服务相关的额外信息,可以是键值对形式的任意数据。(它会自动设置进去)

2. 服务路由类型:用于指定如何在消费者和成产者之间进行路由决策的,它可以实现请求的负载均衡。

PS:服务路由类型最主要的作用就是实现 CMDB,地域就近访问的,什么叫地域就近访问

        当有北京的调用者来获取服务的时候,他肯定是调用北京的服务是最快的,因为对于北京的调用者来说,北京的网络,路由调的次数肯定比深圳少,所以它的速度肯定快,那么深圳的调用者肯定是调用深圳的服务最快,这就是地域就近访问。

3. 权重:实例级别的设置。范围为 0-10000,用于负载均衡决策,权重越大,分配给该实例的流量越大。当权重为 0 的时候,和点击下线功能是一样的效果。

Nacos 的负载均衡策略总的来说有两种方式:

① 基于健康检测和权重

② 基于第三方 CMDB 的标签负载均衡器

这在官方的 《Nacos架构与原理》一书中原话是这样说的:

在 Nacos 0.7.0 版本中,我们除了提供基于健康检查和权重的负载均衡方式外,
还新提供了基于第三方 CMDB 的标签负载均衡器

🍁临时实例 VS 永久实例

① 定义和删除方式不同

1. 永久实例:其注册信息会一直保留在 Nacos 服务器上,直到主动注销或被删除。这就意味着即使服务实例下线,或者不健康了,他的注册信息仍然会保留在 Nacos 上。

2. 临时实例:其注册信息在服务实例下线,断开连接或者不健康时,会自动从服务注册列表中被删除。

如何删除永久实例:1.停服务;2. 删除 nacos/data 目录下的 protocol 文件夹;3. 启动 nacos 服务

② 健康检测机制不同

1. 永久实例:服务器反向探测机制,服务器主动来询问永久实例的健康与否。

2. 临时实例:客户端主动上报机制,客户端主动向服务器汇报自己的健康与否。

PS:临时实例每隔 5 秒就会主动上报一次自己的健康状态,发送的数据包叫做心跳包,发送心跳包的机制叫做心跳机制。如果 Nacos 服务端在 15 秒都没收到心跳,就会将实例设置为不健康,在 30 秒没收到心跳时就会将这个临时实例摘除。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1160748.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NoSQL数据库以及架构介绍

文章目录 一. 什么是NoSQL&#xff1f;二. NoSQL分类三. NoSQL与关系数据库有什么区别四. NoSQL主要优势和缺点五. NoSQL体系框架 其它相关推荐&#xff1a; 系统架构之微服务架构 系统架构设计之微内核架构 鸿蒙操作系统架构 架构设计之大数据架构&#xff08;Lambda架构、Kap…

Selenium学习(Java + Edge)

Selenium /səˈliːniəm/ 1. 简介 ​ Selenium是一个用于Web应用程序自动化测试工具。Selenium测试直接运行在浏览器中&#xff0c;就像真正的用户在操作一样。支持的浏览器包括IE、Mozilla Firefox、Safari、Google Chrome、Opera、Edge等。 ​ 适用于自动化测试&#x…

Linux期末复习——文件I/O编程

Linux系统调用以及用户编程接口 三者关系 系统调用、API以及系统命令之间关系&#xff1a; 什么是文件描述符&#xff1f; 是一个非负整数&#xff0c;索引值 打开或者创建一个文件的时候&#xff0c;内核会向进程返回一个文件描述符 读写文件时&#xff0c;会向函数传递一个文…

ModuleNotFoundError: No module named ‘paddle.fluid.incubate.fleet‘

在使用rocketqa的时候可能会遇到下面的问题&#xff1a; 问题&#xff1a; 解决方法&#xff1a; 这完全是paddlepaddle的问题。 在rocketqa/utils/optimization.py出现下面的语句&#xff0c;这个时候直接把出错的注释掉就可以&#xff0c;因为它完全没有用到。&#xff08;…

Win10奇怪的部分文字乱码问题

1.打开Windows设置的时间和语言 2.打开区域下方的的其他日期、时间和区域设置 3.点击更改日期、时间或数字格式。切换到管理 4.点击更改系统区域设置&#xff0c;取消Beta版&#xff1a;使用Unicode UTF-8提供全球语言支持。 按提示重启电脑即可。

Windows电脑怎么下载桌面便签小工具?

Windows电脑是日常办公中常用的工具&#xff0c;电脑上可以安装许多软件来辅助日常办公&#xff0c;其中桌面便签工具可以为大家记录很多日常办公中的各项工作计划&#xff0c;而且便签软件通常可以悬挂于电脑桌面显示&#xff0c;方便大家一边工作一边查看备忘记录。 谈及Win…

探索网络攻击:ARP断网、ARP欺骗和DNS欺骗实验解析

目录 前言 一、ARP概述 1.1 什么是ARP 1.2 ARP协议的基本功能 1.3 ARP缓存表 1.4 ARP常用命令 二、ARP断网实验 三、ARP欺骗实验 3.1 内网截获图片 3.2 HTTP账户密码获取 四、DNS欺骗实验 总结 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&…

OpenGL ES入门教程(一)编写第一个OpenGL程序

OpenGL ES入门教程&#xff08;一&#xff09;编写第一个OpenGL程序 前言 从本文开始我将参考学习OpenGL ES应用开发实践指南 Android卷 [&#xff08;美&#xff09;KevinBrothaler著]&#xff08;提取码: 394m&#xff09;&#xff0c;并基于自己的理解以更加通俗易懂的方式…

[.NET]桃源网络硬盘 v7.4

桃源网络硬盘是一个以.net进行开发的网络硬盘系统源码。 开发环境&#xff1a;Microsoft.NET Framework SDK 运行要求&#xff1a; Windows 2003及以上版本 或 Windows XP及以上版本&#xff0c;安装 .Net Framework 要求上传目录有写权限 请将其放在虚拟目录或单独的网页空间…

Kubernetes包管理工具Helm简介及使用

文章目录 前言技术积累什么是HelmHelm的核心概念Helm可以解决哪些痛点Helm中文官方文档 Helm安装Helm安装nginx用例写在最后 前言 大家都知道K8S是云原生devops的一大利器&#xff0c;可以直接让我们的中间件、应用服务直接运行在云端&#xff0c;让我们可以只关心自身的业务功…

【Unity】【VR开发疑难】Unity运行就报无法启动XR Plugin

【现象】 连接Link后运行Unity的VR项目Link也无反映&#xff0c;Unity控制台报&#xff1a;无法启动XR Plugin&#xff0c;并说是由于Oculus头盔未连接导致。 【分析】 打开Oculus PC客户端&#xff0c;发现状态是连接正常。重启机器后&#xff0c;提示Oculus没有出于RunTim…

概念解析 | 揭开心电图测量的神秘面纱

注1:本文系“概念解析”系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:ECG的测量原理 揭开心电图测量的神秘面纱 How to read an ECG – Physical Therapy Reviewer 1. 背景介绍 心电图(ECG)是记录心脏电活动的过程,它反映了心脏在收缩和舒张期间的…

新一代构建工具Vite-xyphf

一、什么vite? vite:是一款思维比较前卫而且先进的构建工具,他解决了一些webpack解决不了的问题——在开发环境下可以实现按需编译&#xff0c;加快了开发速度。而在生产环境下&#xff0c;它使用Rollup进行打包&#xff0c;提供更好的tree-shaking、代码压缩和性能优化&…

创建javaEE项目(无maven),JSP(九大内置对象)、Servlet(生命周期)了解

一、Servlet和jsp 0.创建web项目(无maven)&#xff1a; 1.创建一个普通的java项目 2.项目根目录右键&#xff0c;添加模板 3.配置tomcat服务器 4.配置项目tomcat依赖 1.Servlet(Server Applet)服务端小程序 用户通过浏览器发送一个请求&#xff0c;服务器tomcat接收到后&…

串口通信(7)判断数据帧头来接收一串数据

本文为博主 日月同辉&#xff0c;与我共生&#xff0c;csdn原创首发。希望看完后能对你有所帮助&#xff0c;不足之处请指正&#xff01;一起交流学习&#xff0c;共同进步&#xff01; > 发布人&#xff1a;日月同辉,与我共生_单片机-CSDN博客 > 欢迎你为独创博主日月同…

微信小程序:两层循环的练习,两层循环显示循环图片大图(大图显示、多层循环)

效果 代码分析 外层循环 外层循环的框架 <view wx:for"{{info}}" wx:key"index"></view> wx:for"{{info}}"&#xff1a;这里wx:for指令用于指定要遍历的数据源&#xff0c;即info数组。当遍历开始时&#xff0c;会依次将数组中的每…

链表的结点个数统计及查找

链表节点个数统计 要统计链表中的节点个数&#xff0c;只需要遍历整个链表&#xff0c;并在遍历的过程中计数即可。具体实现代码如下&#xff1a;(仍然使用C#) 先定义一个整型函数(节点个数的返回值一定是整型变量) int getLinkNodeNum(struct Test *head) {int cnt 0;whil…

STM32:AHT20温湿度传感器驱动程序开发

注&#xff1a;温湿度传感器AHT20数据手册.pdf http://www.aosong.com/userfiles/files/AHT20%E4%BA%A7%E5%93%81%E8%A7%84%E6%A0%BC%E4%B9%A6(%E4%B8%AD%E6%96%87%E7%89%88)%20B1.pdf 一、分析AHT数据手册文档 (1).准备工作 1.新建工程。配置UART2 2.配置I2C1为I2C标准模式&…

数据链路层中存在的报文ip,arp,rarp

IP数据报 ARP请求/应答报 RARP请求/应答报 IP数据报 这里的目的地址和源地址是MAC地址。 这个被称为 MAC 地址&#xff0c;是一个网卡的物理地址&#xff0c;用十六进制&#xff0c;6 个 byte 表示。 MAC 地址是一个很容易让人误解的地址。因为 MAC 地址号称全球唯一&…

深度学习_7_实战_点集最优直线解_优化版代码解析

完整版优化代码&#xff1a; import torch from torch.utils import data from d2l import torch as d2l # 特定导入 from torch import nndef load_array(data_arrays, batch_size, is_trainTrue):dataset data.TensorDataset(*data_arrays) #解包传递&#xff0c;转成张量…