1.什么是spring cloud Gateway?
第三章我们介绍了通过Spring Cloud LoadBalancer实现了微服务之间的调用和负载均衡,以及使用Spring Cloud OpenFeign声明式调用,那我们的各种微服务又要如何提供给外部应用调用呢?
当然,因为是REST API接口,外部客户端直接调用各个微服务是没有问题的。但出于种种原因,这并不是一个好的选择。让客户端直接与各个微服务通讯,会存在以下几个问题。
- 客户端会多次请求不同的微服务,增加了客户端的复杂性。
- 存在跨域请求,在一定场景下处理会变得相对比较复杂。
- 实现认证复杂,每个微服务都需要独立认证。
- 难以重构,项目迭代可能导致微服务重新划分。如果客户端直接与微服务通讯,那么重构将会很难实施。
- 如果某些微服务使用了防火墙、浏览器不友好的协议,直接访问会有一定困难。
面对类似上面的问题,我们要如何解决呢?答案就是:服务网关!在微服务系统中微服务资源一般不直接暴露给我外部客户端访问,这样做的好处是将内部服务隐藏起来,从而解决上述问题。
网关有很多重要的意义,具体体现在下面几个方面。
- 网关可以做一些身份认证、权限管理、防止非法请求操作服务等,对服务起一定保护作用。
- 网关将所有微服务统一管理,对外统一暴露,外界系统不需要知道微服务架构个服务相互调用的复杂性,同时也避免了内部服务一些敏感信息泄露问题。
- 易于监控。可在微服务网关收集监控数据并将其推送到外部系统进行分析。
- 客户端只跟服务网关打交道,减少了客户端与各个微服务之间的交互次数。
- 多渠道支持,可以根据不同客户端(WEB端、移动端、桌面端…)提供不同的API服务网关。
- 网关可以用来做流量监控。在高并发下,对服务限流、降级。
- 网关把服务从内部分离出来,方便测试。
微服务网关能够实现,路由、负载均衡等多种功能。类似Nginx,反向代理的功能。在微服务架构中,后端服务往往不直接开放给调用端,而是通过一个API网关根据请求的URL,路由到相应的服务。当添加API网关后,在第三方调用端和服务提供方之间就创建了一面墙,在API网关中进行权限控制,同时API网关将请求以负载均衡的方式发送给后端服务。微服务网关架构,如下图所示。
2 Spring Cloud Gateway简介
2.1 简介
SpringCloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。
SpringCloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zuul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 2.0之前的非Reactor模式的老版本。而为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。
Spring Cloud Gateway 的目标,不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。
注意:Spring Cloud Gateway 底层使用了高性能的通信框架Netty。
2.2 特征
SpringCloud官方,对SpringCloud Gateway 特征介绍如下:
- 基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0
- 集成 Spring Cloud DiscoveryClient
- Predicates 和 Filters 作用于特定路由,易于编写的 Predicates 和 Filters
- 具备一些网关的高级功能:动态路由、限流、路径重写
- 集成Spring Cloud DiscoveryClient
- 集成熔断器CircuitBreaker
从以上的特征来说,和Zuul的特征差别不大。SpringCloud Gateway和Zuul主要的区别,还是在底层的通信框架上。
简单说明一下上文中的三个术语:
(1)Filter(过滤器):
和Zuul的过滤器在概念上类似,可以使用它拦截和修改请求,并且对下游的响应,进行二次处理。过滤器为org.springframework.cloud.gateway.filter.GatewayFilter类的实例。
(2)Route(路由):
网关配置的基本组成模块,和Zuul的路由配置模块类似。一个Route模块由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配,目标URI会被访问。
(3)Predicate(断言):
这是一个 Java 8 的 Predicate,可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。断言的输入类型是一个 ServerWebExchange。
3.项目要求
- 创建网关微服务项目
- 网关的负载均衡和熔断配置
- Gateway 跨域配置
前端统一访问地址 http://locahost:8086/api/bill/list,注意路径过滤器配置
4.具体操作
1.pom.XML ```yaml <?xml version=”1.0” encoding=”UTF-8”?> <project xmlns=”http://maven.apache.org/POM/4.0.0“ xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance“
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0 <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
com.csz bill-gateway 0.0.1-SNAPSHOT bill-gateway bill-gateway <java.version>1.8</java.version>
<spring-cloud.version>2021.0.1</spring-cloud.version>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
org.springframework.cloud spring-cloud-dependencies ${spring-cloud.version} pom import org.springframework.boot spring-boot-maven-plugin org.projectlombok lombok
2.启动器添加@EnableDiscoveryClient注解
```yaml
package com.csz.billgateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class BillGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(BillGatewayApplication.class, args);
}
}
3.配置文件 (重点)
server:
port: 8086
spring:
application:
name: bill-gateway
cloud:
gateway:
routes:
- id: service2
# uri: http://127.0.0.1:9001
uri: http://localhost:9001
predicates: #4. 前端统一访问地址 http://locahost:8086/api/bill/list,注意路径过滤器配置
- Path=/api/bill/list-page
filters:
- StripPrefix=1
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:9004/eureka
在routes配置中,配置一下规则:
当访问localhost:8086/api/bill/list-page时,过滤器过滤掉了第一个参数api,转发到localhost:9001/bill/list-page.
结果:
问题汇总
1.Unsatisfied dependency expressed through method ‘gatewayHttpClientFactory’
解决方案:spring-boot-starter-parent 和spring cloud 版本冲突。降级就好了。