Gateway入门

113 阅读2分钟

什么是网关

API网关是随着微服务概念兴起的一种架构模式,它是运行于外部请求与内部服务之间的一个流量入 口,用于实现对外部请求的协议转换、鉴权、流控、参数校验、监控等通用功能。
架构图

Gateway架构图.png

Spring Cloud Gateway

Spring Cloud Gateway 是Spring Cloud官方推出的第二代网关框架,定位于取代 Netflix Zuul。 Spring Cloud Gateway 旨在为微服务架构提供一种简单且有效的 API 路由的管理方式,并基于 Filter 的方式提供网关的基本功能,例如说安全认证、监控、限流等等。 Spring Cloud Gateway 是由 WebFlux + Netty + Reactor 实现的响应式的 API 网关。它不能在传统的servlet 容器中工作,也不能构建成 war 包。

基本概念

  • 路由:路由信息包括一个ID、一个目的URI、一组断言工厂、一组Filter组成。
  • 断言:Java8中的断言函数,SpringCloud Gateway中的断言函数类型是Spring5.0框架中的 ServerWebExchange。断言函数允许开发者去定义匹配Http request中的任何信息,比如请求头和 参数等。如果断言为真,则说明请求的URL和配置的路由匹配。
  • 过滤:SpringCloud Gateway中的filter分为Gateway FilIer和Global Filter。Filter可以对请求和响应进行 处理。

Gateway实战

依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

yml配置

spring:
  cloud:
    gateway:
      routes:
        - id: clothing-user //路由id
          uri: lb://clothing-user
          predicates:
            - Path=/api/clothing/user/** //断言,路径匹配进行路由
          filters:
            - StripPrefix=1 //过滤掉路径第一个/api/
        - id: clothing-aisketch
          uri: lb://clothing-aisketch
          predicates:
            - Path=/api/clothing/aisketch/**
          filters:
            - StripPrefix=1

自定义全局过滤器配置

自定义全局过滤器定义方式是实现GlobalFilter接口。每一个过滤器都必须指定一个int类型的order 值,order值越小,过滤器优先级越高,执行顺序越靠前。GlobalFilter通过实现Ordered接口来指定 order值。

@Slf4j
@Component
public class AuthorizeSecurityFilter extends BaseFilter implements GlobalFilter, Ordered {

    @Resource
    private OauthConfig oauthConfig;
    @Resource
    private RedisUtil redisUtil;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = null;
        try {
            //写自己的业务鉴权逻辑
            path = request.getPath().toString();
            if (isFilterPath(path)) {
                String token = exchange.getRequest().getHeaders().getFirst("Authorization");
                log.info("token:{}",token);
                checkToken(token);
            }
        } catch (Exception e) {
            log.info("[网关-token鉴权异常] path:{} 异常记录:{}", path, Throwables.getStackTraceAsString(e));
            Asserts.fail(e.getMessage());
        }
        return chain.filter(exchange);
    }

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