SpringCloud(四)GateWay网关
GateWay网关
概述简介
Gateway是在 Spring生态系统之上构建的AP网关服务,基于 Spring5, Spring Boot2和 Project Reactor等技术。
Gateway旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤器功能,例如:熔断、限流、重试等
官网地址:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.2.RELEASE/reference/html/

SpringCloud Gateway是 Spring Cloud的个全新项目,基于 Spring5.0+ Spring Boot2.0和 Project Reactor等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的API路由管理方式
SpringCloud Gateway作为 Spring Cloud生态系统中的网关,目标是替代zuul,在 Spring Cloud2.0以上版本中,没有对新版本的zuul2.0以上最新高性能版本进行集成,仍然还是使用的zuul1.×非 Reactor模式的老版本。Spring Cloud Gateway使用的 Webflux中的 reactor-netty响应式编程组件,底层使用了 Netty通讯框架
Spring Cloud Gateway的目标提供统-的路由方式且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流
主要特点
作用:反向代理,鉴权,流量控制,熔断,日志监控
- 基于 Spring Framework5, Project Reactor和 Spring Boot2.0进行构建
- 动态路由:能够匹配任何请求属性
- 可以对路由指定 Predicate(断言)和 Filter(过滤器)
- 集成 Hystrix的断路器功能
- 集成 Spring Cloud服务发现功能
- 请求限流功能
- 支持路径重写
三大核心概念
Route(路由)
路由是构建网关的基本模块,它由 ID,目标URI,一系列的断言和过滤器组成,如果断言为 true 则匹配该路由
Predicate(断言)
开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由
Filter(过滤)
指的是 Spring框架中 Gateway Filter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改
web请求,通过一些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制,predicate就是我们的匹配条件,而 Filter ,就可以理解为个无所不能的拦截器有了这两个元素,再加上目标 uri 就可以实现一个具体的路由了

客户端向 Spring Cloud Gateway 发出请求,然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web handler,Handler再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回,过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前("pre")或之后("post")执行业务逻辑
Filter在"pre"类型的过滤器可以做参数校验、权限校验、流量监控、日志输岀、协议转换等,在"post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用
路由配置
- 创建一个新的 module
- 导入 GateWay 依赖
<!-- Gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>2.2.2.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</exclusion>
</exclusions>
</dependency>
- 配置路由映射
- 第一种配置方式:在配置文件 yml 中配置
server:
port: 9527
spring:
application:
name: GateWay-Service
cloud:
gateway:
routes:
# 路由的 ID,没有固定规则但要求唯一,建议配合服务名
- id: payment-route1
# 匹配后提供服务的路由地址
uri: http://localhost:8001
# 断言,路径相匹配的进行路由
# 配置服务端的方法路径
predicates:
- Path=/payment/query/**
- id: payment-route2
uri: http://localhost:8001
predicates:
- Path=/payment/discovery/**
# Eureka
eureka:
client:
# 表示是否将自己注册到 EurekaServer
register-with-eureka: true
# 是否从 EurekaServer 抓取已有的注册信息
# 单节点无所谓,集群必须设置为 true 才能配合 ribbon 使用
fetch-registry: true
service-url:
# 单机版
# defaultZone: http://localhost:7001/eureka/
# 集群版
defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7002/eureka
instance:
hostname: GateWay-Service

- 第二种配置方式:自定义配置文件
@Configuration
public class GateConfig {
/**
* 测试通过网关 跳转到 百度新闻 的页面 http://news.baidu.com/guonei
* 配置了一个 id 为 payment-route3 的路由规则
* 当访问地址为 http://localhost:9527/guonei 会自动转发到 http://news.baidu.com/guonei
* @param routeLocatorBuilder
* @return
*/
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder){
return routeLocatorBuilder.routes()
.route( "payment-route3",r -> {
return r.path("/guonei")
.uri("http://news.baidu.com/guonei");
})
.build();
}
}

动态路由
默认情况下 Gateway会根据注册中心注册的服务列表,以注册中心上微服名为路径创建动态路由进行转发,从而实现动态路由的功能
配置 yml 配置文件
需要注意的是 uri 的协议为lb,表示启用 Gateway的负载均衡功能
lb://service Name 是spring cloud gateway在微服务中自动为我们创建的负载均衡uri
spring:
application:
name: GateWay-Service
cloud:
gateway:
discovery:
locator:
# 开启从注册中心动态创建路由的功能,利用微服务名进行路由
enabled: true
routes:
# 路由的 ID,没有固定规则但要求唯一,建议配合服务名
- id: payment-route1
# 匹配后提供服务的路由地址
# uri: http://localhost:8001 不能写死
# 匹配 服务端 的路由地址,就是微服务名
uri: lb://provider-payment-service
# 断言,路径相匹配的进行路由
# 配置服务端的方法路径
predicates:
- Path=/payment/lb/**
- id: payment-route2
uri: lb://provider-payment-service
predicates:
- Path=/payment/query/**
开启两个服务端8001和8002
实现了动态路由,可以测试到此时端口可以互相切换
Predicate使用
当开启路由网关时

SpringCloud Gateway 将路由匹配作为 Spring WebFlux HandlerMapping基础架构的部分
SpringCloud Gateway 包括许多内置的 RoutePredicate 工厂。所有这些Predicate都与HTTP请求的不同属性匹配,多个Route Predicate工厂可以进行组合
Spring Cloud Gateway创建 Route对象时,使用 RoutePredicate Factory创建 Predicate对象, Predicate对象可以赋值给Route. Spring Cloud Gateway包含许多内置的 Route predicate factories
所有这些谓词都匹配HTTP请求的不同属性。多种谓词工厂可以组合,并通过逻辑and组合
常用的 Route Predicate
After
路由规则可以匹配一个时间,设置在{arg}之后,当请求的时间在配置时间之后,才会交给 route 去处理
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- After=2021-01-20T17:42:47.789-07:00[China/Shanghai]
Before
路由规则可以匹配一个时间,设置在{arg}之前,当请求的时间在配置时间之前,才会交给 route 去处理
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- Before=2021-01-20T17:42:47.789-07:00[China/Shanghai]
Between
路由规则可以匹配一个时间,设置在{arg}之间,当请求的时间在配置时间之间,才会交给 route 去处理
spring:
cloud:
gateway:
routes:
- id: between_route
uri: https://example.org
predicates:
- Between=2021-01-20T17:42:47.789-07:00[China/Shanghai], 2021-01-21T17:42:47.789-07:00[China/Shanghai]
Cookie
需要2个参数,一个是cookie名字,另一个是值,可以为正则表达式。它用于匹配请求中,带有该名称的cookie和cookie匹配正则表达式的请求
spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: https://example.org
predicates:
- Cookie=name, zhangsan
# 例
# 请求带有cookie名为name, cookie值为 zhangsan 的请求
# 将都会转发到uri为 https://example.org 的地址上
# curl 请求
# $ curl -H ‘Cookie:name=zhangsan’ localhost:8081
不带cookie访问

带cookie访问

Header
在上面的配置中,当请求的 Header 中有 X-Request-Id的header名,且header值为数字时,请求会被路由到配置的 uri
spring:
cloud:
gateway:
routes:
- id: header_route
uri: https://example.org
predicates:
- Header=X-Request-Id, \d+
# 例
# $ curl -H ‘X-Request-Id:1’ localhost:8081

Host
需要一个参数即hostname,它可以使用 . 或者 * 等去匹配host。这个参数会匹配请求头中的host的值,一致,则请求正确转发
spring:
cloud:
gateway:
routes:
- id: host_route
uri: https://example.org
predicates:
- Host=**.somehost.org,**.anotherhost.org
# 如果请求的主机标头的值为
www.somehost.org
或 beta.somehost.org
或 www.anotherhost.org
# 则此路由匹配
# curl 请求
# curl -H ‘Host:www.adou.com’ localhost:8081

Method
如果请求方法是GET或POST,则此路由匹配
spring:
cloud:
gateway:
routes:
- id: method_route
uri: https://example.org
predicates:
- Method=GET,POST
Path
当请求路径满足 /red/** ,则会经过 route 到达 https://example.org
spring:
cloud:
gateway:
routes:
- id: path_route
uri: https://example.org
predicates:
- Path=/red/**
Query
也可以只填一个参数,填一个参数时,则只匹配参数名,当请求中请求参数包含 green,则会经过 route 到达 https://example.org
spring:
cloud:
gateway:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=green
- Query=color, green
# 配置了请求中含有参数color,并且color的值匹配green.,则请求命中路由
# curl 请求
# $ curl localhost:8081?color=green
RemoterAddr
请求远程地址,则会经过 route
spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: https://example.org
predicates:
- RemoteAddr=192.168.1.1/24
# 如果请求的远程地址是 192.168.1.10 ,则此路由匹配
Weight
权重采用两个参数匹配 group 和 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
# 这条路线会将大约80%的流量转发到 weighthigh.org
# 将大约20%的流量转发到 weightlow.org
说白了, Predicate就是为了实现一组匹配规则,让请求过来找到对应的 Route进行处理
Filter使用
路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用
Spring Cloud Gateway内置了多种路由过滤器,他们都由 GatewayFilter 的工厂类来产生
种类:GateWayFilter,GlobalFilter
自定义过滤器
自定义全局GlobalFilter
主要继承两个接口:GlobalFilter,Ordered
作用:全局日志记录,统一网关鉴权等等
@Component
@Slf4j
public class LogGateWayFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 获取请求的参数
String username = exchange.getRequest().getQueryParams().getFirst("username");
if (username == null){
log.info("用户名为空,找不到该用户");
// 设置状态码
exchange.getResponse().setStatusCode(HttpStatus.NOT_FOUND);
return exchange.getResponse().setComplete();
}
// 返回
log.info("进入拦截器");
return chain.filter(exchange);
}
/**
* 加载过滤器的顺序
* @return
*/
@Override
public int getOrder() {
return 0;
}
}

SpringCloud(四)GateWay网关的更多相关文章
- SpringCloud:gateway网关模块启动报错
1.错误信息 org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with na ...
- SpringCloud使用GateWay网关前端请求请求跨域处理
增加配置类 CorsConfig.java import org.springframework.context.annotation.Bean; import org.springframework ...
- Spring Cloud gateway 网关四 动态路由
微服务当前这么火爆的程度,如果不能学会一种微服务框架技术.怎么能升职加薪,增加简历的筹码?spring cloud 和 Dubbo 需要单独学习.说没有时间?没有精力?要学俩个框架?而Spring C ...
- SpringCloud + Consul服务注册中心 + gateway网关
1 启动Consul 2 创建springcloud-consul项目及三个子模块 2.1 数据模块consul-producer 2.2 数据消费模块consul-consumer 2.3 ga ...
- 实战四:Gateway网关作全局路由转发
Gateway网关的作用主要是两个:路由转发,请求过滤.此篇讲的是路由转发,下篇介绍请求过滤. 一,创建网关module,添加依赖 1,new -> module -> maven 或直接 ...
- Spring Cloud实战 | 第十一篇:Spring Cloud Gateway 网关实现对RESTful接口权限控制和按钮权限控制
一. 前言 hi,大家好,这应该是农历年前的关于开源项目 的最后一篇文章了. 有来商城 是基于 Spring Cloud OAuth2 + Spring Cloud Gateway + JWT实现的统 ...
- JHipster生成微服务架构的应用栈(四)- 网关微服务示例
本系列文章演示如何用JHipster生成一个微服务架构风格的应用栈. 环境需求:安装好JHipster开发环境的CentOS 7.4(参考这里) 应用栈名称:appstack 认证微服务: uaa 业 ...
- 微服务SpringCloud之GateWay路由
在前面博客学习了网关zuul,今天学下spring官方自带的网关spring cloud gateway.Zuul(1.x) 基于 Servlet,使用阻塞 API,它不支持任何长连接,如 WebSo ...
- Spring Cloud gateway 网关服务二 断言、过滤器
微服务当前这么火爆的程度,如果不能学会一种微服务框架技术.怎么能升职加薪,增加简历的筹码?spring cloud 和 Dubbo 需要单独学习.说没有时间?没有精力?要学俩个框架?而Spring C ...
随机推荐
- .NET测试--模拟框架NSubstitute
.NET测试--模拟框架NSubstitute .NET测试 NSubstitute在GitHub的开源地址:https://github.com/nsubstitute/nsubstitute/do ...
- Java数组练习(打印杨辉数组)
打印杨辉数组 package com.kangkang.array; import java.util.Scanner; public class demo02 { public static voi ...
- Java 中为什么要设计包装类
尽人事,听天命.博主东南大学硕士在读,热爱健身和篮球,乐于分享技术相关的所见所得,关注公众号 @ 飞天小牛肉,第一时间获取文章更新,成长的路上我们一起进步 本文已收录于 「CS-Wiki」Gitee ...
- Java 面向对象 04
面向对象·四级 多态的概述及其代码实现 * A:多态(polymorphic)概述 * 事物存在的多种形态 * B:多态前提 * a:要有继承关系 * b:要有方法重写 * c: 要有父类引用指向子类 ...
- git clone 提速
将类似于 git clone https://github.com/graykode/nlp-tutorial 的命令改成 https://github.com.cnpmjs.org/graykode ...
- 【Arduino学习笔记08】使用串口监视器显示数据
代码及相关说明: 1 // 示例:读取模拟输入并显示在串口监视器中 2 3 const int ANALOG_IN = 0; 4 int val = 0; 5 6 void setup(){ 7 Se ...
- 在Fedora中安装PostgreSQL并配置密码和开启远程登陆
在Fedora中安装PostgreSQL并配置密码 首先先放出官方的文档教程 :https://fedoraproject.org/wiki/PostgreSQL 我写的内容其实也八九不离十,站在一个 ...
- 痞子衡嵌入式:盘点国内Cortex-M内核MCU厂商高性能产品
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是国内Cortex-M内核MCU厂商高性能产品. 在8/16位中低端MCU领域,国内厂商的本土化产品设计以及超低价特点,使得其与国外大厂竞 ...
- C#关于个Base64,MD5,16进制的转换
1,待签名数据以UTF-8的格式转字节流,对字节流进行MD5算法得到的签名字节流,再转换为16进制字符串,即生成了数字签名. byte[] targetData = md5.ComputeHash(S ...
- @MockBean 注解后 bean成员对象为 null?
笔者在写自测的时候遇到的问题: 我想模拟一个Bean,并在之后使用Mockito打桩,于是使用了 @MockBean 注解(spring集成mockito的产物),但代码编写好了后启动测试却报Null ...