我最新最全的文章都在南瓜慢说 www.pkslow.com,欢迎大家来喝茶!

1 简介

见名知义,Spring Cloud Gateway是用于微服务场景的网关组件,它是基于Spring WebFlux,也就是Reactive的。从实现原理上,它的性能应该是比Zuul会更好。

它的工作原理如下图所示:

简单而言就是通过一连串的Filter处理匹配到特定规则Predicates的请求。所以最主要就是做了两件事:

(1)哪些请求可以被它处理,由Predicates决定;

(2)如何处理,由Filters决定。

2 路由条件判断Predicates

2.1 时间匹配After

表示在什么时间之后才算满足条件匹配路由:

spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- After=2020-01-20T17:42:47.789-07:00[America/Denver]

2.2 时间匹配Before

表示在什么时间之前匹配路由:

spring:
cloud:
gateway:
routes:
- id: before_route
uri: https://example.org
predicates:
- Before=2017-01-20T17:42:47.789-07:00[America/Denver]

2.3 时间段匹配Between

表示在什么时间段匹配路由:

spring:
cloud:
gateway:
routes:
- id: between_route
uri: https://example.org
predicates:
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]

2.4 Cookie匹配

表示通过判断Cookie的键值来匹配路由,其中值支持正则表达式:

spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: https://example.org
predicates:
- Cookie=chocolate, ch.p

2.5 请求头匹配Header

表示通过判断Http请求的Header来匹配路由:

spring:
cloud:
gateway:
routes:
- id: header_route
uri: https://example.org
predicates:
- Header=X-Request-Id, \d+

2.6 主机名匹配Host

通过判断Hostname来匹配路由:

spring:
cloud:
gateway:
routes:
- id: host_route
uri: https://example.org
predicates:
- Host=**.somehost.org,**.anotherhost.org

2.7 请求方法匹配Method

表示通过判断请求方法来匹配路由:

spring:
cloud:
gateway:
routes:
- id: method_route
uri: https://example.org
predicates:
- Method=GET,POST

2.8 请求路径匹配Path

表示通过判断请求路径来匹配路由,很常用:

spring:
cloud:
gateway:
routes:
- id: path_route
uri: https://example.org
predicates:
- Path=/red/{segment},/blue/{segment}

2.9 请求参数匹配Query

表示通过判断请求参数来匹配路由:

spring:
cloud:
gateway:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=red, gree.

2.10 IP地址匹配RemoteAddr

表示通过判断IP地址来匹配路由:

spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: https://example.org
predicates:
- RemoteAddr=192.168.1.1/24

2.11 权重匹配Weight

通过权重来匹配路由:

spring:
cloud:
gateway:
routes:
- id: weight_high
uri: https://weighthigh.org
predicates:
- Weight=group1, 8
- id: weight_low
uri: https://weightlow.org
predicates:
- Weight=group1, 2

3 功能强大的GatewayFilter

Spring提供许多强大的GatewayFilter对请求进行处理。

3.1 添加请求头

给请求添加Header

spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
predicates:
- Path=/red/{segment}
filters:
- AddRequestHeader=X-Request-Red, Blue-{segment}

3.2 添加请求参数

spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: https://example.org
predicates:
- Host: {segment}.myhost.org
filters:
- AddRequestParameter=foo, bar-{segment}

3.3 添加返回Header

spring:
cloud:
gateway:
routes:
- id: add_response_header_route
uri: https://example.org
predicates:
- Host: {segment}.myhost.org
filters:
- AddResponseHeader=foo, bar-{segment}

3.4 删除重复返回Header

spring:
cloud:
gateway:
routes:
- id: dedupe_response_header_route
uri: https://example.org
filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin

3.5 断路器Hystrix

简单配置:

spring:
cloud:
gateway:
routes:
- id: hystrix_route
uri: https://example.org
filters:
- Hystrix=myCommandName

较复杂配置:

spring:
cloud:
gateway:
routes:
- id: hystrix_route
uri: lb://backing-service:8088
predicates:
- Path=/consumingserviceendpoint
filters:
- name: Hystrix
args:
name: fallbackcmd
fallbackUri: forward:/incaseoffailureusethis
- RewritePath=/consumingserviceendpoint, /backingserviceendpoint

3.6 断路器CircuitBreaker

简单配置:

spring:
cloud:
gateway:
routes:
- id: circuitbreaker_route
uri: https://example.org
filters:
- CircuitBreaker=myCircuitBreaker

较复杂配置:

spring:
cloud:
gateway:
routes:
- id: circuitbreaker_route
uri: lb://backing-service:8088
predicates:
- Path=/consumingServiceEndpoint
filters:
- name: CircuitBreaker
args:
name: myCircuitBreaker
fallbackUri: forward:/inCaseOfFailureUseThis
- RewritePath=/consumingServiceEndpoint, /backingServiceEndpoint

3. 7 请求头改名

spring:
cloud:
gateway:
routes:
- id: map_request_header_route
uri: https://example.org
filters:
- MapRequestHeader=Blue, X-Request-Red

3.8 路径添加前缀

这个要注意和匹配路径区分,它是在匹配后再加个前缀:

spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: https://example.org
filters:
- PrefixPath=/mypath

请求/hello变成/mypath/hello

3.9 重定向

spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: https://example.org
filters:
- RedirectTo=302, https://acme.org

3.10 删除请求头

spring:
cloud:
gateway:
routes:
- id: removerequestheader_route
uri: https://example.org
filters:
- RemoveRequestHeader=X-Request-Foo

3.11 删除返回头

spring:
cloud:
gateway:
routes:
- id: removeresponseheader_route
uri: https://example.org
filters:
- RemoveResponseHeader=X-Response-Foo

3.12 删除请求参数

spring:
cloud:
gateway:
routes:
- id: removerequestparameter_route
uri: https://example.org
filters:
- RemoveRequestParameter=red

3.13 重写路径

spring:
cloud:
gateway:
routes:
- id: rewritepath_route
uri: https://example.org
predicates:
- Path=/red/**
filters:
- RewritePath=/red(?<segment>/?.*), $\{segment}

3.14 设置路径

spring:
cloud:
gateway:
routes:
- id: setpath_route
uri: https://example.org
predicates:
- Path=/red/{segment}
filters:
- SetPath=/{segment}

3.15 设置请求头

spring:
cloud:
gateway:
routes:
- id: setrequestheader_route
uri: https://example.org
predicates:
- Host: {segment}.myhost.org
filters:
- SetRequestHeader=foo, bar-{segment}

3.16 设置返回头

spring:
cloud:
gateway:
routes:
- id: setresponseheader_route
uri: https://example.org
predicates:
- Host: {segment}.myhost.org
filters:
- SetResponseHeader=foo, bar-{segment}

3.17 设置返回状态码

spring:
cloud:
gateway:
routes:
- id: setstatusstring_route
uri: https://example.org
filters:
- SetStatus=BAD_REQUEST
- id: setstatusint_route
uri: https://example.org
filters:
- SetStatus=401

3.18 去掉路径前缀

spring:
cloud:
gateway:
routes:
- id: nameRoot
uri: https://nameservice
predicates:
- Path=/name/**
filters:
- StripPrefix=2

这配置请求/name/blue/red,实际就是请求nameservice/red,去掉两个前缀。

3.19 重试Retry GatewayFilter

想不到居然还有强大的重试功能:

spring:
cloud:
gateway:
routes:
- id: retry_test
uri: http://localhost:8080/flakey
predicates:
- Host=*.retry.com
filters:
- name: Retry
args:
retries: 3
statuses: BAD_GATEWAY
methods: GET,POST
backoff:
firstBackoff: 10ms
maxBackoff: 50ms
factor: 2
basedOnPreviousValue: false

3.20 请求大小限制

spring:
cloud:
gateway:
routes:
- id: request_size_route
uri: http://localhost:8080/upload
predicates:
- Path=/upload
filters:
- name: RequestSize
args:
maxSize: 5000000

3.21 默认Filter

如果希望对所有路由都生效,可以添加默认Filter

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

4 全局Global Filters

全局过滤器GlobalFilter接口和GatewayFilter的方法是一样的,但它是用于所有路由的。当请求过来时,整个Filter Chain是包含了所有的GlobalFilters和匹配上的GatewayFilters,执行顺序由getOrder()方法决定。

如下:

@Bean
public GlobalFilter customFilter() {
return new CustomGlobalFilter();
} public class CustomGlobalFilter implements GlobalFilter, Ordered { @Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("custom global filter");
return chain.filter(exchange);
} @Override
public int getOrder() {
return -1;
}
}

5 一切皆可自定义

Spring支持开发人员自定义PredicateGatewayFilterGlobalFilter

5.1 自定义Predicate

public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<HeaderRoutePredicateFactory.Config> {

    public MyRoutePredicateFactory() {
super(Config.class);
} @Override
public Predicate<ServerWebExchange> apply(Config config) {
// grab configuration from Config object
return exchange -> {
//grab the request
ServerHttpRequest request = exchange.getRequest();
//take information from the request to see if it
//matches configuration.
return matches(config, request);
};
} public static class Config {
//Put the configuration properties for your filter here
}
}

5.2 自定义GatewayFilter

Pre的过滤器:

public class PreGatewayFilterFactory extends AbstractGatewayFilterFactory<PreGatewayFilterFactory.Config> {

    public PreGatewayFilterFactory() {
super(Config.class);
} @Override
public GatewayFilter apply(Config config) {
// grab configuration from Config object
return (exchange, chain) -> {
//If you want to build a "pre" filter you need to manipulate the
//request before calling chain.filter
ServerHttpRequest.Builder builder = exchange.getRequest().mutate();
//use builder to manipulate the request
return chain.filter(exchange.mutate().request(builder.build()).build());
};
} public static class Config {
//Put the configuration properties for your filter here
}
}

Post的过滤器:

public class PostGatewayFilterFactory extends AbstractGatewayFilterFactory<PostGatewayFilterFactory.Config> {

    public PostGatewayFilterFactory() {
super(Config.class);
} @Override
public GatewayFilter apply(Config config) {
// grab configuration from Config object
return (exchange, chain) -> {
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
ServerHttpResponse response = exchange.getResponse();
//Manipulate the response in some way
}));
};
} public static class Config {
//Put the configuration properties for your filter here
}
}

5.3 自定义GlobalFilter

@Bean
public GlobalFilter customGlobalFilter() {
return (exchange, chain) -> exchange.getPrincipal()
.map(Principal::getName)
.defaultIfEmpty("Default User")
.map(userName -> {
//adds header to proxied request
exchange.getRequest().mutate().header("CUSTOM-REQUEST-HEADER", userName).build();
return exchange;
})
.flatMap(chain::filter);
} @Bean
public GlobalFilter customGlobalPostFilter() {
return (exchange, chain) -> chain.filter(exchange)
.then(Mono.just(exchange))
.map(serverWebExchange -> {
//adds header to response
serverWebExchange.getResponse().getHeaders().set("CUSTOM-RESPONSE-HEADER",
HttpStatus.OK.equals(serverWebExchange.getResponse().getStatusCode()) ? "It worked": "It did not work");
return serverWebExchange;
})
.then();
}

6 项目使用

添加依赖:

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

配置Main启动应用:

package com.pkslow.cloud.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication
public class GatewayService {
public static void main(String[] args) {
SpringApplication.run(GatewayService.class, args);
}
}

配置路由:

server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: pkslow
uri: https://www.pkslow.com
predicates:
- Path=/pkslow/**
filters:
- RewritePath=/pkslow(?<segment>.*), /$\{segment}

启动后可正常访问了:

7 总结

Spring Cloud Gateway实在是非常强大,能满足微服务绝大多数应用场景了,还是很有必要了解一下的。

代码请查看:https://github.com/LarryDpk/pkslow-samples


参考资料:官网


欢迎关注微信公众号<南瓜慢说>,将持续为你更新...

多读书,多分享;多写作,多整理。

Spring Cloud Gateway简单入门,强大的微服务网关的更多相关文章

  1. Spring Cloud Gateway 之请求坑位[微服务IP不同请求会失败]

    问题产生背景 在使用Spring Cloud Gateway过程中,希望配置多Routes映射不同的微服务,因为Gateway 和Zuul的访问路径不同(zuul 会带有服务service Id),造 ...

  2. spring cloud深入学习(一)-----什么是微服务?什么是rpc?spring cloud简介

    近年来,微服务非常的流行,那么为什么是它?简单介绍一下. 为什么是微服务? 微服务架构是一种将单应用程序作为一套小型服务开发的方法,每种应用程序都在其自己的进程中运行,并与轻量级机制(通常是HTTP资 ...

  3. spring cloud: zuul(四): 正则表达式匹配其他微服务(给其他微服务加版本号)

    spring cloud: zuul(四): 正则表达式匹配其他微服务(给其他微服务加版本号) 比如我原来有,spring-boot-user微服务,后台进行迭代更新,另外其了一个微服务: sprin ...

  4. spring cloud Gateway简单使用

    一.引子 2年前有幸使用过一次Spring Cloud (1.5.9),那次用的是ZUUL做网关,没有使用Gateway做网关,一直是个小遗憾.终于在2年后的19年底再次使用Spring Cloud, ...

  5. springcloud(十五):Spring Cloud 终于按捺不住推出了自己的服务网关 Gateway

    Spring 官方最终还是按捺不住推出了自己的网关组件:Spring Cloud Gateway ,相比之前我们使用的 Zuul(1.x) 它有哪些优势呢?Zuul(1.x) 基于 Servlet,使 ...

  6. Spring Cloud Feign 简单入门

    Feign是一个生命是的web service 客户端,使用方式非常简单:接口+注解,spring cloud feign 对feign惊醒了增强使它支持了spring mcv注解. 示例(以下示例结 ...

  7. Spring Cloud Eureka简单入门

    步骤: 1.创建父工程 2.创建EurekaServer工程 3.创建EurekaClient工程 父工程pom.xml <?xml version="1.0" encodi ...

  8. spring boot 2.0.3+spring cloud (Finchley)8、微服务监控Spring Boot Admin

    参考:Spring Boot Admin 2.0 上手 Spring Boot Admin 用于管理和监控一个或多个Spring Boot程序,在 Spring Boot Actuator 的基础上提 ...

  9. Spring Cloud下使用Feign Form实现微服务之间的文件上传

    背景 ​ Spring Cloud现在已经被越来越多的公司采用了,微服务架构比传统意义上的单服务架构从复杂度上多了很多,出现了很多复杂的场景.比如,我们的产品是个app,支持第三方登录功能,在手机端调 ...

随机推荐

  1. vue 访问页面时报错 Failed to compile

    这个是因为node-sass没安装好,所以要重新安装 windows下运行命令:npm install node-sass --registry=https://registry.npm.taobao ...

  2. react+antd 使用脚手架动态修改主题色

    最近做了一个需求,后台管理系统添加一个可以动态修改ant-design主题色.查询了大多数的文章,发现基本都是抄来抄去,而且文章记录的也一点也不详细.刚刚把这个功能做完了,顺便记录一下如何去修改主题色 ...

  3. centos 7.6 安装最新版docker 19.03

    systemctl stop docker rpm -qa | grep docker 看到那个删除那个yum erase docker \ docker-client \ docker-client ...

  4. 【近取 Key】Alpha - v1.0 测试报告

    Bug 前端 主页.登录.注册.导航 bug说明 修复方法 修复结果 导航栏有时不显示用户姓名 修改用户信息的获取逻辑与存储方式 成功 展示词图界面导航栏居右失败 在组件中增加自适应相关设置 成功 用 ...

  5. [敏杰开发]知识路书——图形化文献管理大师 Beta版发布喽!!!

    [敏杰开发]知识路书--图形化文献管理大师 Beta版发布喽!!! 一.总览 项目名称:知识路书 发布形式:网页应用 发布地址:http://roadmap.imcoming.top 二.运行环境与使 ...

  6. 动态类型转换dynamic_cast

    C++Primer第十九章的动态类型转换部分讲的不是很清楚,于是自己查cpp的官方手册总结一下. dynamic_cast < new-type > ( expression ) 动态类型 ...

  7. 在ZOHO企业网盘中如何快速搜索文件?

    现在越来越多的企业采用企业网盘来存储文档和资料,而且现在市面上的企业网盘各种各样.在使用企业网盘过程中,很多用户会问到企业网盘中如何快速搜索文件的问题.但是无论是"标签"功能还是普 ...

  8. jQ的隐式迭代和设置样式属性

    jQ中的隐式迭代 意义:不需要原生迭代了,在jQ内部自动帮你实现了循环 代码实现: let arr = document.querySelectorAll('li') for(let i = 0;i ...

  9. KEIL中查看程序存储空间的大小

    Program Size: Code=86496 RO-data=9064 RW-data=1452 ZI-data=16116 Code是代码占用的空间,RO-data是 Read Only 只读常 ...

  10. 第六章 XaaS和IT服务标准

    从云计算(Cloud Computing)谈起 云计算是一种按使用量付费的模式,这种模式提供可用的.便捷的.按需的网络访问,进入可配置的计算资源共享池(资源包括网络,服务器,存储,应用软件,服务),这 ...