当前位置 : 主页 > 网络编程 > net编程 >

Spring Cloud Gateway过滤器配置

来源:互联网 收集:自由互联 发布时间:2023-09-06
Spring Cloud Gateway过滤器配置 我们只是简单的介绍了如何集成​ ​Spring Cloud Gateway​ ​​ ,下面我们来详细说说​ ​Spring Cloud Gateway​ ​ 的一些特性 Spring Cloud Gateway 建立在 Spring Boot

Spring Cloud Gateway过滤器配置

我们只是简单的介绍了如何集成​​Spring Cloud Gateway​​​ ,下面我们来详细说说​​Spring Cloud Gateway​​ 的一些特性

Spring Cloud Gateway 建立在 Spring Boot 2.x、Spring WebFlux 和 Project Reactor 之上。 因此,当您使用 Spring Cloud Gateway 时,您所知道的许多熟悉的同步库(例如 Spring Data 和 Spring Security)和模式可能并不适用。 如果您不熟悉这些项目,我们建议您在使用 Spring Cloud Gateway 之前先阅读他们的文档以熟悉一些新概念。


路由的配置方式

基于配制文件

​Spring Cloud Gateway​​ 有两种配置路由和过滤器的方法:快捷方式和完全扩展的参数。下面的大多数示例都使用快捷方式。

快捷方式配置

快捷方式配置由过滤器名称识别,后跟等号 ( ​​=​​),后跟以逗号 ( ​​,​​) 分隔的参数值。

spring:
cloud:
gateway:
routes:
- id: after_route #路由的ID,保证全局唯一就行了,建议和服务名搭配命名
uri: https://example.org #uri,断言匹配时转发的uri
predicates:
- Cookie=mycookie,mycookievalue #断言,当断言匹配时就会转发至uri
复制代码

完全扩展的参数

完全扩展的参数看起来更像是带有名称/值对的标准 yaml 配置。通常,会有一把​​name​​钥匙和一把​​args​​钥匙。键是用于配置谓词或过滤器的​​args​​键值对映射。

spring:
cloud:
gateway:
routes:
- id: after_route #路由的ID,保证全局唯一就行了,建议和服务名搭配命名
uri: https://example.org #uri,断言匹配时转发的uri
predicates:
- name: Cookie
args:
name: mycookie
regexp: mycookievalue
复制代码

之前我们项目中用到的路由匹配规则就是快捷方式

service-url:
user-service: http://localhost:8080

spring:
cloud:
gateway:
# 静态路由
routes:
- id: path_route
uri: ${service-url.user-service}/user/get/{id}
predicates:
- Path=/user/get/{id}
复制代码

这个配置的意思就是当请求的​​URI​​ 与​​/user/get/{id}​​ 相匹配时,就会将请求转发至​​http://localhost:8080/user/get/{id}​

基于Java代码的配置方式

除了可以通过配制文件的方式,我们还可以通过Java代码进行硬编码,但是我个人不推荐这种方式,因为一是我认为在配制文件中配置路由可读性更高,另外就是配制文件可以整合配置中心实现动态路由,而显然,Java硬编码的方式是没法配合配置中心进行动态路由的,灵活性不高

// Spring 官方的例子
@SpringBootApplication
public class DemogatewayApplication {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("path_route", r -> r.path("/get")
.uri("http://httpbin.org"))
.route("host_route", r -> r.host("*.myhost.org")
.uri("http://httpbin.org"))
.route("rewrite_route", r -> r.host("*.rewrite.org")
.filters(f -> f.rewritePath("/foo/(?<segment>.*)", "/${segment}"))
.uri("http://httpbin.org"))
.route("hystrix_route", r -> r.host("*.hystrix.org")
.filters(f -> f.hystrix(c -> c.setName("slowcmd")))
.uri("http://httpbin.org"))
.route("hystrix_fallback_route", r -> r.host("*.hystrixfallback.org")
.filters(f -> f.hystrix(c -> c.setName("slowcmd").setFallbackUri("forward:/hystrixfallback")))
.uri("http://httpbin.org"))
.route("limit_route", r -> r
.host("*.limited.org").and().path("/anything/**")
.filters(f -> f.requestRateLimiter(c -> c.setRateLimiter(redisRateLimiter())))
.uri("http://httpbin.org"))
.build();
}
}
复制代码

网上Copy的代码

package com.atguigu.springcloud.config;

import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* @author LiFang
* @version 1.0
* @since

@Configuration
public class GateWayConfig {
/**
* @param routeLocatorBuilder
* @return org.springframework.cloud.gateway.route.RouteLocator
* @description 配置了一个id为route_name的路由规则,
* 当访问地址为http://localhost:9527/guonei时会自动转发到地址:http://news.baidu.com/guonei
* @author LiFang
* @date
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
routes.route("path_route_atguigu",
r -> r.path("/guonei")
.uri("http://news.baidu.com/guonei")).build();
return routes.build();
}

@Bean
public RouteLocator customRouteLocator2(RouteLocatorBuilder builder) {
RouteLocatorBuilder.Builder routes = builder.routes();
routes.route("path_route_atguigu2",
r -> r.path("/guoji")
.uri("http://news.baidu.com/guoji")).build();
return routes.build();
}
}

复制代码

过滤器

Route Predicate 的使用

Spring Cloud Gateway将路由匹配作为Spring WebFlux HandlerMapping基础架构的一部分。 Spring Cloud Gateway包括许多内置的Route Predicate工厂。 所有这些Predicate都与HTTP请求的不同属性匹配。 多个Route Predicate工厂可以进行组合,下面我们来介绍下一些常用的Route Predicate。

注意:Predicate中提到的配置都在application-predicate.yml文件中进行修改,并用该配置启动api-gateway服务。

Spring Cloud Gateway自带了很多断言过滤器,可以让我们在断言中使用,我这里只简单的列举几个常用的,想要详细了解的可以查阅​​官方文档​​

After Route Predicate

在指定时间之后的请求会匹配该路由。

spring:
cloud:
gateway:
routes:
- id: after_route
uri: ${service-url.user-service}
predicates:
- After=2019-09-24T16:30:00+08:00[Asia/Shanghai]
复制代码

Before Route Predicate

在指定时间之前的请求会匹配该路由。

spring:
cloud:
gateway:
routes:
- id: before_route
uri: ${service-url.user-service}
predicates:
- Before=2019-09-24T16:30:00+08:00[Asia/Shanghai]
复制代码

Between Route Predicate

在指定时间区间内的请求会匹配该路由。

spring:
cloud:
gateway:
routes:
- id: before_route
uri: ${service-url.user-service}
predicates:
- Between=2019-09-24T16:30:00+08:00[Asia/Shanghai], 2019-09-25T16:30:00+08:00[Asia/Shanghai]
复制代码

Cookie Route Predicate

带有指定Cookie的请求会匹配该路由

spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: ${service-url.user-service}
predicates:
- Cookie=username,macro
复制代码

带有cookie为​​username=macro​​的请求可以匹配该路由

Header Route Predicate

带有指定请求头的请求会匹配该路由

spring:
cloud:
gateway:
routes:
- id: header_route
uri: ${service-url.user-service}
predicates:
- Header=X-Request-Id, \d+
复制代码

带有请求头为​​X-Request-Id:123​​的请求可以匹配该路由

Method Route Predicate

发送指定方法的请求会匹配该路由

spring:
cloud:
gateway:
routes:
- id: method_route
uri: ${service-url.user-service}
predicates:
- Method=GET
复制代码

GET请求可以匹配该路由

Path Route Predicate

发送指定路径的请求会匹配该路由

spring:
cloud:
gateway:
routes:
- id: path_route
uri: ${service-url.user-service}/user/{id}
predicates:
- Path=/user/{id}
复制代码

Query Route Predicate

带指定查询参数的请求可以匹配该路由

spring:
cloud:
gateway:
routes:
- id: query_route
uri: ${service-url.user-service}/user/getByUsername
predicates:
- Query=username
复制代码

带​​username=macro​​查询参数的请求可以匹配该路由。

RemoteAddr Route Predicate

从指定远程地址发起的请求可以匹配该路由

spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: ${service-url.user-service}
predicates:
- RemoteAddr=192.168.1.1/24
复制代码

从192.168.1.1发起请求可以匹配该路由

Weight Route Predicate

使用权重来路由相应请求,以下表示有80%的请求会被路由到localhost:8201,20%会被路由到localhost:8202

spring:
cloud:
gateway:
routes:
- id: weight_high
uri: http://localhost:8201
predicates:
- Weight=group1, 8
- id: weight_low
uri: http://localhost:8202
predicates:
- Weight=group1, 2
复制代码

Route Filter 的使用

路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用。Spring Cloud Gateway 内置了多种路由过滤器,他们都由GatewayFilter的工厂类来产生,下面我们介绍下常用路由过滤器的用法。

AddRequestHeader

AddRequestHeader GatewayFilter 采用名称和值参数。 以下示例配置一个 AddRequestHeader GatewayFilter:

spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
filters:
- AddRequestHeader=X-Request-red, blue
复制代码

这个例子将 X-Request-red:blue 标头添加到所有匹配请求的下游请求标头中

AddRequestParameter GatewayFilter

给请求添加参数的过滤器

spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: http://localhost:8201
filters:
- AddRequestParameter=username, macro
predicates:
- Method=GET
复制代码

以上配置会对GET请求添加​​username=macro​​的请求参数,相当于发起该请求:

curl http://localhost:8201/user/getByUsername?username=macro
复制代码

StripPrefix GatewayFilter

对指定数量的路径前缀进行去除的过滤器

spring:
cloud:
gateway:
routes:
- id: strip_prefix_route
uri: http://localhost:8201
predicates:
- Path=/user-service/**
filters:
- StripPrefix=2
复制代码

以上配置会把以​​/user-service/​​开头的请求的路径去除两位,通过curl工具使用以下命令进行测试

curl http://localhost:9201/user-service/a/user/1
复制代码

相当于发起该请求:

curl http://localhost:8201/user/1
复制代码

PrefixPath GatewayFilter

与StripPrefix过滤器恰好相反,会对原有路径进行增加操作的过滤器。

spring:
cloud:
gateway:
routes:
- id: prefix_path_route
uri: http://localhost:8201
predicates:
- Method=GET
filters:
- PrefixPath=/user
复制代码

以上配置会对所有GET请求添加​​/user​​路径前缀,通过curl工具使用以下命令进行测试。

curl http://localhost:9201/1
复制代码

相当于发起该请求:

curl http://localhost:8201/user/1
复制代码

Hystrix GatewayFilter

Hystrix 过滤器允许你将断路器功能添加到网关路由中,使你的服务免受级联故障的影响,并提供服务降级处理。

  • 要开启断路器功能,我们需要在pom.xml中添加Hystrix的相关依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
复制代码
  • 然后添加相关服务降级的处理类:
@RestController
public class FallbackController {

@GetMapping("/fallback")
public Object fallback() {
Map<String,Object> result = new HashMap<>();
result.put("data",null);
result.put("message","Get request fallback!");
result.put("code",500);
return result;
}
}
复制代码
  • 在application-filter.yml中添加相关配置,当路由出错时会转发到服务降级处理的控制器上:
spring:
cloud:
gateway:
routes:
- id: hystrix_route
uri: http://localhost:8201
predicates:
- Method=GET
filters:
- name: Hystrix
args:
name: fallbackcmd
fallbackUri: forward:/fallback
复制代码
  • 关闭user-service,调用该地址进行测试:​​http://localhost:9201/user/1​​ ,发现已经返回了服务降级的处理信息。

Spring Cloud Gateway过滤器配置_get请求

RequestRateLimiter GatewayFilter

RequestRateLimiter 过滤器可以用于限流,使用RateLimiter实现来确定是否允许当前请求继续进行,如果请求太大默认会返回HTTP 429-太多请求状态。

  • 在pom.xml中添加相关依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
复制代码
  • 添加限流策略的配置类,这里有两种策略一种是根据请求参数中的username进行限流,另一种是根据访问IP进行限流
@Configuration
public class RedisRateLimiterConfig {
@Bean
KeyResolver userKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("username"));
}

@Bean
public KeyResolver ipKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}
}
复制代码
  • 我们使用Redis来进行限流,所以需要添加Redis和RequestRateLimiter的配置,这里对所有的GET请求都进行了按IP来限流的操作
server:
port: 9201
spring:
redis:
host: localhost
password: 123456
port: 6379
cloud:
gateway:
routes:
- id: requestratelimiter_route
uri: http://localhost:8201
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 1 #每秒允许处理的请求数量
redis-rate-limiter.burstCapacity: 2 #每秒最大处理的请求数量
key-resolver: "#{@ipKeyResolver}" #限流策略,对应策略的Bean
predicates:
- Method=GET
logging:
level:
org.springframework.cloud.gateway: debug
复制代码

Retry GatewayFilter

对路由请求进行重试的过滤器,可以根据路由请求返回的HTTP状态码来确定是否进行重试。

  • 修改配置文件:
spring:
cloud:
gateway:
routes:
- id: retry_route
uri: http://localhost:8201
predicates:
- Method=GET
filters:
- name: Retry
args:
retries: 1 #需要进行重试的次数
statuses: BAD_GATEWAY #返回哪个状态码需要进行重试,返回状态码为5XX进行重试
backoff:
firstBackoff: 10ms
maxBackoff: 50ms
factor: 2
basedOnPreviousValue: false
复制代码
  • 当调用返回500时会进行重试,访问测试地址:​​http://localhost:9201/user/111​​
  • 可以发现user-service控制台报错2次,说明进行了一次重试。
2019-10-27 14:08:53.435 ERROR 2280 --- [nio-8201-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause

java.lang.NullPointerException: null
at com.macro.cloud.controller.UserController.getUser(UserController.java:34) ~[classes/:na]
复制代码

添加默认过滤器

要添加过滤器并将其应用于所有路由,您可以使用​​spring.cloud.gateway.default-filters​​. 此属性采用过滤器列表。以下清单定义了一组默认过滤器:

spring:
cloud:
gateway:
default-filters:
- AddResponseHeader=X-Response-Default-Red, Default-Blue
- PrefixPath=/httpbin
复制代码

自定义全局过滤器

当请求与路由匹配时,过滤 Web 处理程序会将 的所有实例​​GlobalFilter​​和所有特定于路由的实例添加​​GatewayFilter​​到过滤器链中。这个组合的过滤器链是按​​org.springframework.core.Ordered​​接口排序的,你可以通过实现​​getOrder()​​方法来设置。

由于 Spring Cloud Gateway 区分过滤器逻辑执行的“前”和“后”阶段(请参阅​​它的工作原理​​),具有最高优先级的过滤器是“前”阶段的第一个和“后”阶段的最后一个阶段。

参考示例

package cuit.epoch.pymjl.filter;

import lombok.extern.log4j.Log4j2;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
* @author Pymjl
* @version 1.0
* @date
@Component
@Log4j2
public class MyGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("=====================come in MyGlobalFilter==========================");
String username = exchange.getRequest().getQueryParams().getFirst("username");
if (username == null) {
log.error("用户名为null,非法用户");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}

/**
* 得到权重,order越小,优先级越高
*
* @return
@Override
public int getOrder() {
return 0;
}
}
复制代码

我们启动项目进行测试

当带上username参数时访问正常

Spring Cloud Gateway过滤器配置_get请求_02

当不带username参数时网关会路由失败

Spring Cloud Gateway过滤器配置_get请求_03

观察后台输出

Spring Cloud Gateway过滤器配置_spring_04

跨域过滤器配置

您可以配置网关来控制 CORS 行为

spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "https://docs.spring.io"
allowedMethods:
- GET
复制代码

在前面的示例中,允许来自​​docs.spring.io​​所有 GET 请求路径的请求的 CORS 请求。

要为某些网关路由谓词未处理的请求提供相同的 CORS 配置,请将​​spring.cloud.gateway.globalcors.add-to-simple-url-handler-mapping​​属性设置为​​true​​.

通常的配置是:

spring:
cloud:
gateway:
default-filters:
# gateway 和下游系统同时支持了跨域,都会向 response header 中增加 Access-Control-Allow-Origin*,所以出现重复的 *。所以需要使用DedupeResponseHeader 来处理一下响应头重复的问题
- DedupeResponseHeader=Access-Control-Allow-Origin, RETAIN_UNIQUE
globalcors:
cors-configurations:
'[/**]':
# 允许携带认证信息
allow-credentials: true
# 允许跨域的源(网站域名/ip),设置*为全部
allowedOrigins: "*"
# 允许跨域的method, 默认为GET和OPTIONS,设置*为全部
allowedMethods: "*"
# 允许跨域请求里的head字段,设置*为全部
allowedHeaders: "*"
复制代码

至此,关于Spring Cloud Gateway的进一步解释到这里就结束啦,后面我们会继续介绍Spring Cloud Gateway的动态路由配置以及负载均衡



网友评论