La primera muestra de las notas de estudio integrales de Spring Cloud

prefacio

Este artículo es para registrar las notas durante el proceso de aprendizaje de SpringCloud de Dark Horse.Este artículo es la primera parte del artículo práctico, que registra la arquitectura de microservicios, el centro de registro de Eurake, el centro de gestión de registro y configuración de Nacos, Ribbon, Feign y Gateway en detalle; y Docker, MQ, ES y otros componentes del servicio se seguirán registrando en la segunda parte de la parte práctica. Finalmente, gracias por leer y espero que obtenga algo al final.


Conociendo los microservicios

Con el aumento del negocio portátil de proyectos individuales, es inevitable que los proyectos se vuelvan cada vez más grandes, lo que no conduce al mantenimiento de proyectos posteriores, lo que resulta en cambios en la estructura del proyecto.Muy hinchado, muy acopladoPor lo tanto, la arquitectura de servicios actual también ha evolucionado de un solo proyecto a una arquitectura distribuida y de microservicios .


arquitectura monolítica

单体架构: Todas las funciones del negocio se desarrollan en un proyecto, se empaquetan en un paquete y se implementan en el servidor

inserte la descripción de la imagen aquí

la ventaja es

  • simple y conveniente
  • fácil de usar
  • Dificultad operativa baja

la debilidad es

  • Con el aumento del negocio, la estructura se infla gradualmente.
  • Alto grado de acoplamiento, no es fácil de mantener

arquitectura distribuida

分布式架构: El sistema se divide según las funciones comerciales, y cada módulo de funciones comerciales se desarrolla como un proyecto independiente, denominado servicio.

Aquí hay una cita del maestro Yan

El núcleo de la distribución es solo una palabra: demolición .Siempre que un proyecto se divida en varios módulos y estos módulos se implementen por separado, se considera distribuido.


分布式的拆分可以分为水平拆分和垂直拆分

dividir horizontalmente

Entendida literalmente, la división horizontal se divide según el modelo de tres niveles. La "arquitectura de tres niveles" se divide en capa de presentación (jsp+servlet), capa de lógica de negocios (servicio) y capa de acceso a datos (dao), y luego se implementa por separado Integración entre servidores a través de dubbo o RPC

división vertical

Dividir según el negocio . Por ejemplo, según la lógica comercial , como los sistemas comunes de comercio electrónico, el módulo de usuario se puede considerar como un proyecto independiente. De manera similar, los pedidos y los chats también se pueden dividir en un proyecto independiente. ==Obviamente, estos tres proyectos divididos todavía se pueden usar como proyectos independientes. == Un método de división como este se convierte en una división vertical .

Ventajas y desventajas de la arquitectura distribuida:

ventaja:

  • Reducir el acoplamiento de servicios
  • Propicio para la actualización y expansión del servicio

defecto:

  • La relación de la llamada de servicio es compleja

arquitectura de microservicios

Los microservicios se pueden entender como una división vertical muy fina . Por ejemplo, el "artículo de pedido" anterior es originalmente un subartículo dividido verticalmente, pero de hecho el "artículo de pedido" se puede dividir en "artículo de compra", "artículo de liquidación" y "artículo posventa".

Los microservicios son servicios "pequeños" que no se pueden desmantelar, similares a la "atomicidad"

Cuatro características de la arquitectura de microservicio :

  • Responsabilidad única: la granularidad de la división de microservicios es más pequeña y cada servicio corresponde a una capacidad comercial única, para lograr una responsabilidad única
  • Autonomía: equipo independiente, tecnología independiente, datos independientes, implementación y entrega independientes
  • Orientado a servicios: los servicios proporcionan una interfaz estándar unificada, independiente del idioma y la tecnología.
  • Fuerte aislamiento: las llamadas de servicio son aisladas, tolerantes a fallas y degradadas para evitar problemas en cascada

Las características anteriores de los microservicios en realidad están estableciendo un estándar para la arquitectura distribuida, reduciendo aún más el acoplamiento entre servicios y brindando independencia y flexibilidad a los servicios. Lograr alta cohesión y bajo acoplamiento.

Por lo tanto, los microservicios pueden considerarse como una solución de arquitectura distribuida con una arquitectura bien diseñada

①Ventajas: La granularidad dividida es más pequeña, el servicio es más independiente y el grado de acoplamiento es más bajo

②Desventajas: La estructura es muy compleja y aumenta la dificultad de operación y mantenimiento, monitoreo e implementación


La siguiente figura es un diagrama de una arquitectura de microservicio estándar

La función y la estructura combinada de cada módulo se muestran en la siguiente figura

inserte la descripción de la imagen aquí


Tenga en cuenta que los microservicios no son solo SpringCloud

inserte la descripción de la imagen aquí


Ver Spring Cloud por primera vez

Como una de las grandes familias de Spring, SpringCloud también es el marco de microservicios más utilizado en China. SpringCloud integra varios componentes funcionales de microservicios y realiza el ensamblaje automático de estos componentes en función de SpringBoot, lo que proporciona una buena solución lista para usar. experiencia

Aquí hay algunos componentes comunes

inserte la descripción de la imagen aquí
La capa inferior de SpringCloud depende de SpringBoot y existe una relación de compatibilidad de versiones


Gobernanza de microservicios

Los más conocidos en China son SpringCloud y Alibaba's Dubbo. Más tarde, el marco SpringCloudAlibaba más popular lanzado por Ali es compatible con los dos primeros protocolos de servicio (Dubbo, Feign)

inserte la descripción de la imagen aquí

Cuatro soluciones para el aterrizaje de la arquitectura de microservicios

inserte la descripción de la imagen aquí


Caso de arquitectura de servicios distribuidos

Ahora vamos a demostrar un pequeño ejemplo de demostración de la división del servicio.
Por ejemplo, ahora dividimos el módulo de usuario y el módulo de pedido; los pasos son los siguientes

①首先为两个项目建立各自的数据库,导入对应的数据(sql文件)创建表

inserte la descripción de la imagen aquí


②先创建boot主项目(如果是b站黑马过来的,直接导入资料文件夹下的demo项目),然后创建其他模块的项目

Tenga en cuenta que la capa inferior de la nube depende del arranque.Por lo tanto, las versiones de nube y de arranque deben corresponder uno a uno, esto es importante, la correspondencia específica es la siguiente

inserte la descripción de la imagen aquí
Por ejemplo, el siguiente es el archivo pom del proyecto principal

inserte la descripción de la imagen aquí
Dependencias en el proyecto principal proyecto

    <dependencyManagement>
        <dependencies>
            <!-- springCloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${
    
    spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- mysql驱动 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${
    
    mysql.version}</version>
            </dependency>
            <!--mybatis-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${
    
    mybatis.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

Luego cree un proyecto de submódulo, la versión de arranque es alta, baje manualmente la versión después de la creación, es decir, en el padre, simplemente ajuste y actualice manualmente la versión

La estructura específica del proyecto es la siguiente

inserte la descripción de la imagen aquí
Luego mejore los submódulos, primero escriba un negocio de consulta básico, capa de mapeador, capa de servicio, capa de controlador, no hay nada que decir, si usa la api de mp, incluso puede ser más rápido.

A continuación, inicie los proyectos de servicio de usuario y servicio en la nube, y luego visite http://localhost:8080/order/101 con el navegador, y podrá ver que se han consultado los datos de la información del pedido.

inserte la descripción de la imagen aquí


③实现远程调用

Sin embargo, el atributo de usuario en la figura anterior es nulo. Esto se debe a que no hay un campo de usuario en la tabla de pedidos. Si es un solo proyecto en el pasado, consultará directamente las dos tablas. Sin embargo, para proyectos de microservicio, cada El módulo es responsable de su propio negocio. No se permite la duplicación de negocios, por lo que se requieren llamadas remotas.

Necesitamos iniciar una solicitud http al servicio de usuario en el servicio de pedido y llamar a la interfaz http://localhost:8081/user/{userId}.

inserte la descripción de la imagen aquí

Los pasos aproximados son los siguientes:

  • Registre una instancia de RestTemplate en el contenedor Spring
  • Modifique el método queryOrderById en la clase OrderService en el servicio de servicio de pedidos y consulte al Usuario de acuerdo con el ID de usuario en el objeto Pedido.
  • Complete el Usuario consultado en el objeto Pedido y devuélvalo juntos

La implementación es la siguiente
En la clase de inicio en el proyecto de servicio de pedidos, registre la instancia de RestTemplate

@MapperScan("cn.order.mapper")
@SpringBootApplication
public class OrderApplication {
    
    

    public static void main(String[] args) {
    
    
        SpringApplication.run(OrderApplication.class, args);
    }
    
    @Bean
    public RestTemplate restTemplate(){
    
    
        return new RestTemplate();
    }
}

Modifique el método queryOrderById en la clase OrderService bajo la capa de servicio en el servicio de servicio de pedidos:

@Service
public class OrderService {
    
    

    @Resource
    private OrderMapper orderMapper;
    @Resource
    private RestTemplate restTemplate;

    public Order queryOrderById(Long orderId) {
    
    
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 2.远程查询user
        // 2.1 url地址
        String url = "http://localhost:8081/user" + order.getUserId();
        // 2.2 发起调用
        User user = restTemplate.getForObject(url, User.class);
        // 3. 存入order
        order.setUser(user);
        // 4.返回
        return order;
    }
}

Luego reinicie los dos servicios nuevamente, y luego vaya al navegador para acceder al servicio de pedidos, y encontrará que también se consulta al usuario

inserte la descripción de la imagen aquí


Componentes y uso de microservicios

Registro Eureka

proveedor y consumidor

Al igual que en el caso distribuido anterior, cuando se necesita información de datos de otro módulo, se llama de forma remota al servicio del módulo correspondiente.En la relación de llamada de servicio, habrá dos roles diferentes: Proveedor de servicio: En una empresa, es utilizado por otro
micro El servicio invocado por el servicio. (Proporcionar interfaces a otros microservicios)

Consumidor de servicios : un servicio que llama a otros microservicios en una empresa. (interfaces de llamadas proporcionadas por otros microservicios)

Los roles de los proveedores de servicios y los consumidores de servicios no son absolutos, sino relativos al negocio.

El siguiente ejemplo es fácil de entender
Si el servicio A llama al servicio B y el servicio B llama al servicio C, ¿cuál es el papel del servicio B?

  • Para el negocio de A llamando a B: A es un consumidor de servicios, B es un proveedor de servicios
  • Para el negocio donde B llama a C: B es un consumidor de servicios y C es un proveedor de servicios

por lo tanto,El servicio B puede ser un proveedor de servicios o un consumidor de servicios.


La estructura y función de Eureka

Si el proveedor de servicios implementa varias instancias , se producirán los siguientes problemas cuando se llame al servicio de forma remota:

  • Cuando el servicio de pedidos inicia una llamada remota, ¿cómo sabe la dirección IP y el puerto de la instancia de servicio de usuario?
  • Hay varias direcciones de instancia de servicio de usuario, ¿cómo elegir al llamar al servicio de pedido?
  • ¿Cómo sabe order-service si una determinada instancia de servicio de usuario todavía está en buen estado o no?

Bajo esta estructura de proyecto clúster, Eureka está obligada a venir


Eureka es el registro en SpringCloud, y la estructura de registro más conocida
es la siguiente

inserte la descripción de la imagen aquí

Contesta las preguntas anteriores.

Pregunta 1: ¿Cómo sabe order-service la dirección de la instancia de user-service?

El proceso de obtención de la información de la dirección es el siguiente:

  • Después de iniciar la instancia de servicio de servicio de usuario, registre su propia información con eureka-server (servidor Eureka). Esto se llama registro de servicio.
  • eureka-server guarda la relación de mapeo entre el nombre del servicio y la lista de direcciones de la instancia del servicio
  • order-service extrae la lista de direcciones de la instancia según el nombre del servicio. Esto se llama descubrimiento de servicios o extracción de servicios.

Pregunta 2: ¿Cómo selecciona el servicio de pedidos una instancia específica de varias instancias de servicio de usuario?

  • order-service selecciona una dirección de instancia de la lista de instancias utilizando un algoritmo de equilibrio de carga (como round robin, random, weight)
  • Iniciar una llamada remota a la dirección de la instancia

Pregunta 3: ¿Cómo sabe el servicio de pedidos si una determinada instancia de servicio de usuario todavía está en buen estado o está inactiva?

  • El servicio de usuario iniciará una solicitud al servidor eureka de vez en cuando (predeterminado 30 segundos) para informar su propio estado, que se llama latido del corazón
  • Cuando no se envía ningún latido durante más de un cierto período de tiempo, eureka-server considerará que la instancia de microservicio es defectuosa y la eliminará de la lista de servicios.
  • Cuando el servicio de pedidos extrae el servicio, se puede descartar la instancia defectuosa

Nota: un microservicio puede ser tanto un proveedor de servicios como un consumidor de servicios, por lo que eureka encapsula funciones como el registro de servicios y el descubrimiento de servicios en el cliente eureka.


Construir el servicio Eureka

1. Introducir la dependencia de eureka

Servidor de registro: eureka-server, que debe ser un microservicio independiente (subproyecto independiente, se recomienda crear un proyecto maven, no tengo problema si desea usar el arranque), solo agregue eureka a su archivo pom Solo confíe en él, otras cosas como la información de la versión y otras dependencias se agregan en el proyecto principal, hereda las dependencias del proyecto principal

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

2. Escribe la clase de inicio

Para escribir una clase de inicio para el servicio del servidor eureka, asegúrese de agregar una anotación @EnableEurekaServer para habilitar la función del centro de registro de eureka:

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

3. Escribir archivos de configuración

Escriba un archivo application.yml en la carpeta de recursos

server:
  port: 10086
spring:
  application:
    name: eureka-server
eureka:
  client:
    service-url: 
      defaultZone: http://127.0.0.1:10086/eureka

4. Iniciar el servicio

Una vez completada la configuración, puede iniciar el servicio para ver si la compilación es exitosa, visite http://localhost:10086/

inserte la descripción de la imagen aquí


servicio de registro

1. Introducir dependencias

A diferencia de la dependencia de la creación del servicio eureka anterior, esta vez se inyecta el cliente

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

Nota: Introduzca esta dependencia en el archivo pom del proveedor de servicios

2. Archivo de configuración

En el servicio de usuario del proveedor de servicios, modifique el archivo application.yml, agregue el nombre del servicio, la dirección del servicio eureka

spring:
  application:
    name: userservice
eureka:
  client:
    service-url:
      defaultZone: http://localhost:10086/eureka

Inicie varias instancias de servicio de usuario (opcional)

Aquí se muestra la llamada remota de la estrategia de sondeo cuando un servicio tiene varias instancias, agregamos una configuración de inicio de SpringBoot y luego iniciamos un servicio de usuario.

Primero, copie la configuración de inicio del servicio de usuario original:

inserte la descripción de la imagen aquí

Luego, en la ventana emergente, realice la configuración:

inserte la descripción de la imagen aquí

Ahora, aparecerán dos configuraciones de inicio de servicio de usuario en la ventana de SpringBoot, la primera es el puerto 8081 y la segunda es el puerto 8082.
Inicie la instancia de servidor de usuario recién agregada

inserte la descripción de la imagen aquí

Ahora visite http://localhost:10086 para ver si el servicio se ha registrado correctamente

inserte la descripción de la imagen aquí


descubrimiento de servicios

Modificar la lógica de order-service:Obtenga información de servicio de usuario de eureka-server para realizar el descubrimiento de servicios.

1. Introducir dependencias

El descubrimiento de servicios y el registro de servicios están todos encapsulados en las dependencias eureka-client , por lo que este paso es coherente con el registro de servicios.

En el archivo pom de order-service, introduzca las siguientes dependencias de eureka-client:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2. Archivo de configuración

El descubrimiento de servicios también necesita conocer la dirección eureka, por lo que el segundo paso es coherente con el registro del servicio, que consiste en configurar la información eureka:

En order-service, modifique el archivo application.yml y agregue el nombre del servicio y la dirección eureka:

spring:
  application:
    name: orderservice
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka

3. Servicio de extracción y balanceo de carga

Finalmente, extraeremos la lista de instancias del servicio de servicio de usuario de eureka-server e implementaremos el equilibrio de carga.

En OrderApplication del servicio de pedidos del consumidor del servicio, agregue una anotación @LoadBalanced al Bean RestTemplate: estrategia de sondeo

inserte la descripción de la imagen aquí

Modifique el método queryOrderById en la clase OrderService en el servicio de servicio de pedidos. Modifique la ruta de la URL para acceder y use el nombre del servicio en lugar de ip y puerto :

inserte la descripción de la imagen aquí

Spring nos ayudará automáticamente a obtener la lista de instancias del lado del servidor eureka de acuerdo con el nombre del servicio userservice, y luego completará el equilibrio de carga.


4. Resultados finales de la prueba

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Llamó con éxito al servicio de atención al usuario de forma remota para consultar la información del usuario


Resumen del servicio de registro de Eureka

1. Construir servidor Eureka

  • Introducir la dependencia del servidor eureka
  • Agregue la anotación @EnableEurekaServer Configure la dirección eureka en application.yml

2. registro de servicio

  • Introducir la dependencia del cliente eureka
  • Configure la dirección eureka en application.yml

3. descubrimiento de servicios

  • Introducir la dependencia del cliente eureka
  • Configure la dirección eureka en application.yml
  • Agregue la anotación @LoadBalanced a RestTemplate Llamada remota con el nombre de servicio del proveedor de servicios

Principio de equilibrio de carga de la cinta

Listón (homofónico: Ruiben), me temo que mi lectura no es estándar, por favor recuerda

Después de realizar el registro del servicio Eureka arriba, el servicio se extrae automáticamente y se completa el equilibrio de carga. Luego, cuándo extraer automáticamente, cuándo equilibrar la carga, exploremos el principio del equilibrio de carga

Principio de equilibrio de carga

1. Cuando un consumidor de servicios inicia una solicitud de servicio de llamadas remotas


2. LoadBalancerIntercepor interceptará la solicitud
y hará varias cosas:

  • request.getURI(): obtenga el uri de solicitud, en este caso es http://user-service/user/8
  • originalUri.getHost(): obtenga el nombre de host de la ruta uri, que en realidad es la identificación del servicio, es deciruser-service
  • this.loadBalancer.execute(): ID de servicio de proceso y solicitudes de usuario.

3. El siguiente paso del punto de interrupción es continuar con el seguimiento del método de ejecución anterior (este paso completa la adquisición de los servicios correspondientes registrados en eureka y la estrategia de equilibrio de carga especificada)

inserte la descripción de la imagen aquí

  • getLoadBalancer(serviceId): obtenga ILoadBalancer de acuerdo con la identificación del servicio, y LoadBalancer llevará la identificación del servicio a eureka para obtener la lista de servicios y guardarla.
  • getServer(loadBalancer): use el algoritmo de equilibrio de carga integrado para seleccionar uno de la lista de servicios. En este ejemplo, puede ver que se ha obtenido el servicio en el puerto 8082

4. Estrategia de equilibrio de carga IRule
En el código anterior, puede ver que la obtención de servicios utiliza un getServermétodo para equilibrar la carga:

El siguiente es el seguimiento del código fuente, siga hasta el final y vea quién nos está ayudando con el equilibrio de carga

inserte la descripción de la imagen aquí

Finalmente, el siguiente es un diagrama de flujo de equilibrio de carga,Este diagrama facilitará la comprensión del proceso de llamar al equilibrio de carga desde la solicitud de servicios remotos

inserte la descripción de la imagen aquí

El proceso básico es el siguiente :

  • Interceptar nuestra solicitud RestTemplate http://userservice/user/1
  • RibbonLoadBalancerClient obtendrá el nombre del servicio de la URL de solicitud, que es servicio de usuario
  • DynamicServerListLoadBalancer extrae la lista de servicios de eureka según el servicio de usuario
  • eureka devuelve la lista, localhost:8081, localhost:8082
  • IRule usa reglas de equilibrio de carga integradas, seleccione una de la lista, como localhost: 8081
  • RibbonLoadBalancerClient modifica la dirección de la solicitud, reemplaza el servicio de usuario con localhost:8081, obtiene http://localhost:8081/user/1 e inicia una solicitud real

estrategia de equilibrio de carga

Las reglas de equilibrio de carga de Ribbon están definidas por una interfaz llamada IRule, y cada subinterfaz es una regla :

inserte la descripción de la imagen aquí

Los significados de las diferentes reglas son los siguientes:

Clase de regla de equilibrio de carga integrada Descripción de la regla
Regla de todos contra todos Simplemente sondee la lista de servicios para seleccionar un servidor. Es la regla de equilibrio de carga predeterminada de Ribbon.
DisponibilidadRegla de filtradoDisponibilidadRegla de filtrado Ignore los siguientes dos servidores: (1) De forma predeterminada, si este servidor no se conecta 3 veces, este servidor se establecerá en el estado de "cortocircuito". El estado de cortocircuito tendrá una duración de 30 segundos, y si la conexión vuelve a fallar, la duración del cortocircuito aumentará geométricamente. (2) Servidores con concurrencia demasiado alta. Si el número de conexiones simultáneas de un servidor es demasiado alto, el cliente configurado con la regla AvailabilityFilteringRule también lo ignorará. El límite superior del número de conexiones simultáneas se puede configurar mediante la propiedad ..ActiveConnectionsLimit del cliente.
Regla de tiempo de respuesta ponderada Asigne un valor de peso a cada servidor. Cuanto mayor sea el tiempo de respuesta del servidor, menos peso tendrá este servidor. Esta regla seleccionará aleatoriamente un servidor y este valor de ponderación afectará la selección del servidor.
Regla de evitación de zona La selección del servidor se basa en los servidores disponibles en la región. Use Zona para clasificar los servidores, esta Zona puede entenderse como una sala de cómputo, un rack, etc. Luego sondee múltiples servicios en la Zona.
Mejor regla disponible Ignore los servidores que están en cortocircuito y elija servidores con menor simultaneidad.
Regla aleatoria Seleccione aleatoriamente un servidor disponible.
regla de reintento Lógica de selección para el mecanismo de reintento

La implementación predeterminada es ZoneAvoidanceRule, que es un esquema de sondeo


Estrategia de equilibrio de carga personalizada

Las reglas de equilibrio de carga se pueden modificar definiendo la implementación de IRule.Hay dos formas:

  1. Método de código: en la clase OrderApplication (clase de inicio) en el servicio de pedidos, defina una nueva IRule:
@Bean
public IRule randomRule(){
    
    
    return new RandomRule();
}

Esta es una configuración global, y el servicio de pedidos seguirá la estrategia de esta configuración cuando llame a otros microservicios.


2. Método del archivo de configuración: en el archivo application.yml de order-service, agregar nuevas configuraciones también puede modificar las reglas:

userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则 

La configuración agregada en el archivo yml solo es válida para el microservicio actual y es una configuración local

Tenga en cuenta que las reglas de equilibrio de carga predeterminadas generalmente se usan sin modificaciones.


carga lenta

Ribbon usa la carga diferida de forma predeterminada, es decir, LoadBalanceClient se crea solo cuando se accede a él por primera vez, y el tiempo de solicitud será muy largo.

La carga de hambre se creará cuando el proyecto comience a reducir el tiempo que lleva la primera visita Habilite la carga de hambre a través de la siguiente configuración:

ribbon:
  eager-load:
    enabled: true
    clients: userservice

Centro de Registro de Nacos

Dado que las empresas nacionales generalmente respetan la tecnología de Alibaba, como el centro de registro, SpringCloudAlibaba también lanzó un centro de registro llamado Nacos, que tiene más funciones y es más utilizado que Eureka.

Saber instalar nacos

Descarga de nacos1.4.1: descarga de nacos
Código de extracción: olww
Una vez completada la descarga, en el directorio bin, escriba cmd para comenzar

inserte la descripción de la imagen aquí

Ingrese el siguiente comando, porque es un inicio de clúster de forma predeterminada, aquí está configurado para un inicio único

startup.cmd -m standalone

inserte la descripción de la imagen aquí

El navegador se mantiene actualizado con esta dirección
http://localhost:8848/nacos/index.html

El usuario y la contraseña son ambos nacos, inicia sesión

inserte la descripción de la imagen aquí


Inicio rápido de Nacos

1.父工程导入SpringCloudAlibaba的依赖

<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>

2.在user-service和order-service中的pom文件中引入nacos-discovery依赖

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

Recuerde comentar la dependencia original de eureka

3.配置nacos地址
Agregue la configuración de nacos al archivo yml del proyecto que importa las dependencias de nacos

spring:
  cloud:
    nacos:
      server-addr: localhost:8848

4.启动服务,然后再前面打开的nacos网页中查看

inserte la descripción de la imagen aquí


Modelo de almacenamiento jerárquico del servicio Nacos

En general, las grandes fábricas crearán clústeres para la recuperación ante desastres para garantizar que cuando el servicio local esté inactivo, aún pueda operar normalmente (acceder a los servicios en otro lugar).Por ejemplo,
cuando su servidor de Hangzhou falla y causa un tiempo de inactividad, entonces accederá al servicio. en Shanghai por venir Garantizar el funcionamiento normal de la función
es un poco como un neumático de repuesto para los demás

Nacos divide las instancias en la misma sala de computadoras en un clúster .
El servicio de usuario es un servicio. Un servicio puede contener varios clústeres, como Hangzhou y Shanghái. Cada clúster puede tener varias instancias para formar un modelo jerárquico . ——> De hecho, se divide enServicio - Clúster - InstanciaCuando estas tres capas
inserte la descripción de la imagen aquí
de microservicios acceden entre sí, deben acceder a la misma instancia de clúster tanto como sea posible, porque la velocidad de acceso local es más rápida. Solo acceda a otros clústeres cuando el clúster no esté disponible

Configurar el clúster para el servicio

Agregar al archivo de configuración yml

inserte la descripción de la imagen aquí
nombre aleatorio


Estrategia de equilibrio de carga NacosRule

userservice:
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则 

①Seleccione primero la lista de instancias de servicio del mismo clúster
. ②Si el clúster local no puede encontrar un proveedor, vaya a otros clústeres para encontrarlo y se emitirá una advertencia. ③Después de confirmar
la lista de instancias disponibles, use el equilibrio de carga aleatorio para seleccionar instancias .


Equilibrio de carga de peso

En la implementación real, aparecerá un escenario de este tipo:

El rendimiento de los equipos del servidor es diferente. Algunas instancias tienen un mejor rendimiento, mientras que otras tienen un rendimiento más bajo. Esperamos que las máquinas con un mejor rendimiento puedan soportar más solicitudes de los usuarios.

Pero por defecto, NacosRule se selecciona aleatoriamente en el mismo clúster, sin tener en cuenta el rendimiento de la máquina.
Pero debemos considerar que aquellos que pueden hacer más trabajo, por lo que viene la configuración del peso. De acuerdo con diferentes configuraciones de peso, se puede controlar la frecuencia de las visitas. A mayor peso, mayor frecuencia de visitas .

Cuando el peso sea 0, no habrá acceso a través del servidor

En el pasado, si un servicio necesita actualizarse y actualizarse, el servicio debe reiniciarse, pero es imposible actualizarlo a plena luz del día, lo que genera fallas en el acceso de los usuarios y, a menudo, actualizan en secreto en la oscuridad de la noche. no conveniente.
Una de las funciones de la estrategia de ponderación es que cuando el proyecto se actualiza y mejora, se reduce la ponderación del servidor correspondiente y se pone a prueba a un pequeño número de usuarios para ver si se supera la función recién iniciada, de modo que para lograr una actualización sin problemas.
Por ejemplo, cierto juego a veces emite un anuncio y sigue actualizando el servidor, así es como surgió

Control de peso de instancia

①La consola de Nacos puede establecer el valor de peso de la instancia
②Múltiples instancias en el mismo clúster entre 0 y 1, cuanto mayor sea el peso, mayor será la frecuencia de acceso
③Si el peso se establece en 0, no se accederá en absoluto


Aislamiento del ambiente Nacos

De forma predeterminada, todos los servicios, datos y grupos se encuentran en el mismo espacio de nombres, el
Nacos público denominado proporciona un espacio de nombres para lograr el aislamiento ambiental.

  • Puede haber múltiples espacios de nombres en nacos
  • Puede haber grupo, servicio, etc. bajo el espacio de nombres
  • Los diferentes espacios de nombres están aislados entre sí., como los servicios en diferentes espacios de nombres son invisibles entre sí

La operación específica es la siguiente.

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí


Aislamiento del ambiente Nacos

El espacio de nombres se usa para el aislamiento del entorno, cada espacio de nombres tiene una identificación única y los servicios en diferentes espacios de nombres son invisibles.


La diferencia entre Nacos y Eureka

Nacos (homofónico: Nagram 4); Eureka (homofónico: Yiruika) Mi propia lectura en inglés no es estándar, así que grábala, para que solo pueda leer la ortografía cuando hable con otros la próxima vez. ¿Hacer que los demás se vean confundidos y digan que usted y yo estamos hablando de la misma tecnología?

De vuelta a los negocios

Nacos envía activamente la lista de servicios registrados a los consumidores de servicios. Si un servicio está inactivo, inmediatamente enviará una nueva lista de servicios.
Eureka extrae regularmente la lista de servicios del centro de registro, por lo que su eficiencia de actualización de la lista de servicios es ligeramente inferior a eso. de Nacos.
inserte la descripción de la imagen aquí


Las instancias de servicio de Nacos se dividen en dos tipos:

  • Instancia temporal: si la instancia está inactiva durante más de un cierto período de tiempo (sin enviar activamente información de latido), se eliminará de la lista de servicios, el tipo predeterminado.

  • Instancia no temporal: nacos solicitará activamente la información de latido de la instancia. Si la instancia deja de funcionar, no se eliminará de la lista de servicios. También se le puede llamar instancia permanente.

Establecer el tipo de instancia en la configuración
inserte la descripción de la imagen aquí


resumen final

Nacos与eureka的共同点

  • Tanto el registro del servicio de soporte como la extracción del servicio
  • Ambos admiten el método de latido del proveedor de servicios para la detección del estado

Nacos与Eureka的区别

  • Nacos admite que el servidor detecte activamente el estado del proveedor: la instancia temporal adopta el modo de latido y la instancia no temporal adopta el modo de detección activa
  • Se eliminarán las instancias temporales con latidos cardíacos anormales, mientras que las instancias no temporales no se eliminarán
  • Nacos admite el modo de envío de mensajes de cambios en la lista de servicios, y la lista de servicios se actualiza más oportunamente
  • El clúster Nacos adopta el modo AP por defecto, cuando hay instancias no temporales en el clúster, se adopta el modo CP, Eureka adopta el modo AP

Configuración de gestión de Nacos

Gestión de configuración unificada

Escenas a utilizar

Cuando hay demasiados microservicios en un clúster, y hay miles o cientos de ellos, la información de configuración de uno de los microservicios debe cambiarse y los otros miles o cientos de servicios que llaman de forma remota al servicio deben reiniciarse. lo cual es casi imposible en un entorno de producción.

Por lo tanto, necesitamos una solución de gestión de configuración unificada que pueda gestionar de forma centralizada la configuración de todas las instancias.

inserte la descripción de la imagen aquí


inserte la descripción de la imagen aquí

Por un lado, Nacos puede administrar la configuración de forma centralizada y, por otro lado, cuando la configuración cambia, el microservicio puede ser notificado a tiempo para realizar una actualización en caliente de la configuración.


Agregar información de configuración

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

Nota: La configuración central del proyecto debe ser administrada por nacos solo cuando se requiere la configuración de actualización activa. Es mejor guardar algunas configuraciones que no se cambiarán localmente en el microservicio.


Extraer servicios de microservicios

El microservicio debe extraer la configuración administrada en nacos y fusionarla con la configuración application.yml local para completar el inicio del proyecto.

La información de configuración, como la dirección de nacos, está en applicationyml, pero si application.yml no se ha leído, cómo saber la dirección de nacos Entonces, Spring
introduce un nuevo archivo de configuración: el archivo bootstrap.yaml, que se leerá antes de la aplicación. selección de yml

inserte la descripción de la imagen aquí

1.导入Nacos配置管理依赖

<!--nacos配置管理依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

2.添加bootstrap.yaml
Luego, agregue un archivo bootstrap.yaml en la carpeta de recursos

spring:
  application:
    name: userservice # 服务名称
  profiles:
    active: dev #开发环境,这里是dev 
  cloud:
    nacos:
      server-addr: localhost:8848 # Nacos地址
      config:
        file-extension: yaml # 文件后缀名

Aquí se obtendrá la dirección de nacos según spring.cloud.nacos.server-addr, y luego se leerá la configuración correspondiente según nombre, activo y extensión
inserte la descripción de la imagen aquí

3.添加nacos配置并读取
Agregue la lógica comercial en UserController en el servicio de usuario y lea la configuración de pattern.dateformat agregada en Nacos:

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

Complete el formato de fecha de acuerdo con nuestro formato especificado y regrese

inserte la descripción de la imagen aquí

Indica que la información de configuración en Nacos se ha extraído con éxito


Configurar actualización en caliente

Después de cambiar el archivo de configuración en Nacos, el microservicio puede percibirlo sin reiniciar (es decir, actualizar la página web directamente actualizará la configuración). Se puede lograr mediante los siguientes dos métodos de configuración:

método uno

Agregue la anotación @RefreshScope a la clase donde se encuentra la variable inyectada por @Value:
inserte la descripción de la imagen aquí


forma dos

Utilice la anotación @ConfigurationProperties en lugar de la anotación @Value.

En el servicio de servicio al usuario, agregue una clase para leer la propiedad patternern.dateformat:

@Component
@Data
@ConfigurationProperties(prefix = "pattern")
public class PatternProperties {
    
    
    private String dateformat;
}

Use esta clase en lugar de @Value en UserController:

inserte la descripción de la imagen aquí


compartir configuración

Algunas propiedades tienen el mismo valor en múltiples entornos, como desarrollo y pruebas. Para evitar modificar el valor de la configuración, se requiere una modificación una por una; se cita el método de uso compartido de la configuración y se coloca la misma configuración en la configuración compartida. Como una variable estática pública modificada en una clase

Cuando se inicia el microservicio, irá a nacos para leer varios archivos de configuración, por ejemplo:

  • [spring.application.name]-[spring.profiles.active].yaml, por ejemplo: userservice-dev.yaml

  • [spring.application.name].yaml, por ejemplo: userservice.yaml

No[spring.application.name].yaml contiene entornos, por lo que varios entornos pueden compartirlo.

Prioridad de configuración
Configuración remota dedicada > configuración remota compartida > configuración local

inserte la descripción de la imagen aquí


Cree un clúster de Nacos

En la etapa de aprendizaje, no hay tantas máquinas, por lo que solo podemos hacer una versión simplificada y configurar los servicios en la local.

Premisa: cree un clúster mysql, inicialice la tabla de la base de datos y solo use una base de datos mysql si las condiciones son limitadas

①Descomprima el paquete comprimido nacos
inserte la descripción de la imagen aquí

②Ingrese al directorio conf de nacos, modifique el archivo de configuración cluster.conf.example y cámbiele el nombre a cluster.conf:

inserte la descripción de la imagen aquí
③ Luego agregue contenido: (Debido a que solo se asignan tres servidores localmente y no hay tres servidores, por lo que todos son IP locales y el puerto se puede seleccionar si no se usa)

inserte la descripción de la imagen aquí

127.0.0.1:8845
127.0.0.1.8846
127.0.0.1.8847

④ Modifique el archivo application.properties y agregue la configuración de la base de datos

inserte la descripción de la imagen aquí

⑤ Copie la carpeta nacos tres veces y luego modifique application.properties en las tres carpetas respectivamente,
inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

nacos1:

server.port=8845

nacos2:

server.port=8846

nacos3:

server.port=8847

⑥ Luego inicie tres nodos nacos,

Es el archivo startup.cmd en el directorio bin, porque inicia el clúster de forma predeterminada, simplemente haga doble clic en él.

⑦Usar nginx para proxy inverso

Modifique el archivo conf/nginx.conf, la configuración es la siguiente:
Simplemente cópielo directamente

upstream nacos-cluster {
    
    
    server 127.0.0.1:8845;
	server 127.0.0.1:8846;
	server 127.0.0.1:8847;
}

server {
    
    
    listen       80;
    server_name  localhost;

    location /nacos {
    
    
        proxy_pass http://nacos-cluster;
    }
}

⑧ La configuración del archivo application.yml en el código es la siguiente:

spring:
  cloud:
    nacos:
      server-addr: localhost:80 # Nacos地址

En este momento, la nueva configuración creada en nacos se almacenará en la base de datos para completar la persistencia.

mejoramiento

  • En la implementación real, es necesario establecer un nombre de dominio para el servidor nginx que actúa como un proxy inverso, de modo que no sea necesario cambiar la configuración del cliente nacos si el servidor se migra más adelante.

  • Cada nodo de Nacos debe implementarse en varios servidores diferentes para recuperación ante desastres y aislamiento.


Fingir llamada remota

El registro del servicio se completa antes, y el centro de configuración nacos está relacionado, pero la parte de la extracción del servicio es usar RestTemplate

El código que usó RestTemplate para iniciar una llamada remota antes:
inserte la descripción de la imagen aquí
Existen los siguientes problemas:

• Mala legibilidad del código y experiencia de programación inconsistente

• Las URL con parámetros complejos son difíciles de mantener


Feign es un cliente http declarativo, su función es ayudarnos a implementar elegantemente el envío de solicitudes http y resolver los problemas mencionados anteriormente.


Fingir reemplaza RestTemplate

①引入Feign依赖
Introduzca la dependencia fingida en el archivo pom:

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

②添加注解
Agregue anotaciones a la clase de inicio para habilitar la funcionalidad de Fingir:

inserte la descripción de la imagen aquí
③编写Feign的客户端
El siguiente es un ejemplo del servicio de pedidos de la demostración anterior

@FeignClient("userservice")
public interface UserClient {
    
    
    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}

Este cliente se basa principalmente en anotaciones SpringMVC para declarar información de llamadas remotas, como:

  • Nombre del servicio: servicio de usuario
  • Método de solicitud: OBTENER
  • Ruta de solicitud: /usuario/{id}
  • Parámetro de solicitud: identificación larga
  • Tipo de valor de retorno: Usuario

De esta forma, Feign puede ayudarnos a enviar solicitudes http sin usar RestTemplate para enviarlas nosotros mismos.

④在业务方法中替换以前的RestTemplate
No agregará URL al código comercial como antes, la legibilidad es muy baja y el código no es conciso
inserte la descripción de la imagen aquí

Finalmente, puede ver que la llamada remota también se completa al final, y el código es más conciso. Al mismo tiempo, después de algunos intentos más, encontrará que fingir no solo realiza la extracción del servicio, sino que también realiza el equilibrio de carga.

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

⑤总结

Pasos para usar Fingir:

① Introducir dependencia

② Agregue la anotación @EnableFeignClients

③ Escribir la interfaz FeignClient

④ Use el método definido en FeignClient en lugar de RestTemplate


configuración personalizada

Fingir puede admitir muchas configuraciones personalizadas, como se muestra en la siguiente tabla:

tipo efecto ilustrar
fingir.Logger.Level Modificar nivel de registro Contiene cuatro niveles diferentes: NINGUNO, BÁSICO, ENCABEZADOS, COMPLETO
fingir.códec.Decodificador Analizador del resultado de la respuesta Analizar los resultados de llamadas remotas http, como analizar cadenas json en objetos java
fingir.códec.codificador codificación de parámetros de solicitud Codifique los parámetros de solicitud para enviar a través de solicitudes http
fingir. Contrato Formatos de anotación admitidos El valor predeterminado es la anotación de SpringMVC.
fingir. reintentador Mecanismo de reintento fallido El mecanismo de reintento en caso de falla de la solicitud, el valor predeterminado es no, pero se usará el reintento de Ribbon

En circunstancias normales, el valor predeterminado es suficiente para que lo usemos. Si desea personalizarlo, solo necesita crear un @Bean personalizado para anular el Bean predeterminado.


método de archivo de configuración

La modificación del nivel de registro de fingir en función del archivo de configuración puede apuntar a un solo servicio:

feign:  
  client:
    config: 
      userservice: # 针对某个微服务的配置
        loggerLevel: FULL #  日志级别 

También es posible apuntar a todos los servicios:

feign:  
  client:
    config: 
      default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
        loggerLevel: FULL #  日志级别 

Método de código Java

También puede modificar el nivel de registro en función del código Java, primero declarar una clase y luego declarar un objeto Logger.Level:

public class DefaultFeignConfiguration  {
    
    
    @Bean
    public Logger.Level feignLogLevel(){
    
    
        return Logger.Level.BASIC; // 日志级别为BASIC
    }
}

Si desea que tenga efecto globalmente , colóquelo en la anotación @EnableFeignClients de la clase de inicio:

@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class) 

Si es efectivo localmente , póngalo en la anotación @FeignClient correspondiente:

@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration .class) 

El nivel de registro se divide en cuatro tipos:

  • NINGUNO: no registra ninguna información de registro, que es el valor predeterminado.
  • BÁSICO: solo registra el método de solicitud, la URL, el código de estado de respuesta y el tiempo de ejecución
  • ENCABEZADOS: Sobre la base de BASIC, la información del encabezado de la solicitud y la respuesta se registra adicionalmente
  • COMPLETO: registre los detalles de todas las solicitudes y respuestas, incluida la información del encabezado, el cuerpo de la solicitud y los metadatos.

Puede usar COMPLETO al depurar errores, pero generalmente use NINGUNO y BÁSICO


Fingir optimización del rendimiento

La capa inferior de Fingir inicia solicitudes http y se basa en otros marcos. Su implementación de cliente subyacente incluye:

• URLConnection: la implementación predeterminada no admite la agrupación de conexiones, por lo que el rendimiento no es muy bueno, porque la agrupación de conexiones puede reducir la pérdida de conexión de la creación y destrucción de la conexión (porque cada conexión requiere tres apretones de manos y cuatro manos agitadas)

• Apache HttpClient: grupo de conexiones de soporte

• OKHttp: grupo de conexiones de soporte

Por lo tanto, el medio principal para mejorar el rendimiento de Fingir es utilizar el conjunto de conexiones en lugar de la conexión URL predeterminada.

HttpClient de Apache se usa aquí para demostrar.

①引入依赖

<!--httpClient的依赖 -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

②配置文件中做相应的配置

feign:
  client:
    config:
      default: # default全局的配置
        loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
  httpclient:
    enabled: true # 开启feign对HttpClient的支持
    max-connections: 200 # 最大的连接数
    max-connections-per-route: 50 # 每个路径的最大连接数

En resumen, la optimización de Fingir:

1. Trate de usar básico como nivel de registro

2. Use HttpClient u OKHttp en lugar de URLConnection

  • ① Introducir la dependencia de fingir-httpClient

  • ② El archivo de configuración habilita la función httpClient y establece los parámetros del grupo de conexiones


Mejores prácticas para fingir

La mejor práctica es la experiencia resumida por los predecesores después de pisar constantemente el foso, y también es la mejor manera de usar Fingir

fingir cliente:
inserte la descripción de la imagen aquíUserController:
inserte la descripción de la imagen aquí

La observación muestra que el cliente de Feign es muy similar al código del controlador del proveedor de servicios Para simplificar esta escritura de código repetitiva, hay dos métodos de implementación a continuación

Herencia

El mismo código se puede compartir a través de la herencia:

1) Defina una interfaz API, use el método de definición y haga una declaración basada en las anotaciones de SpringMVC.

2) Tanto el cliente de Fingir como el Controlador integran la interfaz

inserte la descripción de la imagen aquí

ventaja:

  • simple y fácil
  • compartir código

defecto:

  • El proveedor de servicios y el consumidor de servicios están estrechamente relacionados

  • La asignación de anotaciones en la lista de parámetros no se heredará, por lo que el método, la lista de parámetros y la anotación deben declararse nuevamente en el controlador.


Método de extracción

Extraiga el cliente de Fingir como un módulo independiente y coloque el POJO relacionado con la interfaz y la configuración predeterminada de Fingir en este módulo y proporciónelo a todos los consumidores.

Por ejemplo, las configuraciones predeterminadas de UserClient, User y Feign se extraen en un paquete feign-api, y todos los microservicios se pueden usar directamente haciendo referencia a este paquete de dependencia.

inserte la descripción de la imagen aquí
Desventajas: Algunas dependencias que no son requeridas por los servicios también se introducen de manera uniforme

Resumir
Mejores prácticas para Fingir:
①让controller和FeignClient继承同一接口

②将FeignClient、POJO、Feign的默认配置都定义到一个项目中,供所有消费者使用


Código

La siguiente es la implementación del segundo método - extracción

El primer paso es crear un módulo de fingir como una API unificada y copiar UserClient, User y DefaultFeignConfiguration escritos en el servicio de pedidos en la demostración anterior en el proyecto de fingir-api.

inserte la descripción de la imagen aquí


El segundo paso es introducir la dependencia inicial de fingir en fingir-api

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

En el tercer paso, puede eliminar la clase de entidad en el servicio de pedido anterior y el cliente de fingir, e importar el módulo eign-api recién escrito en su archivo pom.

inserte la descripción de la imagen aquí

Modifique todas las partes de importación del paquete relacionadas con los tres componentes anteriores en el servicio de pedidos y cámbielo para importar el paquete en fingir-api


El cuarto paso es inyectar en el contenedor Spring

Cuando el FeignClient definido no está dentro del alcance del paquete de escaneo de SpringBootApplication, estos FeignClients no se pueden usar. Hay dos formas de resolverlo:
Método 1: Especifique el paquete donde se encuentra FeignClient

@EnableFeignClients(basePackages = "cn.itcast.feign.clients")

Método 2: especificar el código de bytes de FeignClient

@EnableFeignClients(clients = {
    
    UserClient.class})

Generalmente se recomienda usar el segundo tipo, golpe preciso.

inserte la descripción de la imagen aquí


Puerta de enlace de servicio de puerta de enlace

Conozca el Gateway primero

Gateway es el guardián de nuestros servicios y la entrada unificada de todos los microservicios.

Las tres funciones principales de la puerta de enlace son las siguientes

①Control de privilegios: como entrada de microservicios, la puerta de enlace debe verificar si el usuario es elegible para la solicitud e interceptarla si no.
②Enrutamiento y equilibrio de carga : todas las solicitudes deben pasar primero por la puerta de enlace, pero la puerta de enlace no procesa el negocio, sino que reenvía la solicitud a un microservicio de acuerdo con ciertas reglas. Este proceso se denomina enrutamiento. Por supuesto, cuando hay varios servicios de destino para el enrutamiento, también se requiere equilibrio de carga.
③Limitación : cuando el flujo de solicitudes es demasiado alto, la puerta de enlace liberará la solicitud de acuerdo con la velocidad que el microservicio descendente pueda aceptar para evitar una presión de servicio excesiva .

Hay dos tipos de implementaciones de puerta de enlace en Spring Cloud:

  • puerta
  • azul

Zuul es una implementación basada en Servlet y pertenece a la programación de bloqueo. Spring Cloud Gateway se basa en WebFlux proporcionado en Spring 5, que es una implementación de programación receptiva y tiene un mejor rendimiento.


Inicio rápido de puerta de enlace

Para realizar la función básica de enrutamiento de la puerta de enlace, los pasos básicos son los siguientes:

  1. Cree una puerta de enlace de proyecto SpringBoot e introduzca dependencias de puerta de enlace
  2. Escribir clase de inicio
  3. Escribir reglas básicas de configuración y enrutamiento
  4. Inicie el servicio de puerta de enlace para la prueba

Código

1.创建一个gateway模块作为服务,引入gateway和nacos服务发现依赖

Se recomienda crear un proyecto maven, si desea cambiar la versión del proyecto de arranque

<!--网关-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos服务发现依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2.在gateway模块中编写启动类

@SpringBootApplication
public class GatewayApplication {
    
    

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

3.配置yml文件,给其添加对应配置信息

server:
  port: 10010 # 网关端口
spring:
  application:
    name: gateway # 服务名称
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos地址
    gateway:
      routes: # 网关路由配置
        - id: user-service # 路由id,自定义,只要唯一即可
          # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
          uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
          predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
            - Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求

PathProxy todas urilas solicitudes que coincidan con las reglas a la dirección especificada por el parámetro.

Hacemos proxy de la solicitud /user/**que comienza con lb://userservice, lb es balanceo de carga y extraemos la lista de servicios de acuerdo con el nombre del servicio para lograr el balanceo de carga.


4.启动网关服务,访问网关服务端口,测试结果如下图,可以通过网关然后访问到服务

inserte la descripción de la imagen aquí
Error 503
La nueva versión de nacos debe agregar la dependencia spring-cloud-starter-loadbalancer para reemplazar la cinta


Diagrama de flujo del enrutamiento de la puerta de enlace

inserte la descripción de la imagen aquí


Finalmente, resuma los pasos del proceso.

Pasos de construcción de la puerta de enlace:

  1. Cree un proyecto, presente el descubrimiento de servicios de nacos y las dependencias de la puerta de enlace

  2. Crear una clase de inicio GatewayApplication

  3. Configure application.yml, incluida la información básica del servicio, la dirección de nacos, el enrutamiento


La configuración de enrutamiento incluye:

  1. ID de ruta: el identificador único de la ruta (generalmente el nombre del servicio, pero no se repite)

  2. Destino de enrutamiento (uri): la dirección de destino del enrutamiento, http significa dirección fija, lb significa equilibrio de carga según el nombre del servicio

  3. Aserciones de enrutamiento (predicados): reglas para juzgar el enrutamiento,

  4. Filtros de ruta (filtros): procesar la solicitud o respuesta


fábrica de afirmaciones

Las reglas de aserción que escribimos en el archivo de configuración son solo cadenas, que serán leídas y procesadas por Predicate Factory, y convertidas en condiciones de juicio de enrutamiento. Por ejemplo,
Path=/user/** se compara de acuerdo con la ruta

Afirmación(afirmación): Es una especie de lógica de primer orden en el programa (como: una fórmula de juicio lógico que el resultado es verdadero o falso), el propósito es expresar y verificar el resultado esperado del desarrollador de software - cuando el el programa se ejecuta en la posición de la afirmación, la afirmación correspondiente debe ser verdadera. Si la afirmación no es verdadera, el programa abortará la ejecución y dará un mensaje de error.

La lengua vernácula es el juicio, el valor de retorno es verdadero o falso

Hay más de una docena de fábricas de afirmaciones en SpringCloudGateway:

nombre ilustrar ejemplo
Después es una solicitud después de un cierto punto en el tiempo - Después=2037-01-20T17:42:47.789-07:00[América/Denver]
Antes es una solicitud antes de algún punto en el tiempo - Antes=2031-04-13T15:14:47.433+08:00[Asia/Shanghái]
Entre es una solicitud antes de ciertos dos puntos en el tiempo - Entre=2037-01-20T17:42:47.789-07:00[América/Denver], 2037-01-21T17:42:47.789-07:00[América/Denver]
Galleta Las solicitudes deben contener ciertas cookies - Galleta=chocolate, cap.
Encabezamiento Las solicitudes deben contener ciertos encabezados - Encabezado=X-Solicitud-Id, \d+
Anfitrión La solicitud debe ser para acceder a un cierto host (nombre de dominio) - Host= .algúnhost.org, .otrohost.org
Método El método de solicitud debe ser especificado - Método=OBTENER,POST
Camino La ruta de la solicitud debe cumplir con las reglas especificadas - Ruta=/rojo/{segmento},/azul/**
Consulta Los parámetros de la solicitud deben contener los parámetros especificados. - Consulta=nombre, Jack o - Consulta=nombre
DirecciónRemota La ip del solicitante debe estar en el rango especificado - Dirección remota = 192.168.1.1/24
Peso procesamiento de peso

No necesita memorizarlo, puede verificarlo a medida que lo usa y no puede recordarlo. En general, solo necesita dominar el proyecto de enrutamiento de Path

Resumir:

¿Cuál es el papel de PredicateFactory?

Lea las condiciones de aserción definidas por el usuario y juzgue las solicitudes

¿Qué significa Ruta=/usuario/**?

Si la ruta comienza con /usuario, se considera que cumple


fábrica de filtros

GatewayFilter es un filtro provisto en la puerta de enlace, que puede procesar las solicitudes que ingresan a la puerta de enlace y las respuestas devueltas por los microservicios:
inserte la descripción de la imagen aquí

Tipos de filtros de ruta

Spring proporciona 31 fábricas de filtros de ruta diferentes. Los siguientes son varios filtros comunes:

nombre ilustrar
AddRequestHeader Agregar un encabezado de solicitud a la solicitud actual
Quitar encabezado de solicitud Eliminar un encabezado de solicitud de la solicitud
Agregar encabezado de respuesta Agregar un encabezado de respuesta al resultado de la respuesta
RemoveResponseHeader 从响应结果中移除有一个响应头
RequestRateLimiter 限制请求的流量

这里以请求投过滤器为例,来写个案例示范

需求:给所有进入userservice的请求添加一个请求头:Hello World

只需要修改gateway服务的application.yml文件,添加路由过滤即可:

spring:
  cloud:
    gateway:
      routes:
      - id: user-service 
        uri: lb://userservice 
        predicates: 
        - Path=/user/** 
        filters: # 过滤器
        - AddRequestHeader=Head, Hello World # 添加请求头

inserte la descripción de la imagen aquí


测试效果

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

结果如下

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí


默认过滤器

上面加的过滤器是只针对对应的路由有效,若要像对所有路由都有效,就可以配置默认过滤器

如果要对所有的路由都生效,则可以将过滤器工厂写到default下

spring:
  cloud:
    gateway:
      routes:
      - id: user-service 
        uri: lb://userservice 
        predicates: 
        - Path=/user/**
      default-filters: # 默认过滤项
      - AddRequestHeader=Head, Hello World 

总结

过滤器的作用是什么?

① 对路由的请求或响应做加工处理,比如添加请求头

② 配置在路由下的过滤器只对当前路由的请求生效


defaultFilters的作用是什么?

对所有路由都生效的过滤器


全局过滤器

虽然默认过滤器已经实现了全局过滤路由的功能了,但是不能自定义,无法进行定制过滤

全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与GatewayFilter的作用一样。区别在于GatewayFilter通过配置定义,处理逻辑是固定的;而GlobalFilter的逻辑需要自己写代码实现。

定义方式是实现GlobalFilter接口。
在filter中编写自定义逻辑,可以实现下列功能:

  • 登录状态判断
  • 权限校验
  • 请求限流等

自定义全局过滤器

范例
需求:定义全局过滤器,拦截请求,判断请求的参数是否满足下面条件:

  • 参数中是否有authorization,

  • authorization参数值是否为admin

如果同时满足则放行,否则拦截

在gateway中定义一个过滤器:

这个@Order(-1)是指定过滤器执行的顺序,比如有很多过滤器时,这个就是指定谁先执行谁后执行,值越小,越先执行

@Order(-1)
@Component
public class AuthorizeFilter implements GlobalFilter {
    
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
    
        // 1.获取请求参数
        MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
        // 2.获取authorization参数
        String auth = params.getFirst("authorization");
        // 3.校验
        if ("admin".equals(auth)) {
    
    
            // 放行
            return chain.filter(exchange);
        }
        // 4.拦截
        // 4.1.禁止访问,设置状态码
        exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
        // 4.2.结束处理
        return exchange.getResponse().setComplete();
    }
}

结果如下图

inserte la descripción de la imagen aquí


过滤器执行顺序

请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter

Después de solicitar el enrutamiento, el filtro de enrutamiento actual, DefaultFilter y GlobalFilter se fusionarán en una cadena de filtros (colección), y cada filtro se ejecutará a su vez después de ordenar:

inserte la descripción de la imagen aquí
reglas de clasificación

  • Cada filtro debe especificar un valor de orden de tipo int, cuanto menor sea el valor de orden, mayor será la prioridad y mayor el orden de ejecución .
  • GlobalFilter especifica el valor del pedido implementando la interfaz Ordered o agregando la anotación **@Order**, que especificamos nosotros mismos
  • Spring especifica el orden de los filtros de enrutamiento y defaultFilter, y el valor predeterminado es aumentar desde 1 según el orden de declaración.
  • Cuando el valor de orden del filtro es el mismo, seguiráFiltro predeterminado > Filtro de ruta > Filtro globalejecutado en secuencia.

problemas entre dominios

Entre dominios: los nombres de dominio inconsistentes son entre dominios, e incluyen principalmente:

  • Diferentes nombres de dominio: www.taobao.com y www.taobao.org y www.jd.com y miaosha.jd.com

  • Mismo nombre de dominio, diferentes puertos: localhost:8080 y localhost8081

Problema de dominios cruzados: el navegador prohíbe al autor de la solicitud realizar solicitudes ajax de dominios cruzados con el servidor, y el navegador intercepta la solicitud.Solución
: CORS
CORS Explicación detallada


Resolver problemas entre dominios

En el archivo application.yml del servicio de puerta de enlace, agregue la siguiente configuración:

spring:
  cloud:
    gateway:
      globalcors: # 全局的跨域处理
        add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
        corsConfigurations:
          '[/**]':
            allowedOrigins: # 允许哪些网站的跨域请求 
              - "http://localhost:8090"
            allowedMethods: # 允许的跨域ajax的请求方式
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
              - "OPTIONS"
            allowedHeaders: "*" # 允许在请求中携带的头信息
            allowCredentials: true # 是否允许携带cookie
            maxAge: 360000 # 这次跨域检测的有效期

continuará

Por limitaciones de espacio, el uso y análisis del resto de componentes de los microservicios: Docker, MQ, ES se seguirá registrando en la siguiente parte. Gracias por leer

Supongo que te gusta

Origin blog.csdn.net/giveupgivedown/article/details/129270200
Recomendado
Clasificación