目录
- Spring Cloud Gateway
- predicates路由断言工厂
- 全局过滤器
- fGatewayFilter工厂
- filters配置
- Hystrix GatewayFilter工厂
- 限流RequestRateLimiter GatewayFilter工厂
- 参考文档
- 总结
Spring 官方最终还是按捺不住推出了自己的网关组件:Spring Cloud Gateway ,相比之前我们使用的 Zuul(1.x) 它有哪些优势呢?
Zuul(1.x) 基于 Servlet,使用阻塞 API,它不支持任何长连接,如 WebSockets,Spring Cloud Gateway 使用非阻塞 API,支持 WebSockets,支持限流等新特性。
Spring Cloud Gateway
Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。
注意:
Spring Cloud Gateway是基于Spring Boot 2.x, Spring WebFlux和Projec开发者_JAVA开发t Reactor 构建的。
因此,在使用Spring Cloud Gateway时,许多不熟悉的同步库(例如,Spring Data和Spring Security)和模式可能不适用。
如果您对这些项目不熟悉,建议您在使用Spring Cloud Gateway之前先阅读它们的文档,以熟悉一些新概念。
Spring Cloud Gateway需要Spring Boot和Spring Webflux提供的Netty运行时。它不能在传统的Servlet容器中或作为WAR构建。
Spring Cloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Netflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。

Spring Cloud Gateway 的特征:
- 基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0
- 动态路由
- Predicates 和 Filters 作用于特定路由
- 集成 Hystrix 断路器
- 集成 Spring Cloud DiscoveryClient
- 易于编写的 Predicates 和 Filters
- 限流
- 路径重写
相关概念:
- Route(路由):这是网关的基本构建块。它由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配。
- Predicate(断言):这是一个 Java 8 的 Predicate。输入类型是一个 ServerWebExchange。我们可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。
- Filter(过滤器):这是org.springframework.cloud.gateway.filter.GatewayFilter的实例,我们可以使用它修改请求和响应。
Spring Cloud Gateway 网关路由有两种配置方式:
- 在配置文件 yml 中配置通过@Bean自定义 RouteLocator,在启动主类 Application 中配置
- 这两种方式是等价的,建议使用 yml 方式进配置。
pom.XML
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
http://www.devze.com <version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
application.yml
server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: bamboo_route
uri: https://blog.csdn.net/
predicates:
- Path=/blogdevteam
yml方式配置路由
id:我们自定义的路由 ID,保持唯一uri:目标服务地址predicates:路由条件,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。filters:过滤规则,本示例暂时没用。
启动类:代码方式配置路由
package com.bamboo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
/**
* @program: spring-gateway
* @description: Application
* @author: Bamboo zjcjava@163.com
* @create: 2019-10-26 20:00
**/
@SpringBootApplication
public class Application {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
// basic proxy
.route(r -> r.path("/zjcjava")
.uri("https://blog.csdn.net//"))
.build();
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
http://localhost:8080/zjcjava
对应访问的地址是https://blog.csdn.net/zjcjavahttp://localhost:8080/blogdevteam
对应访问的地址是https://blog.csdn.net/blogdevteam
可以看出来,它会自动在url路径/后面加上对应的路由地址
predicates路由断言工厂
Spring Cloud Gateway将路由作为Spring WebFlux HandlerMapping基础架构的一部分进行匹配。Spring Cloud Gateway包括许多内置的Route Predicate工厂。所有这些谓词都与HTTP请求的不同属性匹配。多个Route Predicate工厂可以合并,也可以通过逻辑合并and。
Predicate 来源于 Java 8,是 Java 8 中引入的一个函数,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。可以用于接口请求参数校验、判断新老数据是否有变化需要进行更新操作。
在 Spring Cloud Gateway 中 Spring 利用 Predicate 的特性实现了各种路由匹配规则,有通过 Header、请求参数等不同的条件来进行作为条件匹配到对应的路由。网上有一张图总结了 Spring Cloud 内置的几种 Predicate 的实现。

spring:
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true ##会使用serviceId转发到具体的服务IP上的服务
routes:
- id: after_route
uri: https://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
- Before=2017-01-20T17:42:47.789-07:00[America/Denver]
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
- Cookie=chocolate, ch.p
- Header=X-Request-Id, \d+
- Host=**.somehost.org,**.anotherhost.org
- Method=GET
- Path=/foo/{segment},/bar/{segment}
- Query=baz
- RemoteAddr=192.168.1.1/24
- id: weight_high
uri: https://weighthigh.org
predicates:
- Weight=group1, 8
- id: weight_low
uri: https://weightlow.org
predicates:
- Weight=group1, 2
spring.cloud.gateway.discovery.locator.enabled:使用eurake注册服务后:是否与服务发现组件ID进行结合,通过routes中的serviceId 转发python到具体的服务实例。
默认为false,设为true便开启通过服务中心的自动根据 serviceId 创建路由的功能。
- 后路线断言工厂:After=2017年1月20日17:42山区时间(丹佛)之后的所有请求匹配
- 路线断言工厂之前:Before=2017年1月20日17:42山区时间(丹佛)之前的所有请求匹配。
- 路线断言工厂之间- Between=2017年1月20日山区时间(丹佛)之后和2017年1月21日17:42山区时间(丹佛)之后的所有请求匹配
- Cookie路线断言工厂 Cookie=请求匹配一个名为chocolatewho的值为ch.p正则表达式匹配的cookie
- 标头路由断言工厂 - Header=匹配请求具有名为X-Request-Id其值为\d+正则表达式匹配(具有一个或多个数字的值)的标头
- 主机路由断言工厂 - Host=请求的Host标头中包含值www.somehost.org或beta.somehost.org,则此路由将匹配www.anotherhost.org
- 方法路线断言工厂 - Method=此路由将匹配GET方式的请求
- 路径路线断言工厂 - Path=将匹配:/foo/1或/foo/bar或/bar/baz
- 查询路由断言工厂 - Query=匹配请求包含baz查询参数
- RemoteAddr路由断言工厂 - RemoteAddr=请求的远程地址为192.168.1.1/24之间的IP,则此路由将匹配192.168.1.10
- 权重路线断言工厂 将约80%的流量转发至weighthigh.org,并将约20%的流量转发至weightlow.org
全局过滤器
该GlobalFilter接口具有与相同的签名GatewayFilter。这些是特殊过滤器,有条件地应用于所有路由。(此界面和用法可能会在将来的里程碑中更改)。
全局过滤器和GatewayFilter的组合订购
当请求进入(并与路由匹配)时,过滤Web处理程序会将的所有实例GlobalFilter和所有特定GatewayFilter于路由的实例添加到过滤器链中。该组合的过滤器链按org.springframework.core.Ordered接口排序,可以通过实现该getOrder()方法进行设置。
由于Spring Cloud Gateway区分了执行过滤器逻辑的“前”阶段和“后”阶段(请参阅:工作原理),因此优先级最高的过滤器将在“前”阶段中处于第一个阶段,而在“后”阶段中处于最后一个阶段“-相。
ExampleConfiguration.java
//放入application启动类中main方法后面即可
@Bean
public CustomGlobalFilter tokenFilter() {
return new CustomGlobalFilter();
}
/**
* @program: spring-gateway
* @description: 全局过滤器
* @author: Bamboo zjcjava@163.com
* @create: 2019-10-26 23:06
**/
public class CustomGlobalFilter implements GlobalFilter, Ordered {
private static final Logger log = LoggerFactory.getLogger(CustomGlobalFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("custom global filter.....................................");
// 添加全局鉴权
String token = exchange.getRequest().getQueryParams().getFirst("token");
if (token == null || token.isEmpty()) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -1;
}
}
这里我创建了一个全局的鉴权过滤器,只有参数中带有token值才能继续,否则提示无权访问
http://localhost:8080/zjcjava?token=aa
fGatewayFilter工厂
路由过滤器允许以某种方式修改传入的HTTP请求或传出的HTTP响应。路由过滤器适用于特定路由。Spring Cloud Gateway包括许多内置的GatewayFilter工厂。
filters配置
修改配置文件如下:抓哟是 path,filters
server:
port: 8080
spring:
application:
name: spring-cloud-gateway
cloud:
gateway:
routes:
- id: bamboo_route
uri: https://blog.csdn.net/
predicates:
# - Path=/blogdevteam
- Path=/test/blogdevteam
filters:
- StripPrefix=1 #去掉前缀
- AddResponseHeader=X-Response-Default-Foo, Default-Bar #返回消息头添加head信息
StripPrefix=1 #去掉第1个前缀以/分割
AddResponseHeader返回报文消息头添加head信息
这里只列举几个重要的过滤器
Hystrix GatewayFilter工厂
Hystrix是Netflix的一个库,用于实现断路器模式。Hystrix GatewayFilter允许您将断路器引入网关路由,保护您的服务免受级联故障的影响,并允许您在下游故障的情况下提供后备响应。
要在项目中启用Hystrix GatewayFilters,请spring-cloud-starter-netflix-hystrix从Spring Cloud Netflix添加依赖项。
Hystrix GatewayFilter工厂需要一个name参数,它是的名称HypythonstrixCommand。
spring:
cloud:
gateway:
routes:
- id: hystrix_route
uri: https://example.org
filters:
- Hystrix=myCommandName
这会将其余的过滤器包装在HystrixCommand带有命令名的中myCommandName。
Hystrix过滤器还可以接受可选fallbackUri参数。当前,仅forward:支持计划的URI。如果调用了后备,则请求将被转发到与URI相匹配的控制器。
限流RequestRateLimiter GatewayFilter工厂
RequestRateLimiter GatewayFilter Factory使用一种RateLimiter实现来确定是否允许继续当前请求。如果不是,HTTP 429 - Too Many Requests则返回状态(默认)。
此过滤器采用一个可选keyResolver参数和特定于速率限制器的参数(请参见下文)。
keyResolver是实现KeyResolver接口的bean 。在配置中,使用SpEL按名称引用bean。#{@myKeyResolver}是SpEL表达式,它引用名称为的bean myKeyResolver。
Redis RateLimiter
redis实现基于Stripe所做的工作。它需要使用spring-boot-starter-data-redis-reactiveSpring Boot启动器。
使用的算法是令牌桶算法。
该redis-rate-limiter.replenishRate是多么的每秒许多请求你希望用户被允许做,没有任何下降的请求。这是令牌桶被填充的速率。
redis-rate-limiter.burstCapacity是允许用户在一个单一的第二做请求的最大数目。这是令牌桶可以容纳的令牌数。将此值设置为零将阻止所有请求。
通过在replenishRate和中设置相同的值,可以达到稳定的速率burstCapacity。设置burstCapacity大于可以允许临时爆发replenishRate。在这种情况下,速率限制器需要在突发之间间隔一段时间(根据replenishRate),因为2个连续的突发将导致请求丢失(HTTP 429 - Too Many Requests)。
application.yml
spring:
cloud:
gateway:
routes:
- id: requestratelimiter_route
uri: https://example.org
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
配置文件
@Bean
KeyResolver userKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}
这定义了每个用户10的请求速率限制。允许20个并发,但是下一秒只有10个请求可用。这KeyResolver是一个简单的获取user请求参数的参数(注意:不建议在生产中使用)。
速率限制器也可以定义为实现RateLimiter接口的Bean 。在配置中,使用SpEL按名称引用bean。#{@myRateLimiter}是SpEL表达式,它引用名称为的bean myRateLimiter。
application.yml
spring:
cloud:
gateway:
routes:
- id: requestratelimiter_route
www.devze.com uri: https://example.org
filters:
- name: RequestRateLimiter
args:
rate-limiter: "#{@myRateLimiter}"
key-resolver: "#{@userKeyResolverWkvbF}"
参考文档
官方参考文档:
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.0.RC1/reference/html/
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。
加载中,请稍侯......
精彩评论