Microservicios Nacos

1 Notas de la versión

Dirección del sitio web oficial:

https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E

1.1 rama 2021.x

Las versiones de Spring Cloud Alibaba adaptadas a SpringBoot 2.4, Spring Cloud 2021.x y superiores se enumeran en la siguiente tabla (la última versión está marcada con *):

(Tenga en cuenta que el método de denominación de la versión Spring Cloud Alibaba de esta rama se ha ajustado. En el futuro, corresponderá a la versión Spring Cloud. Los primeros tres dígitos son la versión Spring Cloud y el último dígito es la versión extendida Por ejemplo, Spring Cloud correspondiente a la versión Spring Cloud 2021.0.1 (la primera versión de Alibaba es: 2021.0.1.0, la segunda versión es: 2021.0.1.1, etc.)

Versión de Spring Cloud Alibaba Versión de nube de primavera Versión de arranque de primavera
2021.0.5.0* Nube de primavera 2021.0.5 2.6.13
2021.0.4.0 Nube de primavera 2021.0.4 2.6.11
2021.0.1.0 Nube de primavera 2021.0.1 2.6.3
2021.1 Nube de primavera 2020.0.1 2.4.2

1.2 rama 2.2.x

La versión de Spring Cloud Alibaba adaptada a Spring Boot 2.x, la versión Spring Cloud Hoxton y siguientes es la siguiente (la última versión está marcada con *):

Versión de Spring Cloud Alibaba Versión de nube de primavera Versión de arranque de primavera
2.2.8.LIBERACIÓN* Nube de primavera Hoxton.SR12 2.3.12.LIBERACIÓN
2.2.7.LIBERACIÓN Nube de primavera Hoxton.SR12 2.3.12.LIBERACIÓN
2.2.6.LIBERACIÓN Nube de primavera Hoxton.SR9 2.3.2.LIBERACIÓN
2.1.4.LIBERACIÓN Nube de primavera Greenwich.SR6 2.1.13.LIBERACIÓN
2.2.1.LIBERACIÓN Nube de primavera Hoxton.SR3 2.2.5.LIBERACIÓN
2.2.0.LIBERACIÓN Spring Cloud Hoxton.LANZAMIENTO 2.2.X.LIBERACIÓN
2.1.2.LIBERACIÓN Primavera Nube Greenwich 2.1.X.LIBERACIÓN
2.0.4.RELEASE (detener el mantenimiento, se recomienda actualizar) Nube de primavera Finchley LANZAMIENTO 2.0.X.
1.5.1.RELEASE (detener el mantenimiento, se recomienda actualizar) Edgware de nube de primavera 1.5.X.LIBERACIÓN

1.3 Relación de versión del componente

Cada versión de Spring Cloud Alibaba y las versiones correspondientes de cada componente al que se adapta se muestran en la siguiente tabla:

Versión de Spring Cloud Alibaba Versión centinela Versión Nacos Versión RocketMQ Versión Dubbo Versión Seata
2.2.8.LIBERACIÓN 1.8.4 2.1.0 4.9.3 ~ 1.5.1
2021.0.1.0 1.8.3 1.4.2 4.9.2 ~ 1.4.2
2.2.7.LIBERACIÓN 1.8.1 2.0.3 4.6.1 2.7.13 1.3.0
2.2.6.LIBERACIÓN 1.8.1 1.4.2 4.4.0 2.7.8 1.3.0
2021.1 o 2.2.5.VERSIÓN o 2.1.4.VERSIÓN o 2.0.4.VERSIÓN 1.8.0 1.4.1 4.4.0 2.7.8 1.3.0
2.2.3.LIBERACIÓN o 2.1.3.LIBERACIÓN o 2.0.3.LIBERACIÓN 1.8.0 1.3.3 4.4.0 2.7.8 1.3.0
2.2.1.LIBERACIÓN o 2.1.2.LIBERACIÓN o 2.0.2.LIBERACIÓN 1.7.1 1.2.1 4.4.0 2.7.6 1.2.0
2.2.0.LIBERACIÓN 1.7.1 1.1.4 4.4.0 2.7.4.1 1.0.0
2.1.1.LIBERACIÓN o 2.0.1.LIBERACIÓN o 1.5.1.LIBERACIÓN 1.7.0 1.1.4 4.4.0 2.7.3 0.9.0
2.1.0.RELEASE o 2.0.0.RELEASE o 1.5.0.RELEASE 1.6.3 1.1.1 4.4.0 2.7.3 0.7.1

2 Comprender el descubrimiento de servicios

2.1 Comprender el descubrimiento de servicios

2.1.1 Entorno de prueba

En la arquitectura de microservicios, todo el sistema se divide en múltiples servicios según responsabilidades y capacidades, y los objetivos comerciales se logran mediante la colaboración entre servicios. De esta manera, las llamadas remotas entre servicios son inevitables en nuestro código. El consumidor del servicio necesita llamar al productor del servicio. Para completar una solicitud, el consumidor necesita conocer la ubicación de la red (dirección IP y número de puerto). del productor de servicios.

(La transferencia de la imagen del enlace externo falló. El sitio de origen puede tener un mecanismo anti-leeching. Se recomienda guardar la imagen y cargarla directamente (img-AjaMeq7W-1693272596958)(assets\image-20210316120231655.png)]

Podemos lograr esto fácilmente a través de la tecnología Spring Boot:

1. Cree el proyecto principal alibaba_cloud

pom.xml es el siguiente:

<?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.yunhe</groupId>
    <artifactId>alibaba_cloud</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
  <dependencyManagement>
        <dependencies>
            <!--SpringBoot-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.3.2.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.22</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

2. Servicio B (productor de servicios)

Cree el proveedor de servicios order_server.

pom.xml es el siguiente:

<?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">
    <parent>
        <artifactId>alibaba_cloud</artifactId>
        <groupId>cn.yunhe</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>order_server</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>

El servicio B es el productor del servicio y expone la dirección del servicio /getOrder. El código de implementación es el siguiente: 1. Cree un controlador

package cn.yunhe.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/order")
public class OrderController {
    
    

    @GetMapping("/getOrder")
    public String getOrder(){
    
    
        return "获取订单详情";
    }
}

2. Crear clase de inicio

package cn.yunhe;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

Archivo de configuración:

Cree application.yml con el siguiente contenido:

server:
  port: 9200

3. Servicio A (consumidor del servicio)

Cree un proyecto de consumo de servicios consumer_server.

pom.xml es el siguiente:

<?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">
    <parent>
        <artifactId>alibaba_cloud</artifactId>
        <groupId>cn.yunhe</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>consumer_server</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>

Código de implementación:

1. Crear controlador

package cn.yunhe.controller;

import cn.yunhe.api.OrderApi;
import cn.yunhe.service.UserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/consumer")
public class ConsumerController {
    
    

    @GetMapping("/getOrder")
    public String getOrder(){
    
    
        RestTemplate restTemplate = new RestTemplate();
        String url = "http://127.0.0.1:9200/order/getOrder";
        String orderStr = restTemplate.getForObject(url, String.class);
        return "Consumer::"+orderStr;
    }
}

2. Crear clase de inicio

package cn.yunhe;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

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

Archivo de configuración:

Cree application.yml con el siguiente contenido:

server:
  port: 9100

Visite http://localhost:9100/consumer/getOrder/ y genere el siguiente contenido:

Consumer::获取订单详情

2.2.2 Proceso de descubrimiento de servicios

Si lo piensa detenidamente, la solución anterior no funcionará para una aplicación de microservicios. En primer lugar, los microservicios se pueden implementar en un entorno de nube y las ubicaciones de red de las instancias de servicio se pueden asignar dinámicamente. Además, cada servicio suele tener varias instancias para el equilibrio de carga. Debido al tiempo de inactividad o las actualizaciones, la dirección de red de la instancia del servicio a menudo cambiará dinámicamente. Además, cada servicio también puede agregar nuevos nodos de servicio en respuesta a la presión de acceso temporal. Como se muestra en la siguiente figura:

[La transferencia de la imagen del enlace externo falló. El sitio de origen puede tener un mecanismo anti-leeching. Se recomienda guardar la imagen y cargarla directamente (img-bjywHEa3-1693272596960)(assets\image-20210316120254867.png)]

Con base en las preguntas anteriores, ¿cómo se descubren entre sí los servicios? ¿Cómo se gestionan los servicios? Este es el problema del descubrimiento de servicios.

El descubrimiento de servicios es el proceso en el que los consumidores de servicios descubren de forma inteligente a los proveedores de servicios a través del centro de descubrimiento de servicios y realizan llamadas remotas. Como se muestra abajo:

[La transferencia de la imagen del enlace externo falló. El sitio de origen puede tener un mecanismo anti-leeching. Se recomienda guardar la imagen y cargarla directamente (img-sYEho2Ri-1693272596961)(assets\image-20210316120304796.png)]

En la figura anterior, la instancia de servicio en sí no registra la dirección de red del productor del servicio. Todas las instancias de servicio contendrán un cliente de descubrimiento de servicios .

(1) Cuando se inicie cada servicio, informará su ubicación de red al centro de descubrimiento de servicios . De esta manera, se formará un registro de servicios dentro del centro de descubrimiento de servicios.El registro de servicios es la parte central del descubrimiento de servicios y es una base de datos que contiene las direcciones de red de todas las instancias de servicios.

(2) El cliente de descubrimiento de servicios sincronizará periódicamente el registro de servicios desde el centro de descubrimiento de servicios y lo almacenará en caché en el cliente.

(3) Cuando se requiere una solicitud para un determinado servicio, la instancia de servicio localiza la dirección de red del servicio de destino a través del registro. Si hay varias direcciones de red para el servicio de destino, se utiliza un algoritmo de equilibrio de carga para seleccionar una de las múltiples instancias de servicio y luego realizar la solicitud.

En resumen, en un entorno de microservicio, dado que la dirección de red de la instancia de ejecución del servicio cambia constantemente de forma dinámica y el número de instancias de servicio cambia dinámicamente, es imposible utilizar un archivo de configuración fijo para registrar la dirección de red del proveedor de servicios. Se debe utilizar el descubrimiento dinámico de servicios y utilizar mecanismos para lograr el conocimiento mutuo . Cada instancia de servicio informará su propia dirección de red, de modo que el centro de servicio forme un registro de servicio completo.Cada instancia de servicio obtendrá la dirección de red para acceder al servicio de destino a través del centro de descubrimiento de servicios , implementando así el mecanismo de descubrimiento de servicios.

3 descubrimiento de servicios de Nacos

3.1 Introducción a Nacos

3.1.1 Comparación de productos de descubrimiento de servicios

Actualmente, los centros de descubrimiento de servicios más utilizados en el mercado son: Nacos, Eureka, Consul y Zookeeper.

Comparar artículos Nacos eureka Cónsul cuidador del zoológico
protocolo de coherencia Soporta modelos AP y CP modelo AP modelo CP modelo CP
Examen de salud TCP/HTTP/MYSQL/Cliente Beat Golpe del cliente TCP/HTTP/gRPC/Cmd Mantener viva
Estrategia de equilibrio de carga peso/metadatos/Selector Cinta fabio -
protección contra avalanchas tener tener ninguno ninguno
Cerrar sesión automáticamente en una instancia apoyo apoyo no apoyo apoyo
acuerdo de acceso HTTP/DNS HTTP HTTP/DNS tcp
Soporte de monitoreo apoyo apoyo apoyo apoyo
Múltiples centros de datos apoyo apoyo apoyo no apoyo
Sincronizar entre registros apoyo no apoyo apoyo no apoyo
Integración de SpringCloud apoyo apoyo apoyo no apoyo
integración de dubbo apoyo no apoyo no apoyo apoyo
integración k8s apoyo no apoyo apoyo no apoyo

De la comparación anterior, podemos entender que Nacos, como centro de descubrimiento de servicios, tiene elementos de soporte más funcionales. A largo plazo, Nacos admitirá la combinación de Spring C Loud + Kubernetes en versiones futuras para llenar el vacío entre los dos sistemas. Se puede utilizar el mismo conjunto de soluciones de gestión de configuración y descubrimiento de servicios, lo que simplificará enormemente los costes de uso y mantenimiento. Además, Nacos planea implementar Service Mesh, que también es la tendencia de desarrollo futuro de los microservicios.

3.1.2 Introducción a Nacos

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NwYRklSS-1693272596961)(assets/image-20210316120357611.png)]

Nacos是阿里的一个开源产品,它是针对微服务架构中的服务发现、服务治理、配置管理的综合型解决方案。

官方介绍是这样的:

Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您实现动态服务发现、服务配置管理、服务及流量管理。 Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Nacos 是构建以“服务”为中心的现代应用架构的服务基础设施。

官网地址:https://nacos.io

3.1.3 Nacos特性

Nacos主要提供以下四大功能:

1. 服务发现与服务健康检查

Nacos使服务更容易注册,并通过DNS或HTTP接口发现其他服务,Nacos还提供服务的实时健康检查,以防止向不健康的主机或服务实例发送请求。

2. 动态配置管理

动态配置服务允许您在所有环境中以集中和动态的方式管理所有服务的配置。Nacos消除了在更新配置时重新 部署应用程序,这使配置的更改更加高效和灵活。

3. 动态DNS服务

Nacos提供基于DNS 协议的服务发现能力,旨在支持异构语言的服务发现,支持将注册在Nacos上的服务以域名的方式暴露端点,让三方应用方便的查阅及发现。

4. 服务和元数据管理

Nacos能让您从微服务平台建设的视角管理数据中心的所有服务及元数据,包括管理服务的描述、生命周期、服务的静态依赖分析、服务的健康状态、服务的流量管理、路由及安全策略。

这里1、3、4说明了服务发现的功能特性。

3.2 安装Nacos Server

3.2.1 预备环境准备

Nacos 依赖 Java 环境来运行。如果您是从代码开始构建并运行Nacos,还需要为此配置 Maven环境,请确保是在以下版本环境中安装使用:

  1. 64 bit OS,支持 Linux/Unix/Mac/Windows,推荐选用 Linux/Unix/Mac。

  2. 64 bit JDK 1.8+;下载 & 配置

  3. Maven 3.2.x+;下载 & 配置

3.2.2 下载安装包

进入到github中的nacos网址,选择Releases

https://github.com/alibaba/nacos

选择版本进行下载

3.2.3 启动服务器

nacos的默认端口是8848,需要保证8848默认端口没有被其他进程占用。进入安装程序的bin目录:

Windows启动方式: 启动命令:

cmd startup.cmd或者双击startup.cmd运行文件。

启动成功,可通过浏览器访问 http://127.0.0.1:8848/nacos ,打开如下nacos控制台登录页面:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pbd31pIu-1693272596962)(assets\image-20210316100921240.png)]

使用默认用户名:nacos,默认密码:nacos 登录即可打开主页面。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-77HO0iqA-1693272596962)(assets\image-20210316100945265.png)]

3.3 RESTful服务发现

3.3.1 测试环境

在alibaba_cloud父工程中添加依赖管理

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.3.2.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR9</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.6.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.22</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

分别在服务提供及服务消费工程中添加依赖,此依赖的作用是服务发现

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

3.3.2 服务注册

在服务提供工程中配置nacos服务发现相关的配置:

order_server服务提供:

server:
  port: 9200
spring:
  application:
    name: order-server
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

启动nacos

启动服务提供

观察nacos服务列表,order-server注册成功

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-52sxaHD2-1693272596962)(assets\image-20220902145738251.png)]

服务名称:每个服务在服务注册中心的标识,相当于Java中的类名。

服务实例:网络中提供服务的实例,具有IP和端口,相当于Java中的对象,一个实例即为运行在服务器上的一个进程。

3.3.3 服务发现

在服务消费工程中配置nacos服务发现相关的配置:

consumer_server服务消费

server:
  port: 9100
spring:
  application:
    name: consumer-server
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

修改Controller中远程调用的代码:

@Autowired
LoadBalancerClient loadBalancerClient;

@GetMapping("/getOrder")
public String getOrder(){
    
    
    RestTemplate restTemplate = new RestTemplate();
    ServiceInstance choose = loadBalancerClient.choose("order-server");
    URI uri = choose.getUri();
    String url = uri+"/order/getOrder";
    String orderStr = restTemplate.getForObject(url, String.class);
    return "Consumer::"+orderStr;
}

执行流程:

1、服务提供方将自己注册到服务注册中心

2、服务消费方从注册中心获取服务地址

3、进行远程调用

3.3.4 负载均衡

在RESTful服务发现的流程中,ServiceA通过负载均衡调用ServiceB,下边来了解一下负载均衡

负载均衡就是将用户请求(流量)通过一定的策略,分摊在多个服务实例上执行,它是系统处理高并发、缓解网络 压力和进行服务端扩容的重要手段之一。它分为服务端负载均衡客户端负载均衡

服务器端负载均衡:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WEEQxXuq-1693272596963)(assets\image-20210316103219732.png)]

在负载均衡器中维护一个可用的服务实例清单,当客户端请求来临时,负载均衡服务器按照某种配置好的规则(负载均衡算法)从可用服务实例清单中选取其一去处理客户端的请求。这就是服务端负载均衡。

例如Nginx,通过Nginx进行负载均衡,客户端发送请求至Nginx,Nginx通过负载均衡算法,在多个服务器之间选择一个进行访问。即在服务器端再进行负载均衡算法分配。

客户端服务负载均衡:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E57sUopL-1693272596964)(assets\image-20210316103240358.png)]

上边使用的LoadBalancerClient就是一个客户端负载均衡器,具体使用的是Ribbon客户端负载均衡器。

Ribbon在发送请求前通过负载均衡算法选择一个服务实例,然后进行访问,这是客户端负载均衡。即在客户 端就进行负载均衡的分配。

Ribbon是一个客户端负载均衡器,它的责任是从一组实例列表中挑选合适的实例,如何挑选?取决于负载均衡策略

Ribbon核心组件IRule是负载均衡策略接口,它有如下实现,大家仅做了解:

1.轮询策略:RoundRobinRule(默认)

2.权重策略:WeightedResponseTimeRule.根据每个服务提供者的响应时间分配一个权重,响应时间越长,权重越小,被选中的可能性也就越低。

3.随机策略:RandomRule

4.最小连接数策略:BestAvailableRule。也叫最小并发数策略,它是遍历服务提供者列表,选取连接数最小的⼀个服务实例。如果有相同的最小连接数,那么会调用轮询策略进行选取。

5.重试策略:RetryRule。按照轮询策略来获取服务,如果获取的服务实例为 null 或已经失效,则在指定的时间之内不断地进行重试来获取服务,如果超过指定时间依然没获取到服务实例则返回 null。

6.可用敏感性策略:AvailabilityFilteringRule。先过滤掉非健康的服务实例,然后再选择连接数较小的服务实例。

7.区域敏感策略:ZoneAvoidanceRule,根据服务所在区域(zone)的性能和服务的可用性来选择服务实例,在没有区域的环境下,该策略和轮询策略类似。

准备测试环境:

复制order_server工程,修改端口、pom的artifactId和启动类,导入启动多个服务提供方进程,查看调用效果

复制order_server修改目录名:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PI1wxQbr-1693272596964)(assets\1.png)]

修改pom的artifactId:

修改启动类的名称:

修改端口号:

server:
  port: 9201

然后再服务提供方的方法中输出端口,启动测试观察负载均衡效果!

单个服务策略,可通过下面方式在服务消费方的 配置文件中修改默认的负载均衡策略:

order-server: 
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

即服务提供方的服务名称:

​ com.netflix.loadbalancer.RandomRule:负载均衡类路径。

全局策略设置案例—修改为随机策略:

@Configuration
public class RibbonGlobalLoadBalanceConfig {
    
    
  @Bean
  public IRule ribbonRule(){
    
    
  	return new RandomRule();
   }
}

3.3.5 小结

服务注册与发现流程:

1、服务提供方将自己注册到服务注册中心

2、服务消费方从注册中心获取服务地址

3、通过客户端负载均衡器进行远程调用

3.4 整合OpenFeign客户端

由于OpenFeign集成了Ribbon,所以可以自动实现负载均衡。

3.4.1.consumer_server添加依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

3.4.2.修改启动类

添加注解@EnableFeignClients

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

3.4.3.创建Feign接口

package cn.yunhe.api;

@FeignClient(value = "order-server")
public interface OrderApi {
    
    
    @GetMapping("/order/getOrder")
    String getOrder();
}

3.4.4.修改Controller

@Autowired
private OrderApi orderApi;

@GetMapping("/getOrder2")
public String getOrder2(){
    
    
    String orderStr = orderApi.getOrder();
    return "Consumer::"+orderStr;
}

发送http://localhost:9100/consumer/getOrder请求,结果如下:

Consumer::获取订单详情

3.5 Dubbo服务发现

Dubbo是阿里巴巴公司开源的RPC框架,在国内有着非常大的用户群体,但是其微服务开发组件相对Spring Cloud

来说并不那么完善。

Spring Cloud Alibaba微服务开发框架集成了Dubbo,可实现微服务对外暴露Dubbo协议的接口,Dubbo协议相比RESTful协议速度更快。

RPC:RPC是远程过程调用(Remote Procedure Call)的缩写形式,调用RPC远程方法就像调用本地方法一样,非常方便,后边案例讲解具体过程。

3.5.1 Dubbo服务架构

下图是微服务采用Dubbo协议的系统架构图:

组件说明:

1、客户端:前端或外部系统

2、API网关:系统唯一入口,路由转发

3、application-1 :应用1,前端提供Http接口,接收用户的交互请求

4、service-1 :微服务1,提供业务逻辑处理服务

5、service-2:微服务2,提供业务逻辑处理服务

交互流程:

1、网关负责客户端请求的统一入口,路由转发,前端通过网关请求后端服务。

2、网关收到前端请求,转发请求给应用。

3、应用接收前端请求,调用微服务进行业务逻辑处理

4、微服务为应用提供业务逻辑处理的支撑,为应用提供Dubbo协议接口

优势分析:

此架构同时提供RESTful和Dubbo接口服务,应用层对前端提供RESTful接口,RESTful是互联网通用的轻量级交互协议,方便前端接入系统;微服务层向应用层提供Dubbo接口,Dubbo接口基于RPC通信协议速度更快。

本架构采用阿里开源的Nacos,集服务发现和配置中心于一身,支持RESTful及Dubbo服务的注册。

3.5.2 测试环境

父工程:alibaba_cloud。

application1:使用consumer_server。

service1微服务:需要新建

service2微服务:暂不演示,只演示servce1向consumer提供服务

api网关:后边的课程内容讲解。

3.5.3 service1微服务

service1为user_server服务,对外暴露dubbo协议的接口,考虑远程接口可能会被其它多个服务调用,这里将user_server的接口单独抽取出api工程,user_server微服务工程的结构如下:

user_server_api:存放接口,独立成一个工程方便被其它服务工程依赖。user_server_service:存放接口实现,即dubbo服务的实现部分。

3.5.3.1 定义user_server_api

1、创建user_server工程

<?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">
    <parent>
        <artifactId>alibaba_cloud</artifactId>
        <groupId>cn.yunhe</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>user_server</artifactId>
    <packaging>pom</packaging>
</project>

2、创建user_server_api工程

<?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">
    <parent>
        <artifactId>user_server</artifactId>
        <groupId>cn.yunhe</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>user_server_api</artifactId>

</project>

3、定义接口

package cn.yunhe.service;

public interface UserService {
    
    
    String getUser();
}

3.5.3.2 定义user_server_service

1、创建user_server_service工程

<?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">
    <parent>
        <artifactId>user_server</artifactId>
        <groupId>cn.yunhe</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>user_server_service</artifactId>

    <dependencies>
        <dependency>
            <groupId>cn.yunhe</groupId>
            <artifactId>user_server_api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-dubbo</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
    </dependencies>
</project>

2、定义接口实现

package cn.yunhe.service;

import org.apache.dubbo.config.annotation.DubboService;

@DubboService
public class UserServiceImp implements UserService {
    
    
    @Override
    public String getUser() {
    
    
        return "获取用户信息!";
    }
}

3、定义启动类

package cn.yunhe;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

4、定义配置文件application.yml

server:
  port: 7100
spring:
  application:
    name: user-server
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
dubbo:
  scan:
    base-packages: cn.yunhe.service
  protocol:
    name: dubbo
    port: 20811
  registry:
    address: nacos://127.0.0.1:8848
  consumer:
    check: false #关闭启动时检查

5、启动user_server

启动成功观察nacos的服务列表

6、bootstrap.yml配置说明

bootstrap.yml内容中以dubbo开头的为dubbo服务 的配置:

  1. dubbo.scan.base-packages: 指定 Dubbo 服务实现类的扫描基准包,将@DubboService注解标注的service暴露为dubbo服务。
  2. dubbo.protocol: Dubbo 服务暴露的协议配置,其中子属性name为协议名称。port为dubbo协议端口。可以指定多协议。
  3. dubbo.registry: Dubbo 服务注册中心配置,其中子属性address的值 “nacos://127.0.0.1:8848”,说明dubbo服务注册到nacos。相当于原生dubbo的xml配置中的<dubbo:registry address=“10.20.153.10:9090” />

bootstrap.yml内容的上半部分为SpringCloud的相关配置:

  1. spring.application.name: Spring 应用名称,用于 Spring Cloud 服务注册和发现。该值在 Dubbo Spring Cloud 加持下被视作 dubbo.application.name,因此,无需再次配置。

  2. spring.cloud.nacos.discovery: Nacos 服务发现与注册配置,其中子属性 server-addr 指定 Nacos 服务器主机和端口。

3.5.4 consumer_server调用user_server

3.5.4.1 引用user_server

在consumer_server工程中引用user_server_api依赖和dubbo相关依赖

<dependency>
    <groupId>cn.yunhe</groupId>
    <artifactId>user_server_api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
</dependency>

3.5.4.2 实现远程调用

修改consumer_server工程的ConsumerController:

package cn.yunhe.controller;

@RestController
@RequestMapping("/consumer")
public class ConsumerController {
    
    
    @DubboReference
    private UserService userService;
    
    @GetMapping("/getUser")
    public String getUser(){
    
    
        String userStr = userService.getUser();
        return "Consumer::"+userStr;
    }
}

3.6 服务发现数据模型

3.6.1 Namespace 隔离设计

命名空间(Namespace)用于进行租户粒度的隔离,Namespace的常用场景之一是不同环境的隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。

从一个租户(用户)的角度来看,如果有多套不同的环境,那么这个时候可以根据指定的环境来创建不同的namespce,以此来实现多环境的隔离。例如,你可能有开发,测试和生产三个不同的环境,那么使用一套nacos 集群可以分别建以下三个不同的 namespace。如下图所示:

3.6.2 命名空间管理

前面已经介绍过,命名空间(Namespace)是用于隔离多个环境的(如开发、测试、生产),而每个应用在不同环境的同一个配置(如数据库数据源)的值是不一样的。因此,我们应针对企业项目实际研发流程、环境进行规划。 如某软件公司拥有开发、测试、生产三套环境,那么我们应该针对这三个环境分别建立三个namespace。

建立好所有namespace后,在配置管理服务管理模块下所有页面,都会包含用于切换namespace(环境)的tab按钮,如下图:

注意:

1.namesace 为 public 是 nacos 的一个保留空间,如果您需要创建自己的 namespace,不要和 public重名,以一个实际业务场景有具体语义的名字来命名,以免带来字面上不容易区分自己是哪一个namespace。

2.在编写程序获取配置集时,指定的namespace参数一定要填写命名空间ID,而不是名称。

3.6.3 数据模型

Nacos在经过阿里内部多年生产经验后提炼出的数据模型,则是一种服务-集群-实例的三层模型,这样基本可以满 足服务在所有场景下的数据存储和管理。

nacos服务发现的数据模型如下:

服务

对外提供的软件功能,通过网络访问预定义的接口。

服务名

服务提供的标识,通过该标识可以唯一确定要访问的服务。

实例

提供一个或多个服务的具有可访问网络地址(IP:Port)的进程,启动一个服务,就产生了一个服务实例。

元信息

Nacos数据(如配置和服务)描述信息,如服务版本、权重、容灾策略、负载均衡策略、鉴权配置、各种自定义标 签 (label),从作用范围来看,分为服务级别的元信息、集群的元信息及实例的元信息。

集群

服务实例的集合,服务实例组成一个默认集群, 集群可以被进一步按需求划分,划分的单位可以是虚拟集群,相同集群下的实例才能相互感知。

通过数据模型可知:

应用通过Namespace、Service、Cluster(DEFAULT)的配置,描述了该服务向哪个环境(如开发环境)的哪个集群注册实例。

例子如下:

指定namespace的id:a1f8e863-3117-48c4-9dd3-e9ddc2af90a8(注意根据自己环境设置namespace的id)

指定集群名称:DEFAULT表示默认集群,可不填写

spring:
 application:
   name:  transaction-service
 cloud:
   nacos:
     discovery:
       server-addr: 127.0.0.1:7283 # 注册中心地址
       namespace: a1f8e863-3117-48c4-9dd3-e9ddc2af90a8 # 开发环境
       cluster-name: DEFAULT # 默认集群,可不填写

注意: 集群作为实例的隔离,相同集群的实例才能相互感知。

注意: namespace、cluster-name若不填写都将采取默认值,namespace的默认是public命名空间, cluster-name的默认值为DEFAULT集群。

3.6.4 创建dev命名空间,将所有的服务添加到namespace中

略。

4 Nacos配置管理

3.1 理解配置中心

3.1.1 什么是配置

应用程序在启动和运行的时候往往需要读取一些配置信息,配置基本上伴随着应用程序的整个生命周期,比如:数据库连接参数、启动参数等。

配置主要有以下几个特点:

配置是独立于程序的只读变量

配置对于程序是只读的,程序通过读取配置来改变自己的行为,但是程序不应该去改变配置 配置伴随应用的整个生命周期

配置贯穿于应用的整个生命周期,应用在启动时通过读取配置来初始化,在运行时根据配置调整行为。 比如:启动时需要读取服务的端口号、系统在运行过程中需要读取定时策略执行定时任务等。

配置可以有多种加载方式

常见的有程序内部hard code,配置文件,环境变量,启动参数,基于数据库等配置。

同一份程序在不同的环境(开发,测试,生产)、不同的集群(如不同的数据中心)经常需要有不同的配置,所以需要有完善的环境、集群配置管理

3.1.2 什么是配置中心

在微服务架构中,当系统从一个单体应用,被拆分成分布式系统上一个个服务节点后,配置文件也必须跟着迁移

(分割),这样配置就分散了,不仅如此,分散中还包含着冗余,如下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-us6vMaBU-1693272596965)(assets/11.png)]

下图显示了配置中心的功能,配置中心将配置从各应用中剥离出来,对配置进行统一管理,应用自身不需要自己去管理配置。

配置中心的服务流程如下:

1、用户在配置中心更新配置信息。

2、服务A和服务B及时得到配置更新通知,从配置中心获取配置。

总得来说,配置中心就是一种统一管理各种应用配置的基础服务组件。

3.1.3 主流配置中心对比

目前市面上用的比较多的配置中心有:Spring Cloud Config、Apollo、Nacos和Disconf等。由于Disconf不再维护,下面主要对比一下Spring Cloud Config、Apollo和Nacos。

对比项目 Spring Cloud Config Apollo Nacos
配置实时推送 支持(Spring Cloud Bus) 支持(HTTP长轮询1s内) 支持(HTTP长轮询1s内)
版本管理 支持(Git) 支持 支持
配置回滚 支持(Git) 支持 支持
灰度发布 支持 支持 不支持
权限管理 支持(依赖Git) 支持 不支持
多集群 支持 支持 支持
多环境 支持 支持 支持
监听查询 支持 支持 支持
多语言 只支持Java 主流语言,提供了Open API 主流语言,提供了Open API
配置格式校验 不支持 支持 支持
单机读(QPS) 7(限流所致) 9000 15000
单击写(TPS) 5(限流所致) 1100 1800
3节点读(QPS) 21(限流所致) 27000 45000
3节点写(TPS) 5(限流所致) 3300 5600

​ 从配置中心角度来看,性能方面Nacos的读写性能最高,Apollo次之,Spring Cloud Config依赖Git场景不适合开放的大规模自动化运维API。

​ 功能方面Apollo最为完善,nacos具有Apollo大部分配置管理功能,而Spring Cloud Config不带运维管理界面,需要自行开发。Nacos的一大优势是整合了注册中心、配置中心功能,部署和操作相比Apollo都要直观简单,因此它简化了架构复杂度,并减轻运维及部署工作。

​ 综合来看,Nacos的特点和优势还是比较明显的,下面我们一起进入Nacos的世界。

3.2 Nacos配置管理

3.2.1 发布配置

首先在nacos发布配置,consumer_server服务从nacos读取配置。

浏览器访问 http://127.0.0.1:8848/nacos ,打开nacos控制台,并点击菜单配置管理->配置列表: 在Nacos添加如下的配置:

consumer_server:

Namespace: dev
DataID:  consumer-server.yaml
Group:  DEFAULT_GROUP
配置格式:      YAML
配置内容:    
common:
  name: application1 config

3.2.2 获取配置

要想从配置中心获取配置添加nacos-config的依赖:

<dependency>
	<groupId>com.alibaba.cloud</groupId>
	<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

新建配置文件bootstrap.yml并添加配置:

spring:
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848 # 配置中心地址
        namespace: a1f8e863-3117-48c4-9dd3-e9ddc2af90a8
        file-extension: yaml
        group: DEFAULT_GROUP

注意:要使用配置中心就要在bootstrap.yml中来配置,bootstrap.yml配置文件的加载顺序要比application.yml要优先。

consumer_server服务读取配置文件中的信息:

@Value("${common.name}") 
private String common_name;

@GetMapping(value = "/configs")
public String getvalue(){
    
    
	return common_name;
}

基于上面的例子,若要实现配置的动态更新,只需要在controller类上添加注解:

@RefreshScope
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
    
    
    ...
}

我们通过nacos控制台更新common.name的配置值,再次访问web端点/configs,发现应用程序能够获取到最新的配置值,说明spring-cloud-starter-alibaba-nacos-config 支持配置的动态更新。

我们可以通过配置spring.cloud.nacos.config.refresh.enabled=false来关闭动态刷新。

3.2.3 配置管理模型

对于Nacos配置管理,通过Namespace、group、Data ID能够定位到一个配置集。

配置集(Data ID)

在系统中,一个配置文件通常就是一个配置集,一个配置集可以包含了系统的各种配置信息,例如,一个配置集可 能包含了数据源、线程池、日志级别等配置项。每个配置集都可以定义一个有意义的名称,就是配置集的ID即Data ID。

配置项

配置集中包含的一个个配置内容就是配置项。它代表一个具体的可配置的参数与其值域,通常以 key=value 的形式存在。例如我们常配置系统的日志输出级别(logLevel=INFO|WARN|ERROR) 就是一个配置项。

配置分组(Group)

配置分组是对配置集进行分组,通过一个有意义的字符串(如 Buy 或 Trade )来表示,不同的配置分组下可以有相同的配置集(Data ID)。当您在 Nacos 上创建一个配置时,如果未填写配置分组的名称,则配置分组的名称默认采用 DEFAULT_GROUP 。配置分组的常见场景:可用于区分不同的项目或应用,例如:学生管理系统的配置集可以定义一个group为:STUDENT_GROUP。

命名空间(Namespace)

​ **命名空间(namespace)**可用于进行不同环境的配置隔离。例如可以隔离开发环境、测试环境和生产环境,每个环境的配置是不同的。不同的命名空间下,可以存在相同名称的配置分组(Group) 或 配置集。

最佳实践

Nacos抽象定义了Namespace、Group、Data ID的概念,具体这几个概念代表什么,取决于我们把它们看成什么,这里推荐给大家一种用法,如下图:

Namespace:代表不同环境,如开发、测试、生产环境。

Group:代表某项目,如XX医疗项目、XX电商项目

DataId:每个项目下往往有若干个工程,每个配置集(DataId)是一个工程的主配置文件

获取某配置集的代码

获取配置集需要指定:

​ 1、nacos服务地址,必须指定

​ 2、namespace,如不指定默认public。在config中指定namespace,例子如下:

config:
  server-addr: 127.0.0.1:8848 # 配置中心地址
  file-extension: yaml
  namespace: a1f8e863-3117-48c4-9dd3-e9ddc2af90a8 # 开发环境
  group: DEFAULT_GROUP # xx业务组

​ 3、group,如不指定默认 DEFAULT_GROUP

​ 见上边第2点的例子。

​ 4、dataId,若不指定默认为名称为应用名称+配置文件扩展名

3.3 自定义扩展的 Data Id 配置

3.3.1 ext-config扩展配置

Spring Cloud Alibaba Nacos Config可支持自定义 Data Id 的配置。 一个完整的配置案例如下所示:

server:
  port: 9100
spring:
  application:
    name: consumer-server
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        namespace: 122c7220-e69e-4363-ae89-bc7af9133bba
      config:
        server-addr: 127.0.0.1:8848 # 配置中心地址
        namespace: 122c7220-e69e-4363-ae89-bc7af9133bba
        file-extension: yaml
        ext-config[0]:
          data-id: ext-common.yaml
          group: COMMON_GROUP
          refresh: true

可以看到:

通过 spring.cloud.nacos.config.ext-config[n].data-id 的配置方式来支持多个 Data Id 的配置。

通过 spring.cloud.nacos.config.ext-config[n].group 的配置方式自定义 Data Id 所在的组,不明确配置的话,默认是 DEFAULT_GROUP。

通过spring.cloud.nacos.config.ext-config[n].refresh 的配置方式来控制该 Data Id 在配置变更时,是否支持应用中可动态刷新, 感知到最新的配置值。默认是不支持的。

spring.cloud.nacos.config.ext -config[n].data-id 的值必须带文件扩展名,文件扩展名既可支持
properties,又可以支持 yaml/yml。 此时 spring.cloud.nacos.config.file -extension 的配置对自定义扩
展配置的 Data Id 文件扩展名没有影响。

测试:

配置ext-config-common01.yaml:

配置ext-config-common02.yaml:

编写测试代码:

@Value("${common.name}")
private String name;
@Value("${common.addr}")
private String address;

@GetMapping(value = "/configs") 
public String getvalue(){
    
    
    return  name+address;
}

重启consumer_server工程

通过测试发现:

扩展配置优先级是 spring.cloud.nacos.config.ext -config[n].data-id 其中 n 的值越大,优先级越高。

5 服务续约和下线

Nacos客户端默认5秒一次向Nacos服务端发送一次心跳包。

如果心跳包的间隔时间超过了15秒,则标记该服务为非健康实例。

如果心跳包超过30秒,那么Nacos服务端会把此服务实例从服务列表删除,也就是当心跳包超过15秒会标记为非健康实例,再有15秒就会把这个失效实例剔除!

6 注册中心数据结构

  1. Nacos注册中心数据结构也是一个双层map:
Map<String, Map<String, Service>> serviceMap = new ConcurrentHashMap<>();

外层map的key为namespace,value为Map<String, Service>。

内层的key为group::serviceName,value为service类。

  1. 对于Service类也有个重要的Map为:

    Map<String, Cluster> clusterMap = new HashMap<String, Cluster>();
    

    注册相关的核心数据结构就是clusterMap了,key是个string,保存的是clustername,value是个Cluster类型。

  2. 来看cluster类,核心数据结构是两个Set

    private Set<Instance> persistentInstances = new HashSet<>();
    
    private Set<Instance> ephemeralInstances = new HashSet<>();
    

    第一个是用来存储临时实例,第二个是用来存储持久化实例,有个关键点,什么情况会存储在临时实例,什么情况下会存储持久化实例,这个是由客户端的配置来决定的,默认情况下客户端配置ephemeral=true,如果你想把实例用持久化的方式来存储,可以设置ephemeral=false,这样在客户端发起注册的时候会把这个参数带到Nacos Server,Nacos Server就会按照持久化的方式来存储。

t-config-common01.yaml:

配置ext-config-common02.yaml:

编写测试代码:

@Value("${common.name}")
private String name;
@Value("${common.addr}")
private String address;

@GetMapping(value = "/configs") 
public String getvalue(){
    
    
    return  name+address;
}

重启consumer_server工程

通过测试发现:

扩展配置优先级是 spring.cloud.nacos.config.ext -config[n].data-id 其中 n 的值越大,优先级越高。

5 服务续约和下线

Nacos客户端默认5秒一次向Nacos服务端发送一次心跳包。

如果心跳包的间隔时间超过了15秒,则标记该服务为非健康实例。

如果心跳包超过30秒,那么Nacos服务端会把此服务实例从服务列表删除,也就是当心跳包超过15秒会标记为非健康实例,再有15秒就会把这个失效实例剔除!

6 注册中心数据结构

  1. Nacos注册中心数据结构也是一个双层map:
Map<String, Map<String, Service>> serviceMap = new ConcurrentHashMap<>();

外层map的key为namespace,value为Map<String, Service>。

内层的key为group::serviceName,value为service类。

  1. 对于Service类也有个重要的Map为:

    Map<String, Cluster> clusterMap = new HashMap<String, Cluster>();
    

    注册相关的核心数据结构就是clusterMap了,key是个string,保存的是clustername,value是个Cluster类型。

  2. 来看cluster类,核心数据结构是两个Set

    private Set<Instance> persistentInstances = new HashSet<>();
    
    private Set<Instance> ephemeralInstances = new HashSet<>();
    

    第一个是用来存储临时实例,第二个是用来存储持久化实例,有个关键点,什么情况会存储在临时实例,什么情况下会存储持久化实例,这个是由客户端的配置来决定的,默认情况下客户端配置ephemeral=true,如果你想把实例用持久化的方式来存储,可以设置ephemeral=false,这样在客户端发起注册的时候会把这个参数带到Nacos Server,Nacos Server就会按照持久化的方式来存储。

Supongo que te gusta

Origin blog.csdn.net/zhangchen124/article/details/132554497
Recomendado
Clasificación