网关之 Gateway

简介

Spring Cloud Gateway 是 Spring 官方基于 Spring 5.0、Spring Boot 2.0 和 Project Reactor 等技术开发的网关,Spring Cloud Gateway 旨在为微服务架构提供一种简单有效的、统一的 API 路由管理方式。

Spring Cloud Gateway 作为 Spring Cloud 生态系中的网关,其目标是替代 Netflix Zuul,它不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全、监控/埋点和限流等。

Spring Cloud Gateway 依赖 Spring Boot 和 Spring WebFlux,基于 Netty 运行。它不能在传统的 servlet 容器中工作,也不能构建成 war 包。

route 参数

Route 是网关的基础元素,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。
网关之 Gateway_第1张图片
下面是配置类中的
网关之 Gateway_第2张图片

  1. id 表示每个路由都有自己的唯一标识,如果你不配置,就随机生成一个
  2. uri 转发地址 可以直接路径地址 也可以 lb://xxx lb代表从注册中心获取服务
  3. Predicate 它允许开发人员匹配来自 HTTP 的请求,例如请求头或者请求参数。简单来说它就是匹配条件。常见如:Path、Query、Method、Header等。
    After-route 断言工厂
spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - After=2017-01-20T17:42:47.789-07:00[America/Denver]

这条请求匹配在一定日期之后发生的任何请求

如果把上面的after改成before就变成了 在一定日期之前发生的任何请求

如果把上面的after改成between,并且添加一个日期,就变成了 在俩日期之间发生的任何请求
Path-route 断言工厂

spring:
  cloud:
    gateway:
      routes:
	     - id: atf-ms
	          # 目标服务地址(uri:地址,请求转发后的地址)
	          uri: lb://atf-ms
	          # 路由条件(predicates:断言,匹配 HTTP 请求内容)
	          predicates:
	            ## 转发地址格式为 uri/archive
	            - Path=/atf-ms/**					
	          filters:
	            - StripPrefix=1
	            - name: CusHystrix
	              args:
	                name: default
	                fallbackUri: forward:/defaultfallback   

这里的请求路径是 http://localhost:8002/atf-ms/user/users/2 下面必须加上 StripPrefix=1 否则访问的时候回带上atf-ms

  1. filters
    过滤器分为两种配置 一种是在每一个路由的filters 中配置 一种是default

spring:
  cloud:
    gateway:
		default-filters:
		        - TokenValidate
		routes:
			...

此处是配置是全局过滤器了,是所有的route都会经过这个,也可以直接配置到某个路由上。

过滤器

客户端向 Spring Cloud Gateway 发出请求,如果请求与网关程序定义的路由匹配,则该请求就会被发送到网关 Web 处理程序,此时处理程序运行特定的请求过滤器链。 过滤器
过滤器分为两种

  1. GlobalFilter : 全局过滤器,不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器
  2. GatewayFilter : 需要通过spring.cloud.routes.filters 配置在具体路由下,只作用在当前路由上或通过spring.cloud.default-filters配置在全局,作用在所有路由上
  1. 全局过滤器
    自定义一个过滤器 集成GlobalFilter 和 Ordered 重写 filter 方法
/**
 * 自定义一个全局过滤器
 *      实现 globalfilter , ordered接口
 */
@Component
public class LoginFilter implements GlobalFilter,Ordered {
	//这个方法是调用链前后 返回值越大越后执行
	@Override
    public int getOrder() {
        // -1 是 response write filter,当前filter必须在此之前调用
        return Ordered.HIGHEST_PRECEDENCE + 3;
    }
	@Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("执行了自定义的全局过滤器");
        //1.获取请求参数access-token
        String token = exchange.getRequest().getQueryParams().getFirst("access-token");
        //2.判断是否存在
        if(token == null) {
            //3.如果不存在 : 认证失败
            System.out.println("没有登录");
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete(); //请求结束
        }
        //4.如果存在,继续执行
        return chain.filter(exchange); //继续向下执行
	}
}

ServerWebExchange 类解析

public interface ServerWebExchange {

    // 日志前缀属性的KEY,值为org.springframework.web.server.ServerWebExchange.LOG_ID
    // 可以理解为 attributes.set("org.springframework.web.server.ServerWebExchange.LOG_ID","日志前缀的具体值");
    // 作用是打印日志的时候会拼接这个KEY对饮的前缀值,默认值为""
    String LOG_ID_ATTRIBUTE = ServerWebExchange.class.getName() + ".LOG_ID";
    String getLogPrefix();

    // 获取ServerHttpRequest对象
    ServerHttpRequest getRequest();

    // 获取ServerHttpResponse对象
    ServerHttpResponse getResponse();
    
    // 返回当前exchange的请求属性,返回结果是一个可变的Map
    Map<String, Object> getAttributes();
    
    // 根据KEY获取请求属性
    @Nullable
    default <T> T getAttribute(String name) {
        return (T) getAttributes().get(name);
    }
    
    // 根据KEY获取请求属性,做了非空判断
    @SuppressWarnings("unchecked")
    default <T> T getRequiredAttribute(String name) {
        T value = getAttribute(name);
        Assert.notNull(value, () -> "Required attribute '" + name + "' is missing");
        return value;
    }

     // 根据KEY获取请求属性,需要提供默认值
    @SuppressWarnings("unchecked")
    default <T> T getAttributeOrDefault(String name, T defaultValue) {
        return (T) getAttributes().getOrDefault(name, defaultValue);
    } 

    // 返回当前请求的网络会话
    Mono<WebSession> getSession();

    // 返回当前请求的认证用户,如果存在的话
    <T extends Principal> Mono<T> getPrincipal();  
    
    // 返回请求的表单数据或者一个空的Map,只有Content-Type为application/x-www-form-urlencoded的时候这个方法才会返回一个非空的Map -- 这个一般是表单数据提交用到
    Mono<MultiValueMap<String, String>> getFormData();   
    
    // 返回multipart请求的part数据或者一个空的Map,只有Content-Type为multipart/form-data的时候这个方法才会返回一个非空的Map  -- 这个一般是文件上传用到
    Mono<MultiValueMap<String, Part>> getMultipartData();
    
    // 返回Spring的上下文
    @Nullable
    ApplicationContext getApplicationContext();   

    // 这几个方法和lastModified属性相关
    boolean isNotModified();
    boolean checkNotModified(Instant lastModified);
    boolean checkNotModified(String etag);
    boolean checkNotModified(@Nullable String etag, Instant lastModified);
    
    // URL转换
    String transformUrl(String url);    
   
    // URL转换映射
    void addUrlTransformer(Function<String, String> transformer); 

    // 注意这个方法,方法名是:改变,这个是修改ServerWebExchange属性的方法,返回的是一个Builder实例,Builder是ServerWebExchange的内部类
    default Builder mutate() {
	     return new DefaultServerWebExchangeBuilder(this);
    }

    interface Builder {      
         
        // 覆盖ServerHttpRequest
        Builder request(Consumer<ServerHttpRequest.Builder> requestBuilderConsumer);
        Builder request(ServerHttpRequest request);
        
        // 覆盖ServerHttpResponse
        Builder response(ServerHttpResponse response);
        
        // 覆盖当前请求的认证用户
        Builder principal(Mono<Principal> principalMono);
    
        // 构建新的ServerWebExchange实例
        ServerWebExchange build();
    }
}   

GatewayFilterChain 类 解析

/**
 * 网关过滤链表接口
 * 用于过滤器的链式调用
 * Contract to allow a {@link WebFilter} to delegate to the next in the chain.
 *  * @author Rossen Stoyanchev
 * @since 5.0
 */
public interface GatewayFilterChain {

    /**
     *  链表启动调用入口方法
     * Delegate to the next {@code WebFilter} in the chain.
     * @param exchange the current server exchange
     * @return {@code Mono} to indicate when request handling is complete
     */
    Mono<Void> filter(ServerWebExchange exchange);
}

过滤器的GatewayFilterChain 执行顺序

  • 通过GatewayFilter集合构建顶层的GatewayFilterChain
  • 调用顶层GatewayFilterChain,获取第一个Filter,并创建下一个Filter索引对应的GatewayFilterChain
  • 调用filter的filter方法执行当前filter,并将下次要执行的filter对应GatewayFilterChain传入。

参考文章 http://c.biancheng.net/view/5434.html

你可能感兴趣的:(分布式)