《微服务实战》 第七章 Spring Cloud 之 GateWay

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
云原生 API 网关,700元额度,多规格可选
简介: 《微服务实战》 第七章 Spring Cloud 之 GateWay

前言

API 网关是一个搭建在客户端和微服务之间的服务,我们可以在 API 网关中处理一些非业务功能的逻辑,例如权限验证、监控、缓存、请求路由等。

1、通过API网关访问服务

  • 客户端通过 API 网关与微服务交互时,客户端只需要知道 API 网关地址即可,而不需要维护大量的服务地址,简化了客户端的开发。
  • 客户端直接与 API 网关通信,能够减少客户端与各个服务的交互次数。
  • 客户端与后端的服务耦合度降低。
  • 节省流量,提高性能,提升用户体验。
  • API 网关还提供了安全、流控、过滤、缓存、计费以及监控等 API 管理功能。

2、Spring Cloud GateWay 最主要的功能就是路由转发

而在定义转发规则时主要涉及了以下三个核心概念,如下表。

核心概念 描述
Route(路由) 网关最基本的模块。它由一个 ID、一个目标 URI、一组断言(Predicate)和一组过滤器(Filter)组成。
Predicate(断言) 路由转发的判断条件,我们可以通过 Predicate 对 HTTP 请求进行匹配,例如请求方式、请求路径、请求头、参数等,如果请求与断言匹配成功,则将请求转发到相应的服务。
Filter(过滤器) 过滤器,我们可以使用它对请求进行拦截和修改,还可以使用它对上文的响应进行再处理。

3、Gateway的工作流程

  • 客户端将请求发送到 Spring Cloud Gateway 上。
  • Spring Cloud Gateway 通过 Gateway Handler Mapping 找到与请求相匹配的路由,将其发送给 Gateway Web Handler。
  • Gateway Web Handler 通过指定的过滤器链(Filter Chain),将请求转发到实际的服务节点中,执行业务逻辑返回响应结果。
  • 过滤器之间用虚线分开是因为过滤器可能会在转发请求之前(pre)或之后(post)执行业务逻辑。
  • 过滤器(Filter)可以在请求被转发到服务端前,对请求进行拦截和修改,例如参数校验、权限校验、流量监控、日志输出以及协议转换等。
  • 过滤器可以在响应返回客户端之前,对响应进行拦截和再处理,例如修改响应内容或响应头、日志输出、流量监控等。
  • 响应原路返回给客户端。

4、Predicate 断言

pring Cloud Gateway 通过 Predicate 断言来实现 Route 路由的匹配规则。简单点说,Predicate 是路由转发的判断条件,请求只有满足了 Predicate 的条件,才会被转发到指定的服务上进行处理。

常见的 Predicate 断言如下表(假设转发的 URI 为 http://localhost:8001)。

断言 示例 说明
Path - Path=/user/listUserInfo/** 当请求路径与 /user/listUserInfo/** 匹配时,该请求才能被转发到 http://localhost:8001 上。
Before - Before=2022-12-07T11:47:34.255+08:00[Asia/Shanghai] 在 2022 年 12 月 07 日 11 时 47 分 34.255 秒之前的请求,才会被转发到 http://localhost:8001 上。
After - After=2022-12-07T11:47:34.255+08:00[Asia/Shanghai] 在 2022 年 12 月 07 日 11 时 47 分 34.255 秒之后的请求,才会被转发到 http://localhost:8001 上。
Between - Between=2022-12-07T15:18:33.226+08:00[Asia/Shanghai],2022-12-07T15:23:33.226+08:00[Asia/Shanghai] 在 2022 年 12 月 07 日 15 时 18 分 33.226 秒 到 2022 年 12 月 07 日 15 时 23 分 33.226 秒之间的请求,才会被转发到 http://localhost:8001 服务器上。
Cookie - Cookie=name,hqyj.com 携带 Cookie 且 Cookie 的内容为 name=hqyj.com 的请求,才会被转发到 http://localhost:8001 上。
Header - Header=X-Request-Id,\d+ 请求头上携带属性 X-Request-Id 且属性值为整数的请求,才会被转发到 http://localhost:8001 上。
Method - Method=GET 只有 GET 请求才会被转发到 http://localhost:8001 上。

5、示例

建立子模块:gateway-service

5.1、pom.xml配置

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.hqyj</groupId>
        <artifactId>SpringCloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>gateway-service</artifactId>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
    </dependencies>
</project>

5.2、application.xml配置

server:
  port: 80
spring:
  application:
    name: gateway-service
  cloud:
    gateway: #网关路由配置
      routes:
        #将 drp-user-service 提供的服务隐藏起来,不暴露给客户端,只给客户端暴露 API 网关的地址 80
        - id: drp-user-service_routh   #路由 id,没有固定规则,但唯一,建议与服务名对应
          uri: http://localhost:8001          #匹配后提供服务的路由地址
          predicates:
            #以下是断言条件,必选全部符合条件
            - Path=/user/userInfoList/**               #断言,路径匹配 注意:Path 中 P 为大写
            - Method=GET #只能时 GET 请求时,才能访问
eureka:
  instance:
    instance-id: gateway-service
    hostname: localhost
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://localhost:7001/eureka

5.3、启动类

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

访问:http://localhost/user/userInfoList

6、动态路由

以服务名(spring.application.name)作为路径创建动态路由进行转发,从而实现动态路由功能

Route 的 uri 地址修改为以下形式。

lb://service-name

6.1、修改application.xml配置

server:
  port: 80
spring:
  application:
    name: drp-gateway-service
  cloud:
    gateway: #网关路由配置
      routes:
        #将 drp-user-service 提供的服务隐藏起来,不暴露给客户端,只给客户端暴露 API 网关的地址 80
        - id: drp-user-service_routh   #路由 id,没有固定规则,但唯一,建议与服务名对应
          uri: lb://USER-SERVICE          #匹配后提供服务的路由地址
          predicates:
            #以下是断言条件,必选全部符合条件
            - Path=/user/userInfoList/**               #断言,路径匹配 注意:Path 中 P 为大写
            - Method=GET #只能时 GET 请求时,才能访问
          metadata:
             connect-timeout: 10
             #单位毫秒
             response-timeout: 10000
eureka:
  instance:
    instance-id: drp-gateway-service
    hostname: localhost
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
     defaultZone: http://localhost:7001/eureka

7、过滤器Filter

用户登陆状态校验、签名校验。

Spring Cloud Gateway 提供了以下两种类型的过滤器

过滤器类型 说明
Pre 类型 这种过滤器在请求被转发到微服务之前可以对请求进行拦截和修改,例如参数校验、权限校验、流量监控、日志输出以及协议转换等操作。
Post 类型 这种过滤器在微服务对请求做出响应后可以对响应进行拦截和再处理,例如修改响应内容或响应头、日志输出、流量监控等。

7.1、Filter 分类

按照作用范围划分,Spring Cloud gateway 的 Filter 可以分为 2 类:GatewayFilter、GlobalFilter

7.1.1、GatewayFilter

应用在单个路由或者一组路由上的过滤器。

常用的GatewayFilter过滤器

路由过滤器 描述 参数 使用示例
AddRequestHeader 拦截传入的请求,并在请求上添加一个指定的请求头参数。 name:需要添加的请求头参数的 key
value:需要添加的请求头参数的 value。
- AddRequestHeader=my-request-header,1024
AddRequestParameter 拦截传入的请求,并在请求上添加一个指定的请求参数。 name:需要添加的请求参数的 key;
value:需要添加的请求参数的 value。
- AddRequestParameter=my-request-param,c.biancheng.net
AddResponseHeader 拦截响应,并在响应上添加一个指定的响应头参数。 name:需要添加的响应头的 key;
value:需要添加的响应头的 value。
- AddResponseHeader=my-response-header,c.biancheng.net
PrefixPath 拦截传入的请求,并在请求路径增加一个指定的前缀。 prefix:需要增加的路径前缀。 -PrefixPath=/consumer
PreserveHostHeader 转发请求时,保持客户端的 Host 信息不变,然后将它传递到提供具体服务的微服务中。 -PreserveHostHeader
RemoveRequestHeader 移除请求头中指定的参数。 name:需要移除的请求头的 key。 - RemoveRequestHeader=my-request-header
RemoveResponseHeader 移除响应头中指定的参数。 name:需要移除的响应头。 - RemoveResponseHeader=my-response-header
RemoveRequestParameter 移除指定的请求参数。 name:需要移除的请求参数。 - RemoveRequestParameter=my-request-param
RequestSize 配置请求体的大小,当请求体过大时,将会返回 413 Payload Too Large。 maxSize:请求体的大小。 - name:RequestSize
  args:
     maxSize: 5000000

7.1.2、实例

spring:
  application:
    name: drp-gateway-service
  cloud:
    gateway: #网关路由配置
      routes:
        #将 drp-user-service 提供的服务隐藏起来,不暴露给客户端,只给客户端暴露 API 网关的地址 80
        - id: drp-user-service_routh   #路由 id,没有固定规则,但唯一,建议与服务名对应
          uri: lb://USER-SERVICE          #匹配后提供服务的路由地址
          predicates:
            #以下是断言条件,必选全部符合条件
            - Path=/userInfoList/**               #断言,路径匹配 注意:Path 中 P 为大写
            - Method=GET #只能时 GET 请求时,才能访问
          filters:
            - AddRequestHeader=token,tigergege
            - PrefixPath=/user

7.1.2、GlobalFilter

应用在所有的路由上的过滤器,可用于统一异常处理

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.List;
/***
 * @title DrfGlobalFilter
 * @desctption 登录验证
 * @author Administrator
 * @create 2023/5/15 14:17
 **/
@Component
public class DrfGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        //获取URI地址
        RequestPath path = request.getPath();
        HttpHeaders headers = request.getHeaders();
        List<String> stringList = headers.get("token");
        //是否登录验证
        if(CollectionUtils.isEmpty(stringList)){
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        return chain.filter(exchange);
    }
    @Override
    public int getOrder() {
        //过滤器优先级,0为最高
        return 0;
    }
}


目录
相关文章
|
12天前
|
Java 开发者 微服务
从单体到微服务:如何借助 Spring Cloud 实现架构转型
**Spring Cloud** 是一套基于 Spring 框架的**微服务架构解决方案**,它提供了一系列的工具和组件,帮助开发者快速构建分布式系统,尤其是微服务架构。
113 68
从单体到微服务:如何借助 Spring Cloud 实现架构转型
|
2月前
|
Dubbo Java 应用服务中间件
Spring Cloud Dubbo:微服务通信的高效解决方案
【10月更文挑战第15天】随着信息技术的发展,微服务架构成为企业应用开发的主流。Spring Cloud Dubbo结合了Dubbo的高性能RPC和Spring Cloud的生态系统,提供高效、稳定的微服务通信解决方案。它支持多种通信协议,具备服务注册与发现、负载均衡及容错机制,简化了服务调用的复杂性,使开发者能更专注于业务逻辑的实现。
69 2
|
9天前
|
Java Nacos Sentinel
Spring Cloud Alibaba:一站式微服务解决方案
Spring Cloud Alibaba(简称SCA) 是一个基于 Spring Cloud 构建的开源微服务框架,专为解决分布式系统中的服务治理、配置管理、服务发现、消息总线等问题而设计。
111 13
Spring Cloud Alibaba:一站式微服务解决方案
|
11天前
|
JavaScript Java Kotlin
深入 Spring Cloud Gateway 过滤器
Spring Cloud Gateway 是新一代微服务网关框架,支持多种过滤器实现。本文详解了 `GlobalFilter`、`GatewayFilter` 和 `AbstractGatewayFilterFactory` 三种过滤器的实现方式及其应用场景,帮助开发者高效利用这些工具进行网关开发。
|
16天前
|
消息中间件 监控 Java
如何将Spring Boot + RabbitMQ应用程序部署到Pivotal Cloud Foundry (PCF)
如何将Spring Boot + RabbitMQ应用程序部署到Pivotal Cloud Foundry (PCF)
31 6
|
16天前
|
负载均衡 Java 开发者
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
59 5
|
16天前
|
Java 关系型数据库 MySQL
如何将Spring Boot + MySQL应用程序部署到Pivotal Cloud Foundry (PCF)
如何将Spring Boot + MySQL应用程序部署到Pivotal Cloud Foundry (PCF)
36 5
|
16天前
|
缓存 监控 Java
如何将Spring Boot应用程序部署到Pivotal Cloud Foundry (PCF)
如何将Spring Boot应用程序部署到Pivotal Cloud Foundry (PCF)
27 5
|
16天前
|
Prometheus 监控 Java
如何全面监控所有的 Spring Boot 微服务
如何全面监控所有的 Spring Boot 微服务
30 3
|
19天前
|
负载均衡 Java API
项目中用的网关Gateway及SpringCloud
Spring Cloud Gateway 是一个功能强大、灵活易用的API网关解决方案。通过配置路由、过滤器、熔断器和限流等功能,可以有效地管理和保护微服务。本文详细介绍了Spring Cloud Gateway的基本概念、配置方法和实际应用,希望能帮助开发者更好地理解和使用这一工具。通过合理使用Spring Cloud Gateway,可以显著提升微服务架构的健壮性和可维护性。
25 0