1.什么是spring cloud Gateway?

第三章我们介绍了通过Spring Cloud LoadBalancer实现了微服务之间的调用和负载均衡,以及使用Spring Cloud OpenFeign声明式调用,那我们的各种微服务又要如何提供给外部应用调用呢?
当然,因为是REST API接口,外部客户端直接调用各个微服务是没有问题的。但出于种种原因,这并不是一个好的选择。让客户端直接与各个微服务通讯,会存在以下几个问题。

  • 客户端会多次请求不同的微服务,增加了客户端的复杂性。
  • 存在跨域请求,在一定场景下处理会变得相对比较复杂。
  • 实现认证复杂,每个微服务都需要独立认证。
  • 难以重构,项目迭代可能导致微服务重新划分。如果客户端直接与微服务通讯,那么重构将会很难实施。
  • 如果某些微服务使用了防火墙、浏览器不友好的协议,直接访问会有一定困难。

面对类似上面的问题,我们要如何解决呢?答案就是:服务网关!在微服务系统中微服务资源一般不直接暴露给我外部客户端访问,这样做的好处是将内部服务隐藏起来,从而解决上述问题。
网关有很多重要的意义,具体体现在下面几个方面。

  • 网关可以做一些身份认证、权限管理、防止非法请求操作服务等,对服务起一定保护作用。
  • 网关将所有微服务统一管理,对外统一暴露,外界系统不需要知道微服务架构个服务相互调用的复杂性,同时也避免了内部服务一些敏感信息泄露问题。
  • 易于监控。可在微服务网关收集监控数据并将其推送到外部系统进行分析。
  • 客户端只跟服务网关打交道,减少了客户端与各个微服务之间的交互次数。
  • 多渠道支持,可以根据不同客户端(WEB端、移动端、桌面端…)提供不同的API服务网关。
  • 网关可以用来做流量监控。在高并发下,对服务限流、降级。
  • 网关把服务从内部分离出来,方便测试。

微服务网关能够实现,路由、负载均衡等多种功能。类似Nginx,反向代理的功能。在微服务架构中,后端服务往往不直接开放给调用端,而是通过一个API网关根据请求的URL,路由到相应的服务。当添加API网关后,在第三方调用端和服务提供方之间就创建了一面墙,在API网关中进行权限控制,同时API网关将请求以负载均衡的方式发送给后端服务。微服务网关架构,如下图所示。

image.png

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.项目要求

  1. 创建网关微服务项目
  2. 网关的负载均衡和熔断配置
  3. Gateway 跨域配置
  4. 前端统一访问地址 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

    1. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

    4.0.0

    1. <groupId>org.springframework.boot</groupId>
    2. <artifactId>spring-boot-starter-parent</artifactId>
    3. <version>2.3.4.RELEASE</version>
    4. <relativePath/> <!-- lookup parent from repository -->

    com.csz bill-gateway 0.0.1-SNAPSHOT bill-gateway bill-gateway

    1. <java.version>1.8</java.version>
    2. <spring-cloud.version>2021.0.1</spring-cloud.version>

    1. <dependency>
    2. <groupId>org.springframework.cloud</groupId>
    3. <artifactId>spring-cloud-starter-gateway</artifactId>
    4. </dependency>
    5. <dependency>
    6. <groupId>org.springframework.cloud</groupId>
    7. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    8. </dependency>
    9. <dependency>
    10. <groupId>org.springframework.boot</groupId>
    11. <artifactId>spring-boot-devtools</artifactId>
    12. <scope>runtime</scope>
    13. <optional>true</optional>
    14. </dependency>
    15. <dependency>
    16. <groupId>org.projectlombok</groupId>
    17. <artifactId>lombok</artifactId>
    18. <optional>true</optional>
    19. </dependency>
    20. <dependency>
    21. <groupId>org.springframework.boot</groupId>
    22. <artifactId>spring-boot-starter-test</artifactId>
    23. <scope>test</scope>
    24. </dependency>

    org.springframework.cloud spring-cloud-dependencies ${spring-cloud.version} pom import org.springframework.boot spring-boot-maven-plugin org.projectlombok lombok

  1. 2.启动器添加@EnableDiscoveryClient注解
  2. ```yaml
  3. package com.csz.billgateway;
  4. import org.springframework.boot.SpringApplication;
  5. import org.springframework.boot.autoconfigure.SpringBootApplication;
  6. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
  7. @SpringBootApplication
  8. @EnableDiscoveryClient
  9. public class BillGatewayApplication {
  10. public static void main(String[] args) {
  11. SpringApplication.run(BillGatewayApplication.class, args);
  12. }
  13. }

3.配置文件 (重点)

  1. server:
  2. port: 8086
  3. spring:
  4. application:
  5. name: bill-gateway
  6. cloud:
  7. gateway:
  8. routes:
  9. - id: service2
  10. # uri: http://127.0.0.1:9001
  11. uri: http://localhost:9001
  12. predicates: #4. 前端统一访问地址 http://locahost:8086/api/bill/list,注意路径过滤器配置
  13. - Path=/api/bill/list-page
  14. filters:
  15. - StripPrefix=1
  16. eureka:
  17. client:
  18. service-url:
  19. defaultZone: http://127.0.0.1:9004/eureka

在routes配置中,配置一下规则:
当访问localhost:8086/api/bill/list-page时,过滤器过滤掉了第一个参数api,转发到localhost:9001/bill/list-page.
结果:
image.png
问题汇总
1.Unsatisfied dependency expressed through method ‘gatewayHttpClientFactory’
解决方案:spring-boot-starter-parent 和spring cloud 版本冲突。降级就好了。