Spring Cloud Gateway 网关使用

453 阅读2分钟

概述

Gateway 底层基于 Netty 异步通讯的,使用的是 Webflux 框架处理请求。

本文中所用到的 Spring Cloud 和 Spring Boot 相关的版本说明

版本概述: spring-boot 2.4.2 spring-cloud 2020.0.1

服务注册: eureka-client

服务熔断: reactor-resilience4j

本文主要是通过一个 demo 来对 Gateway 的核心功能进行简要的介绍。

demo 项目地址. github 地址

Gateway 核心功能

一. 路由

  1. 配置负载均衡
uri: lb://SERVICE-MEMBER

这里 lb 就是用到了负载均衡, 由于我这里使用的是 eureka-client 3.0.1 内部使用的是loadbalancer 作为负载均衡框。

  1. 配置断言
predicates:
	# 路由断言对符合条件的接口断言
	- Path=/member/**

predicates 下面的所有配置信息都是对服务节点接口的断言,我们还可以对参数, cookie, header 等各方面进行断言

  1. 配置过滤器
filters:
  # 熔断器
  - name: CircuitBreaker
  args:
  name: myCircuitBreaker
  fallbackUri: forward:/fallback

gatway 还提供过滤器的配置,支持自定义过滤器,来控制路由规则

二. 鉴权

实现鉴权咱们的主要主要实现手段是通过 GlobalFilter 的方式来实现的,下面是一个简单的例子判断咱们 cookie 中是否包含 login 信息。如果包含就表示用于已经登录,如果没有就返回 UNAUTHORIZED

  1. 对用户登录进行鉴权,首先定义全局过滤器
/**
 * 自定义登录过滤器判断是否登录
 *
 * @author zhengsh
 * @date 2021-01-31
 */
public class LoginFilter implements GlobalFilter, Ordered {
  @Override
  public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    MultiValueMap<String, HttpCookie> cookies = exchange.getRequest().getCookies();
    for (Map.Entry<String, List<HttpCookie>> cookie : cookies.entrySet()) {
      // 如果 cookie 中包含 login 信息就表示通过
      if (cookie.getKey().equals("login")) {
        System.out.println(1);
        return chain.filter(exchange);
      }
    }
    System.out.println(2);
    // 401
    ServerHttpResponse response = exchange.getResponse();
    response.setStatusCode(HttpStatus.UNAUTHORIZED);
    return response.setComplete();
  }


  @Override
  public int getOrder() {
    return -1;
  }
}

三. 降级/熔断

resilience4j 进行服务降级

filters:
  # 熔断器
  - name: CircuitBreaker
  args:
  name: myCircuitBreaker
  fallbackUri: forward:/fallback

Resilience4j 是一个受hystrix启发的一款轻量级容错类库, 在分布式系统中,许多不可避免的调用会失败, 比如超时,一场等。Resilience4j 能够保证在一个依赖出现问题的情况下,不会导致整体服务失败,避免级联故障,提高分布式系统的弹性

“断路器” 本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似保险熔断),向调用方法返回一个符合预期的,可处理的被选相应(FallBack), 而不是长时间的等待或者跑出调用方法无法处理的异常,这样就保证了服务调用方的线程不会长时间,不必要地占用,从而避免了故障在分布式系统中进行蔓延,从而导致雪崩效应。

四. 限流

通过 gateway 自带的 redislimiter 算法进行限流

配置参数:

filters:
  # 令牌桶
  - name: RequestRateLimiter
  KeyResolver: userKeyResolver
  args:
    redis-rate-limiter.replenishRate: 10
    redis-rate-limiter.burstCapacity: 20
    redis-rate-limiter.requestedTokens: 1

userKeyResolver 定义

@Bean
public KeyResolver userKeyResolver() {
  return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}

访问方式:

http://127.0.0.1:4001/member/test?user=100