您现在的位置是:首页 >其他 >0201概述-网关Gateway-微服务架构网站首页其他

0201概述-网关Gateway-微服务架构

gaog2zh 2023-05-31 04:00:03
简介0201概述-网关Gateway-微服务架构

1 前言

Spring Cloud Gateway是一个基于Spring Framework 5、Spring Boot 2和Project Reactor等技术开发的API网关,它提供了一系列的过滤器(Filter)来处理HTTP请求和响应,可以轻松地实现路由、负载均衡、限流、重试、熔断、安全控制等功能,可以作为微服务架构中的入口和边缘服务。

Spring Cloud Gateway的核心组件包括路由(Route)、断言(Predicate)、过滤器(Filter)等。路由用来将请求映射到不同的微服务上,断言则用来匹配请求的条件,过滤器则可以对请求进行修改和拦截。

Spring Cloud Gateway提供了丰富的可扩展性,可以通过编写自定义的路由、断言、过滤器等组件来满足各种复杂的业务需求。同时,它还集成了Spring Cloud的服务发现和负载均衡机制,可以自动地从注册中心中获取微服务的信息并进行负载均衡

下面我们根据官网文档和我们正在学习的开源项目pig文档以及其他相关文档,介绍一些我们开发中会用到的一些内容。

2 项目引入

项目工程pom.xml文件用引入:

<!-- 版本在spring-cloud-gateway-dependencies中指定 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

3 术语

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

注意:其中Route和Predicate必须同时申明

4 工作原理

gateway工作原理如下图4-1所示:

在这里插入图片描述

Spring Cloud Gateway是Spring Cloud生态系统中的一个API网关服务,它基于Spring 5,Spring Boot 2和Project Reactor构建,提供了一种简单而有效的方式来路由请求、进行限流、进行身份验证和授权、实现负载均衡等功能。

Spring Cloud Gateway的工作原理可以简单概括如下:

  1. 路由规则配置:开发人员通过配置文件或代码配置路由规则,定义请求的匹配规则和目标服务的位置。
  2. 请求到达网关:客户端请求到达Spring Cloud Gateway,被路由到对应的处理器。
  3. 过滤器链处理:Spring Cloud Gateway通过一系列过滤器链处理请求,每个过滤器可以进行一些操作,如修改请求头、重定向、转发、限流、身份验证等。
  4. 路由转发:根据路由规则,将请求转发到对应的目标服务,可以是Spring Boot应用程序、其他微服务或外部API。
  5. 响应处理:Spring Cloud Gateway收到目标服务的响应后,可以通过过滤器链对响应进行修改,然后将响应返回给客户端。

总之,Spring Cloud Gateway作为一种轻量级的API网关服务,可以通过路由规则和过滤器链处理请求,将请求转发到目标服务并处理响应,从而为微服务架构中的应用提供了一种高效、灵活和可扩展的解决方案。

5 配置示例

5.1 简洁配置

application.xml配置示例

spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - Cookie=mycookie,mycookievalue

5.2 展开配置

application.xml配置示例

spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - name: Cookie
          args:
            name: mycookie
            regexp: mycookievalue

6 Predicate

路由转发判断条件,可以根据很多信息去判断,包括时间、Cookie、Header、Host、Method、Path等等。

我们这里以开发中的常用的Path为例,示例如下:

routes:
  - id: admin-service_router
    uri: lb://admin-service
    predicates:
      - Path=/admin/**
    filters:
      - StripPrefix=1
  • /admin/**:**表示任意,匹配任意一级路径是admin的请求,转发到对应的uri

7 GatewayFilter

网关过滤器,可以对HTTP请求或者响应做修改。下面介绍2个开发用常用的网关过滤器:

  • StripPrefix:忽略前缀
  • RequestRateLimiter:请求限流

7.1 StripPrefix GatewayFilter

以#6中路由配置为例讲解,后面参数为数字,表示在向下转发的时候,忽略几段路径前缀。

routes:
  - id: admin-service_router
    uri: lb://admin-service
    predicates:
      - Path=/admin/**
    filters:
      - StripPrefix=1
  • 这里stripPrefix值为1,对应的请求示例/admin/user在向下转发的时候忽略掉/admin/,变为/user;
  • 路径分隔符默认/,StripPrefix值对应几个/xxx/分隔符包围的路径。

7.2 RequestRateLimiter GatewayFilter

网关限流实例:

① pom 依赖

这里一定要注意,是网关引入的redis-reactive,背压模式的redis。

<!--基于 reactive stream 的redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>

② 配置按照请求IP 的限流

spring:
  cloud:
    gateway:
      routes:
      - id: requestratelimiter_route
        uri: lb://pig-upms
        order: 10000
        predicates:
        - Path=/admin/**
        filters:
        - name: RequestRateLimiter
          args:
            redis-rate-limiter.replenishRate: 1  # 令牌桶每秒填充平均速率
            redis-rate-limiter.burstCapacity: 3  # 令牌桶总容量
            key-resolver: "#{@remoteAddrKeyResolver}" #SPEL表达式去的对应的bean
        - StripPrefix=1
  • 配置bean,多维度限流量的入口 对应上边key-resolver
/**
* 自定义限流标志的key,多个维度可以从这里入手
* exchange对象中获取服务ID、请求信息,用户信息等
*/
@Bean
KeyResolver remoteAddrKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}

6 Global Filters

全局过滤器,配合Ordered接口用来指定在过滤器执行链中的顺序。在开发中,我们一般用来做日志记录,获取自定义请求头信息,做校验等等。

下面看下日志记录的实例:

@Slf4j
@Component
public class ApiLoggingFilter implements GlobalFilter, Ordered {

   private static final String START_TIME = "startTime";

   private static final String X_REAL_IP = "X-Real-IP";// nginx需要配置

   @Override
   public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
      if (log.isDebugEnabled()) {
         String info = String.format("Method:{%s} Host:{%s} Path:{%s} Query:{%s}",
               exchange.getRequest().getMethod().name(), exchange.getRequest().getURI().getHost(),
               exchange.getRequest().getURI().getPath(), exchange.getRequest().getQueryParams());
         log.debug(info);
      }
      exchange.getAttributes().put(START_TIME, System.currentTimeMillis());
      return chain.filter(exchange).then(Mono.fromRunnable(() -> {
         Long startTime = exchange.getAttribute(START_TIME);
         if (startTime != null) {
            Long executeTime = (System.currentTimeMillis() - startTime);
            List<String> ips = exchange.getRequest().getHeaders().get(X_REAL_IP);
            String ip = ips != null ? ips.get(0) : null;
            String api = exchange.getRequest().getURI().getRawPath();

            int code = 500;
            if (exchange.getResponse().getStatusCode() != null) {
               code = exchange.getResponse().getStatusCode().value();
            }
            // 当前仅记录日志,后续可以添加日志队列,来过滤请求慢的接口
            if (log.isDebugEnabled()) {
               log.debug("来自IP地址:{}的请求接口:{},响应状态码:{},请求耗时:{}ms", ip, api, code, executeTime);
            }
         }
      }));
   }

   @Override
   public int getOrder() {
      return Ordered.LOWEST_PRECEDENCE;
   }

}

7 网关超时配置

路由超时配置可以为所有路由配置Http超时(响应和连接),并为每个特定路由覆盖Http超时。

7.① 配置全局路由超时时间

spring:
  cloud:
    gateway:
      httpclient:
        connect-timeout: 1000
        response-timeout: 10s
  • connect-timeout 必须以毫秒为单位指定连接超时时间.
  • response-timeout 必须指定为java.time.Duration

7.② 特定接口配置超时时间

- id: pig-upms      # 唯一的服务ID
  uri: lb://pig-upms # 注册中心的服务名称,实现负载均衡
  predicates:
  - Path=/admin/demo  #所有业务的请求前缀
  metadata:
    response-timeout: 200
    connect-timeout: 200

可以通过路由的metadata以下两个参数配置每个路由超时:

  • connect-timeout 必须以毫秒为单位指定连接超时时间.
  • response-timeout 必须以毫秒为单位指定响应超时时间.

8 网关CORS 跨域配置

CORS跨域配置,可以以不同的方式进行配置,这里介绍在网关进行配置的方式。

在网关的配置文件中加入以下内容(请根据实际情况修改)

spring:
  cloud:
    gateway:
#      default-filters:
#        - DedupeResponseHeader=Access-Control-Allow-Origin
      globalcors:
        corsConfigurations:
          '[/**]':
            allowedOriginPatterns: "*"           #注意这个设置只对 spring boot 2.4+ 有效,低版本 使用  allowedOrigins: "*" 属性
            allowed-methods: "*"
            allowed-headers: "*"
            allow-credentials: true
            exposedHeaders: "Content-Disposition,Content-Type,Cache-Control"
  • 以上配置可作为开发环境使用,生成环境建议你根据实际情况修改(请先理解CORS,并参考org.springframework.cloud.gateway.config.GlobalCorsProperties
  • 跨域时会产生预检请求(Pre-Flight Request),这样就会对你的服务器产生额外的网络请求。如果可以通过部署手段解决跨域,则可以关闭跨域支持,方法是把以上配置信息清理掉。

结语

如果小伙伴什么问题或者指教,欢迎交流。

❓QQ:806797785

⭐️源代码仓库地址:https://gitee.com/gaogzhen/micro

参考地址:

[1] springcloud gateway 官方文档

[2] Gateway:Spring Cloud API网关组件(非常详细)

[3] Spring Cloud——微服务网关Spring Cloud GateWay

[4] lengleng /pig

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。