spring的统一网关gateway介绍

55 篇文章 1 订阅
20 篇文章 1 订阅

 工作原理

图片来源spring官网 https://cloud.spring.io/spring-cloud-gateway/reference/html/
这是官网的图-How It Works

网关路由配置

1.网关路由可以配置的内容包括
1.路由id:路由唯一标识
2.uri:路由目的地,支持lb和http两种
3.predicates:路由断言,判断请求是否符合要求,符合则转发到路由目的地
4.filters:路由过滤器,处理请求或响应

1.我们在配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理,转变为路由判断的条件。
2.例如Path=/api/**是按照路径匹配,这个规则是由org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory类来处理的。

名称说明示例 

After

是某个时间点后的请求- After=2037-01-20T17:42:47.789-07:00[America/Denver]

Before

是某个时间点之前的请求- Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai]

Between

是某两个时间点之前的请求

- Between=2037-01-20T17:42:47.789-07:00[America/Denver],

2037-01-21T17:42:47.789-07:00[America/Denver]

Cookie

请求必须包含某些cookie- Cookie=chocolate, ch.p

Header

请求必须包含某些header- Header=X-Request-Id, \d+

Host

请求必须是访问某个host(域名)- Host=**.somehost.org,**.anotherhost.org

Method

请求方式必须是指定方式

- Method=GET,POST

Path

请求路径必须符合指定规则- Path=/red/{segment},/blue/**

Query

请求参数必须包含指定参数- Query=name, Jack或者- Query=name

RemoteAddr

请求者的ip必须是指定范围- RemoteAddr=192.168.1.1/24

Weight

权重处理

自定义断言predicates

自定义Predicate要做的事情有如下几点:

  1. 类名称,以XXX开头,RoutePredicateFactory结尾。
  2. 定义静态内部Config类,内部定义Predicate所需配置。
  3. 继承了抽象类AbstractRoutePredicateFactory,泛型为内部类Config
  4. 重写shortcutTypeshortcutFieldOrder方法。这两个方法主要是用来定义Config的配置及生成方式。shortcutType方法主要是用来定义Config的配置的生成方式, shortcutFieldOrder读取配置文件的中参数值给他赋值到配置类中的属性上。
  5. 实现apply方法,内部创建GatewayPredicate匿名内部类。
  6. 修改源码,将自定义断言加入。
@Bean
 public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties,
  List<GatewayFilterFactory> gatewayFilters,
  List<RoutePredicateFactory> predicates,
  RouteDefinitionLocator routeDefinitionLocator,
  ConfigurationService configurationService) {
  predicates.add(new ExtCheckRoutePredicateFactory());
  return new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates,
    gatewayFilters, properties, configurationService);
 }

过滤器

GatewayFilter(局部过滤器/网关过滤器): 需要通过 spring.cloud.routes.filters配置在具体的路由下,只作用在当前特定路由上,也可以通过配置 spring.cloud.default-filters让它作用于全局路由上。 spring.cloud.gateway.default-filters 上会对所有路由生效也算是全局的过滤器;但是这些过滤器的实现上都是要实现GatewayFilterFactory接口。
GlobalFilter(全局过滤器): 不需要再配置文件中配置,作用在所有的路由上,最终通过 GatewayFilterAdapter包装成 GatewayFilterChain能够识别的过滤器。
全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与GatewayFilter的作用一样。Spring Cloud Gateway y也提供了几种全局过滤器,同时我们也可以自定义全局过滤器。

内置的过滤器工厂

这里简单将Spring Cloud Gateway内置的所有过滤器工厂整理成了一张表格。如下:

过滤器工厂  作用参数
AddRequestHeader为原始请求添加Header Header的名称及值
AddRequestParameter为原始请求添加请求参数参数名称及值
AddResponseHeader为原始响应添加HeaderHeader的名称及值
DedupeResponseHeader剔除响应头中重复的值需要去重的Header名称及去重策略
Hystrix为路由引入Hystrix的断路器保护HystrixCommand的名称
FallbackHeaders为fallbackUri的请求头中添加具体的异常信息Header的名称
PrefixPath为原始请求路径添加前缀前缀路径
PreserveHostHeader为请求添加一个preserveHostHeader=true的属性,路由过滤器会检查该属性以决定是否要发送原始的Host
RequestRateLimiter用于对请求限流,限流算法为令牌桶keyResolver、rateLimiter、statusCode、denyEmptyKey、emptyKeyStatus
RedirectTo将原始请求重定向到指定的URLhttp状态码及重定向的url
RemoveHopByHopHeadersFilter为原始请求删除IETF组织规定的一系列Header默认就会启用,可以通过配置指定仅删除哪些Header
RemoveRequestHeader为原始请求删除某个HeaderHeader名称
RemoveResponseHeader 为原始响应删除某个HeaderHeader名称
RewritePath重写原始的请求路径原始路径正则表达式以及重写后路径的正则表达式
RewriteResponseHeader 重写原始响应中的某个HeaderHeader名称,值的正则表达式,重写后的值
SaveSession在转发请求之前,强制执行WebSession::save操作 
secureHeaders为原始响应添加一系列起安全作用的响应头无,支持修改这些安全响应头的值
SetPath修改原始的请求路径修改后的路径
SetResponseHeader修改原始响应中某个Header的值Header名称,修改后的值
SetStatus修改原始响应的状态码HTTP 状态码,可以是数字,也可以是字符串
StripPrefix用于截断原始请求的路径    使用数字表示要截断的路径的数量
Retry 
针对不同的响应进行重试    retries、statuses、methods、series
RequestSize设置允许接收最大请求包的大小。如果请求包大小超过设置的值,则返回 413 Payload Too Large请求包大小,单位为字节,默认值为5M
ModifyRequestBody在转发请求之前修改原始请求体内容修改后的请求体内容
ModifyResponseBody       修改原始响应体的内容 修改后的响应体内容
Default为所有路由添加过滤器过滤器工厂名称及值


注意:每个过滤器工厂都对应一个实现类,并且这些类的名称必须以GatewayFilterFactory结尾,这是Spring Cloud Gateway的一个约定,例如AddRequestHeader对应的实现类为AddRequestHeaderGatewayFilterFactory。

例如:

AddResponseHeaderGatewayFilterFactory
为原始响应添加Header,配置示例:

spring:
  cloud:
    gateway:
      routes:
      - id: add_response_header_route
        uri: https://example.org
        filters:
        - AddResponseHeader=X-Response-Foo, Bar

为原始响应添加名为 X-Request-Foo ,值为 Bar 的响应头。

Default Filters
Default Filters用于为所有路由添加过滤器工厂,也就是说通过Default Filter所配置的过滤器工厂会作用到所有的路由上。配置示例:

spring:
  cloud:
    gateway:
      default-filters:
      - AddResponseHeader=X-Response-Default-Foo, Default-Bar
      - PrefixPath=/httpbin

全局过滤器:GlobalFilter

官方文档:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#global-filters

 ForwardRoutingFilter全局转发过滤器:

ForwardRoutingFilter会查看 exchange的属性 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR的值(一个URI)。如果 URL有转发 scheme(例如forward:///localendpoint),Gateway使用 Spring DispatcherHandler来处理请求。请求 URL的路径部分被转发URL中的路径覆盖。未修改的原始URL将附加到ServerWebExchangeUtils中的列表中。

ReactiveLoadBalancerClientFilter全局负载均衡过滤器:

LoadBalancerClientFilter 会查看exchange的属性 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 的值(一个URI)。如果该值的 scheme是 lb,比如:lb://app-order ,它将会使用 Spring Cloud的 LoadBalancerClient 来将 微服务名(本例中为app-order)解析成实际的 host和 port,并替换掉 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 的内容。未修改的原始URL将附加到ServerWebExchangeUtils中的列表中。
 

自定义全局过滤器

@Component
public class ExceptionFilter implements Ordered, GlobalFilter {

    /**
     *这里的返回值决定拦截器的优先级,数字越小越先被触发
     * 如果需要拦截返回值并处理,这里则需要返回负数
     */
    @Override
    public int getOrder() {
        return -1;
    }

    /**
     * 异常拦截,拦截响应值不是 200 的数据,并抛给全局异常处理
     */
    @Override
    @SuppressWarnings({"unchecked", "NullableProblems"})
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpResponse response = exchange.getResponse();
        ServerHttpResponseDecorator decorated = new ServerHttpResponseDecorator(response) {
            @Override
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                if (body instanceof Flux) {
                    Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
                    return super.writeWith(fluxBody.map(dataBuffer -> {
                        if (response.getStatusCode() == HttpStatus.NOT_FOUND) {
                            throw new ResponseStatusException(HttpStatus.NOT_FOUND);
                        }
                        if (response.getStatusCode() != HttpStatus.OK) {
                            byte[] content = new byte[dataBuffer.readableByteCount()];
                            dataBuffer.read(content);
                            DataBufferUtils.release(dataBuffer); // 释放掉内存
                            String errMsg = new String(content, StandardCharsets.UTF_8);
                            throw new RuntimeException(errMsg);
                        }
                        return dataBuffer;
                    }));
                }
                return super.writeWith(body);
            }
        };
        return chain.filter(exchange.mutate().response(decorated).build());
    }

}

  • 25
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值