Tabla de contenido
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
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
Tenga en cuenta que los microservicios no son solo SpringCloud
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
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)
Cuatro soluciones para el aterrizaje de la arquitectura de microservicios
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文件)创建表
②先创建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
Por ejemplo, el siguiente es el archivo pom del proyecto principal
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
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.
③实现远程调用
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}.
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
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
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/
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:
Luego, en la ventana emergente, realice la configuración:
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
Ahora visite http://localhost:10086 para ver si el servicio se ha registrado correctamente
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
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 :
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
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/8originalUri.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)
- 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 getServer
mé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
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
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 :
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:
- 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
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
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
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网页中查看
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
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
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.
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.
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
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.
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
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
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
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:
Complete el formato de fecha de acuerdo con nuestro formato especificado y regrese
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:
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:
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
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
②Ingrese al directorio conf de nacos, modifique el archivo de configuración cluster.conf.example y cámbiele el nombre a cluster.conf:
③ 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)
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
⑤ Copie la carpeta nacos tres veces y luego modifique application.properties en las tres carpetas respectivamente,
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:
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:
③编写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
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.
⑤总结
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:
UserController:
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
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.
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.
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.
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.
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:
- Cree una puerta de enlace de proyecto SpringBoot e introduzca dependencias de puerta de enlace
- Escribir clase de inicio
- Escribir reglas básicas de configuración y enrutamiento
- 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/开头就符合要求
Path
Proxy todas uri
las 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.启动网关服务,访问网关服务端口,测试结果如下图,可以通过网关然后访问到服务
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
Finalmente, resuma los pasos del proceso.
Pasos de construcción de la puerta de enlace:
-
Cree un proyecto, presente el descubrimiento de servicios de nacos y las dependencias de la puerta de enlace
-
Crear una clase de inicio GatewayApplication
-
Configure application.yml, incluida la información básica del servicio, la dirección de nacos, el enrutamiento
La configuración de enrutamiento incluye:
-
ID de ruta: el identificador único de la ruta (generalmente el nombre del servicio, pero no se repite)
-
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
-
Aserciones de enrutamiento (predicados): reglas para juzgar el enrutamiento,
-
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:
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 # 添加请求头
测试效果
结果如下
默认过滤器
上面加的过滤器是只针对对应的路由有效,若要像对所有路由都有效,就可以配置默认过滤器
如果要对所有的路由都生效,则可以将过滤器工厂写到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();
}
}
结果如下图
过滤器执行顺序
请求进入网关会碰到三类过滤器:当前路由的过滤器、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:
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