Gestión de configuración Spring Cloud Day2 Nacos, llamada remota Fingir y puerta de enlace del servicio Gateway

Artículos prácticos de Spring Cloud 02

0. Objetivos de aprendizaje

1. Gestión de la configuración de Nacos

Además de ser un centro de registro, Nacos también se puede utilizar para la gestión de la configuración.

1.1 Gestión de configuración unificada

Cuando se implementan más y más instancias de microservicios, llegando a decenas o cientos, modificar la configuración de los microservicios uno por uno hará que la gente se vuelva loca y propensa a errores. 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í

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

1.1.1 Agregar archivos de configuración en nacos

¿Cómo gestionar la configuración en nacos?
inserte la descripción de la imagen aquí

Luego complete la información de configuración en el formulario emergente:

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.

1.1.2 Extraer la configuración del microservicio

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.

Pero si aún no se ha leído application.yml, ¿cómo sabes la dirección de nacos?

Por lo tanto, Spring introduce un nuevo archivo de configuración: el archivo bootstrap.yaml, que se leerá antes que application.yml. El proceso es el siguiente:

inserte la descripción de la imagen aquí

1) Introducir la dependencia nacos-config

Primero, en el servicio de servicio al usuario, introduzca la dependencia del cliente de nacos-config:

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

2) Agrega bootstrap.yaml

Luego, agregue un archivo bootstrap.yaml en el servicio de usuario con el siguiente contenido:

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

Aquí, la dirección de nacos se obtendrá según spring.cloud.nacos.server-addr, y luego según

${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}Como ID de archivo, para leer la configuración.

En este ejemplo, es para leer userservice-dev.yaml:

inserte la descripción de la imagen aquí

3) Leer la configuración de nacos

Agregue la lógica comercial a UserController en el servicio de usuario, lea la configuración de pattern.dateformat:
inserte la descripción de la imagen aquí

Código completo:

package cn.itcast.user.web;

import cn.itcast.user.pojo.User;
import cn.itcast.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

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

    @Autowired
    private UserService userService;

    @Value("${pattern.dateformat}")
    private String dateformat;
    
    @GetMapping("now")
    public String now(){
    
    
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dateformat));
    }
    // ...略
}

1.2 Configurar actualización en caliente

Nuestro objetivo final es modificar la configuración en nacos, para que el microservicio pueda hacer que la configuración surta efecto sin reiniciar, es decir, configuración hot update .

Para lograr la actualización en caliente de la configuración, se pueden utilizar dos métodos:

1.2.1 Método 1

Agregue la anotación @RefreshScope a la clase donde se encuentra la variable inyectada por @Value:

1.2.2 Método 2

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:

package cn.itcast.user.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

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

Use esta clase en lugar de @Value en UserController:

Código completo:

package cn.itcast.user.web;

import cn.itcast.user.config.PatternProperties;
import cn.itcast.user.pojo.User;
import cn.itcast.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

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

    @Autowired
    private UserService userService;

    @Autowired
    private PatternProperties patternProperties;

    @GetMapping("now")
    public String now(){
    
    
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(patternProperties.getDateformat()));
    }

    // 略
}

1.3 Compartir configuración

De hecho, 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.

Probemos la configuración compartida a través del caso.

1) Agregar una configuración para compartir el entorno

Agregamos un archivo userservice.yaml en nacos:

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

2) Leer la configuración compartida en el servicio de usuario

En el servicio de servicio al usuario, modifique la clase PatternProperties para leer las propiedades recién agregadas:

inserte la descripción de la imagen aquí

En el servicio de servicio de usuario, modifique UserController y agregue un método:

inserte la descripción de la imagen aquí

3) Ejecute dos aplicaciones de usuario, utilizando diferentes perfiles

Modifique el elemento de inicio UserApplication2 y cambie su valor de perfil:

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

De esta forma, el perfil utilizado por UserApplication (8081) es dev, y el perfil utilizado por UserApplication2 (8082) es test.

Inicie UserApplication y UserApplication2

4) Configurar la prioridad de compartir

Cuando nacos y local de servicio tienen el mismo atributo al mismo tiempo, la prioridad se divide en alta y baja:

inserte la descripción de la imagen aquí

2. Fingir llamada remota

Primero veamos el código que usamos para iniciar llamadas remotas usando RestTemplate:

inserte la descripción de la imagen aquí

Hay 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

Fingir es un cliente http declarativo, dirección oficial: https://github.com/OpenFeign/feign

Su función es ayudarnos a implementar elegantemente el envío de solicitudes http y resolver los problemas mencionados anteriormente.
inserte la descripción de la imagen aquí

2.1 Fingir reemplaza RestTemplate

Los pasos para usar Fegin son los siguientes:

1) Introducir dependencias

Introducimos la dependencia fingida en el archivo pom del servicio de servicio de pedidos:

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

2) Agregar anotaciones

Agregue anotaciones a la clase de inicio de servicio de pedidos para habilitar la función de Fingir:

inserte la descripción de la imagen aquí

3) Escriba el cliente de Fingir

Crear una nueva interfaz en orden-servicio con el siguiente contenido:

package cn.itcast.order.client;

import cn.itcast.order.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

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

4) prueba

Modifique el método queryOrderById en la clase OrderService en el servicio de pedidos y use el cliente Fingir en lugar de RestTemplate:
inserte la descripción de la imagen aquí

¿No se ve más elegante?

5) Resumen

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

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

A continuación, se utilizan registros como ejemplo para demostrar cómo personalizar la configuración.

2.2.1 Método del 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 #  日志级别 

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.

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

2.3 Optimización del uso de fingir

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

•URLConnection: implementación predeterminada, no es compatible con el conjunto de conexiones

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

Aquí usamos HttpClient de Apache para demostrarlo.

1) Introducir dependencias

Introduzca la dependencia HttpClient de Apache en el archivo pom del servicio de pedidos:

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

2) Configurar el grupo de conexiones

Agregue la configuración en application.yml de order-service:

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

A continuación, introduzca el método loadBalance en FeignClientFactoryBean:

inserte la descripción de la imagen aquí

Inicie el servicio de servicio de pedidos en modo de depuración, puede ver el cliente aquí, la capa inferior es Apache HttpClient:

inserte la descripción de la imagen aquí

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

3. Pasarela de servicio de puerta de enlace

Spring Cloud Gateway es un nuevo proyecto de Spring Cloud, que es una puerta de enlace desarrollada en base a Spring 5.0, Spring Boot 2.0 y Project Reactor y otras tecnologías de flujo de eventos y programación reactiva. Su objetivo es proporcionar un método de gestión de rutas API unificado simple y eficaz.

3.1 ¿Por qué necesitamos una puerta de enlace?

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

Las características funcionales principales de la puerta de enlace :

  • solicitud de enrutamiento
  • control de acceso
  • limitando

Diagrama de arquitectura:
inserte la descripción de la imagen aquí

Control de acceso : como punto de entrada de los microservicios, la puerta de enlace debe verificar si el usuario es elegible para la solicitud e interceptarla en caso contrario.

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 actual : cuando el tráfico 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.

3.2 Inicio rápido de la puerta de enlace

A continuación, demostraremos 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

1) Cree un servicio de puerta de enlace e introduzca dependencias

Crear un servicio:

[Falló la transferencia de la imagen del enlace externo, el sitio de origen puede tener un mecanismo de enlace antirrobo, se recomienda guardar la imagen y cargarla directamente (img-zluiTnUM-1686994288645)(assets/image-20210714210919458.png)]

Dependencias de importación:

<!--网关-->
<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) Escribe la clase de inicio

package cn.itcast.gateway;

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

@SpringBootApplication
public class GatewayApplication {
    
    

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

3) Escribir reglas básicas de configuración y enrutamiento

Cree un archivo application.yml con el siguiente contenido:

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/开头就符合要求

Enviaremos Pathtodas las solicitudes que coincidan con las reglas a la dirección especificada por uriel parámetro .

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

4) Reiniciar la prueba

Reinicie la puerta de enlace, al acceder a http://localhost:10010/user/1, cumple con /user/**las reglas, la solicitud se reenvía a uri: http://userservice/user/1, y se obtiene el resultado:

inserte la descripción de la imagen aquí

5) Diagrama de flujo del enrutamiento de la puerta de enlace

Todo el proceso de acceso es el siguiente:

inserte la descripción de la imagen aquí

Resumir:

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

  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

A continuación, concéntrese en aprender el conocimiento detallado de las aserciones de enrutamiento y los filtros de enrutamiento.

3.3 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 para enrutar juicios.

Por ejemplo, Path=/user/** coincide con la ruta. Esta regla está determinada por

org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactoryclase a

Para el procesamiento, hay más de una docena de fábricas de afirmaciones como esta en Spring Cloud Gateway:

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

Solo necesitamos dominar la ingeniería de enrutamiento de Path.

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

3.4.1 Tipos de filtros de enrutamiento

Spring proporciona 31 fábricas de filtros de ruta diferentes. Por ejemplo:

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
Quitar encabezado de respuesta Se eliminó un encabezado de respuesta del resultado de la respuesta.
RequestRateLimiter limitar la cantidad de solicitudes

3.4.2 Filtro de encabezado de solicitud

Tomemos AddRequestHeader como ejemplo para explicar.

Requisito : agregue un encabezado de solicitud a todas las solicitudes que ingresan al servicio de usuario: ¡Verdad = itcast es increíble!

Simplemente modifique el archivo application.yml del servicio de puerta de enlace y agregue filtrado de rutas:

spring:
  cloud:
    gateway:
      routes:
      - id: user-service 
        uri: lb://userservice 
        predicates: 
        - Path=/user/** 
        filters: # 过滤器
        - AddRequestHeader=Truth, Itcast is freaking awesome! # 添加请求头

El filtro actual está escrito en la ruta de servicio de usuario, por lo que solo es válido para las solicitudes de acceso al servicio de usuario.

3.4.3 Filtro predeterminado

Si desea que tenga efecto para todas las rutas, puede escribir la fábrica de filtros por defecto. El formato es el siguiente:

spring:
  cloud:
    gateway:
      routes:
      - id: user-service 
        uri: lb://userservice 
        predicates: 
        - Path=/user/**
      default-filters: # 默认过滤项
      - AddRequestHeader=Truth, Itcast is freaking awesome! 

3.4.4 Resumen

¿Cuál es el papel del filtro?

① Procesar la solicitud o respuesta de enrutamiento, como agregar un encabezado de solicitud

② El filtro configurado bajo la ruta solo surte efecto para la solicitud de la ruta actual

¿Cuál es el papel de los filtros predeterminados?

① Un filtro que es efectivo para todas las rutas

3.5 Filtro global

Para los filtros aprendidos en la sección anterior, la puerta de enlace proporciona 31 tipos, pero la función de cada filtro es fija. Si queremos interceptar solicitudes y hacer nuestra propia lógica comercial, no hay forma de hacerlo.

3.5.1 Función de filtro global

La función del filtro global también es procesar todas las solicitudes y respuestas de microservicios que ingresan a la puerta de enlace, que es la misma que la función de GatewayFilter. La diferencia es que GatewayFilter se define a través de la configuración y la lógica de procesamiento es fija, mientras que la lógica de GlobalFilter debe implementarse escribiendo el código usted mismo.

La forma de definición es implementar la interfaz GlobalFilter.

public interface GlobalFilter {
    
    
    /**
     *  处理当前请求,有必要的话通过{@link GatewayFilterChain}将请求交给下一个过滤器处理
     *
     * @param exchange 请求上下文,里面可以获取Request、Response等信息
     * @param chain 用来把请求委托给下一个过滤器 
     * @return {@code Mono<Void>} 返回标示当前过滤器业务结束
     */
    Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}

Escriba lógica personalizada en el filtro para lograr las siguientes funciones:

  • Juicio de estado de inicio de sesión
  • comprobación de permisos
  • Solicitar estrangulamiento, etc.

3.5.2 Filtro global personalizado

Requisitos: definir un filtro global, interceptar solicitudes y determinar si los parámetros de la solicitud cumplen las siguientes condiciones:

  • Si hay autorización en el parámetro,

  • Si el valor del parámetro de autorización es admin

Si se satisface al mismo tiempo, déjalo ir, de lo contrario, bloquéalo.

lograr:

Defina un filtro en la puerta de enlace:

package cn.itcast.gateway.filters;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@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();
    }
}

3.5.3 Orden de ejecución del filtro

Cuando una solicitud ingresa a la puerta de enlace, encontrará tres tipos de filtros: filtro de ruta actual, 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í

¿Cuáles son las reglas para clasificar?

  • 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 los valores de orden de los filtros sean los mismos, se ejecutarán en el orden predeterminadoFilter > filtro de enrutamiento > GlobalFilter.

Para más detalles, puede ver el código fuente:

org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters()El método es cargar primero los filtros predeterminados, luego cargar los filtros de una determinada ruta y luego fusionarlos.

org.springframework.cloud.gateway.handler.FilteringWebHandler#handle()El método cargará el filtro global, ordenará según el orden después de fusionarse con el filtro anterior y organizará la cadena de filtros.

3.6 Problemas entre dominios

3.6.1 ¿Qué es un problema de dominio cruzado?

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 entre dominios: el navegador prohíbe que el autor de la solicitud realice una solicitud ajax entre dominios con el servidor, y el navegador intercepta la solicitud

Solución: CORS, esto debería haberse aprendido antes, así que no lo repetiré aquí. Los amigos que no lo sepan pueden consultar https://www.ruanyifeng.com/blog/2016/04/cors.html

Supongo que te gusta

Origin blog.csdn.net/2201_75381449/article/details/131262758
Recomendado
Clasificación