gateway通过filter路由转发或过滤到不同的网关

  • Post author:
  • Post category:其他


gateway 路由 转发或过滤:

接口网关转发到另一个接口网关


法1:访问actuar接口

可以通过gateway内嵌的endpoint来查看GlobalFilter列表(网关ip:端口号/actuator/gateway/globalfilters):


法2:自定义GlobalFilter然后打断点

过滤器大全

org.springframework.cloud.gateway.filter.RemoveCachedBodyFilter, order = -2147483648

移除缓存中的请求体

org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter, order = -2147482648

从exchange的attributes中获得cachedRequestBody属性值作为request的body

必须预设cachedRequestBody属性至attributes中,要手动设置,无法通过配置来设置。可以在优先级更高的filter中来设置cachedRequestBody。当然也可以自己写一个FilterFactory类来做成配置化。

org.springframework.cloud.gateway.filter.NettyWriteResponseFilter, order = -1

将Netty代理调用的response数据流写入ServerHttpResponse的body中。当NettyRouting拿到远程调用的结果数据流之后会将其写入当前请求exchange的attributes中。

org.springframework.cloud.gateway.filter.ForwardPathFilter, order = 0

条件过滤器,只有当请求的header scheme为forward的时候才会发生,否则会忽略没有任何作用,当有转发需求的时候会将request的请求path修改,从而修改了请求的目的地址。

[[RewritePath /order/(?<remaining>.*) = ‘/${remaining}’], order = 1

org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter, order = 10000

将网关上的请求转为对应业务应用的真实ip的请求。

请求进来时path的前缀是gateway的地址(ip+port或域名),需要将其uri映射至服务id上;比如:将path的192.168.20.134:10080映射至服务lb://{serviceId};对于绝对路径配置的服务,exchange的GATEWAY_ROUTE_ATTR属性将会是null,直接过滤到下一个过滤器,不会发生path的真实映射。

org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter, order = 10150

负责服务真实ip的映射,对服务进行负载均衡,默认采用的netflix-ribbon作为负载均衡器。

如果scheme不是服务节点映射的话直接过滤,获取服务节点。里边的choose函数是核心负载均衡函数,获取一个实例(如果是单节点则不计算),然后将服务的真实ip+port替换掉path中的lb://{serviceId}前缀。

org.springframework.cloud.gateway.filter.WebsocketRoutingFilter, order = 2147483646

实现了gateway对于websocket的支持,内部通过websocketClient实现将一个http请求协议换转成websocket,实现调用方无感知的请求websocket的服务,只需要将schme设置成ws或者wss这么简单。

org.springframework.cloud.gateway.filter.NettyRoutingFilter, order = 2147483647

org.springframework.cloud.gateway.filter.ForwardRoutingFilter, order = 2147483647

是一个结束操作,经过filter chain的链式调用,最终将exchange交还给web handler做http请求处理。

package com.knife.gateway.dynamic;
 
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;
 
import java.net.URI;
import java.util.Map;
import java.util.Objects;
 
 
/**
 * 动态路由
 */
@Slf4j
@Component
public class ForwardOrIgnoreFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest originalRequest = exchange.getRequest();
 
        // 可获得所有请求参数
        // Map<String, String> cachedRequestBody = exchange
        // .getAttribute(ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR);
 
        //获取域名+端口后的path
        String rawPath = originalRequest.getURI().getRawPath();
 
        // todo 从redis中取出所有url,然后用rawPath去匹配
 
        String host = "localhost";
        int port = 9012;
 
        URI originUri = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
 
        URI newUri = UriComponentsBuilder.fromUri(originUri)
                .host(host)
                .port(port)
                .build()
                .toUri();
 
        //重新封装request对象
        ServerHttpRequest newRequest = originalRequest.mutate().uri(newUri).build();
 
        // NettyRoutingFilter 最终从GATEWAY_REQUEST_URL_ATTR 取出uri对象进行http请求
        // 所以这里要将新的对象覆盖进去
        exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, newUri);
 
        return chain.filter(exchange.mutate().request(newRequest).build());
 
        // 也可以加回调方法
        // return chain.filter(exchange.mutate().request(newRequest).build())
        //         .then(Mono.fromRunnable(() -> {
        //             //请求完成回调方法 可以在此完成计算请求耗时等操作
        //         }));
    }
 
    /**
     * 这里不能用@Order,必须实现Ordered接口
     * 值必须大于10150。原因:Gateway有自己的过滤器,两个比较重要的如下:
     *      RouteToRequestUrlFilter:将根据Route将网关请求转为真实的请求。order = 10000
     *      ReactiveLoadBalancerClientFilter:负载均衡。order = 10150
     */
    @Override
    public int getOrder() {
        return 15000;
    }
}



版权声明:本文为weixin_60748184原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。