Spring Cloud Gateway 网关 组件核心是一系列的过滤器,通过这些过滤器可以将客户端发送的请求转发(路由)到对 应的服务。
补充说明&优点
- Gateway 替换了 Netflix Zuul 的一套解决方案
- 隐藏 服务的 IP/端口 等信息
- 提供统一的API路由管理方式 (url管理)
- Gateway 核心功能 过滤/路由/断言
- Gateway 也是个微服务,需要注册到 Eureka
- Route (路由) :路由信息由 ID、目标URL、一组断言、一组Filter 组成 (一般情况会通过断言进行判断 路由匹配)
- Predicate (断言) :定义匹配的 HTTP 中的任何信息(如:请求头/参数等…
- Filter (过滤器) :可在 请求/响应 进行一些业务上的处理
说明:
客户端 发出请求,如果请求与网关程序定义的路由匹配,则该请求就会被发送到网关 的微服务中进行处理,此时处理运行特定的请求过滤器链
过滤器虚线分开的原因:会在发送代理请求的 请求/响应 执行逻辑(所有 pre 过滤器逻辑先执行,然后执行 代理请求;代理请求完成后,执行 post 过滤器逻辑,进行响应)
示例
代码在 01Spring Cloud 的基础上进行编辑
-
创建新Maven工程(无骨架)
我创建的工程名称 gateway -
gateway 依赖配置 pom.xml
org.springframework.cloud spring-cloud-starter-gateway org.springframework.cloud spring-cloud-starter-netflix-eureka-client -
gateway 启动类
@SpringBootApplication @EnableDiscoveryClient // Eureka客户端 public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } } -
gateway 配置 application.yml
server : port : 10010 spring : application : name : api-gateway cloud : gateway : routes : # 路由id (随意) - id : user-service-route # 代理服务的地址 # uri: http://localhost:9091 # 方式1 固定代理 uri : lb://user-service # 方式2 动态代理 # 路由断言,可以配置的映射路径 predicates: - Path=/user/** eureka : client : service-url : defaultZone : http://localhost:10086/eureka instance : # 优先应用ip,并非 host prefer-ip-address : true注意:
- 填写路由断言的路径 不能存在空格 - Path=/user
public MyParamGatewayFilterFactory() {
super(Config.class);
}
@Override
public List
shortcutFieldOrder() { //一个参数 return Arrays.asList("params"); } @Override public GatewayFilter apply(Config config) { // 实例化 GatewayFilter.filter() // exchange - 请求属性 // chain - 提供一种委托给下一个过滤器的方法 return (exchange , chain) -> { // 前置 ServerHttpRequest request = exchange.getRequest(); // 路由包含 name参数 则执行 if (request.getQueryParams().containsKey(config.params)) { request.getQueryParams().get(config.params).forEach((v)->{ System.out.printf("局部过滤器 => %s = %sn",config.params,v); }); } public static class Config { // 对应配置在 application.yml 配置文件中的过滤参数 private String params; public String getParams() { return params; } public void setParams(String params) { this.params = params; } } } -
配置 application.yml 添加 自定义过滤器
spring : cloud : gateway : routes : # 路由id (随意) - id : user-service-route # 代理服务的地址 # uri: http://localhost:9091 # 方式1 uri : lb://user-service # 方式2 # 路由断言,可以配置的映射路径 predicates: - Path=/user/** filters: # 添加自定义过滤器 - MyParam=name说明:
- 在配置中 过滤器指定可省略 GatewayFilterFactory 后缀
- 以上对应参数是 shortcutFieldOrder()方法 返回指定参数数量的List (以上我指定返回一个参数params 的List)
-
测试
- 依次打开 Eureka、server、gateway 三个服务
- 访问 http://localhost:10010/user/1?name=Sans
访问后,控制台会打印,若参数名name不匹配,则不打印
- 填写路由断言的路径 不能存在空格 - Path=/user
public MyParamGatewayFilterFactory() {
super(Config.class);
}
@Override
public List
全局过滤器作用于所有路由, 无需其他配置!!!一般情况用于权限统一验证,安全验证等功能…
示例
说明:
- 全局过滤器 需要实现 GlobalFilter接口
- 过滤器顺序 需要实现 Ordered接口 指定数值(值越小越快
- 测试 请求是否授权 。判断是否包含 token 的请求头
-
创建 自定义全局过滤器 (我创建的MyGlobalFilter
package com.sans.gateway.filter; import org.apache.commons.lang.StringUtils; 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; @Component public class MyGlobalFilter implements GlobalFilter, Ordered { @Override public Monofilter(ServerWebExchange exchange , GatewayFilterChain chain) { System.out.println("=================全局过滤器MyGlobalFilter================="); String token = exchange.getRequest().getHeaders().getFirst("token"); if (StringUtils.isBlank(token)) { // 设置响应状态码为未授权 401 exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } return chain.filter(exchange); } @Override public int getOrder() { return 1; } } -
测试 (由于需要为请求添加请求头)
- 依次打开 Eureka、server、gateway 三个服务
- 通过 以下的IDEA内置的HTTP测试 以下有示例
说明: 请求成功会 返回数据 ;请求失败会返回401 (未授权)
IDEA内置HTTP调试
-
创建测试 HTTP请求 草稿文件
-
设置请求url测试
有示例查看使用方式等功能…
跨域:当一个请求URL的 协议/域名/端口 之间任意一个与当前页面URL不同,称为跨域
| 当前 URL | 被请求URL | 是否跨域 | 原因 | 比较 |
|---|---|---|---|---|
| http://www.test.com/ | http://www.test.com/index.html | N | - | - |
| http://www.test.com/ | https://www.test.com/index.html | Y | 协议不同 | http/https |
| http://www.test.com/ | http://www.baidu.com/ | Y | 主域名不同 | test/baidu |
| http://www.test.com/ | http://blog.test.com/ | Y | 子域名不同 | www/blog |
| http://www.test.com:8080/ | http://www.test.com:7001/ | Y | 端口号不同 | 8080/7001 |
这一跨域问题可通过 Gateway 网关服务器中配置即可。配置如下:
spring :
application :
name : api-gateway
cloud :
gateway :
globalcors :
cors-configurations :
# 代表所有访问到网关服务器上的地址
'[/**]' :
# 允许指定服务器地址访问
# allowedOrigins : * # *代表全部支持访问
allowedOrigins :
- "http://demo.sans.top"
allowedMethods :
- GET
上述配置 允许来自 http://demo.sans.top 的 GET请求 获取服务数据
官方具体了解:CORS Configuration (spring.io)
负载均衡&熔断器Gateway 默认集成 Ribbon、Hystrix (配置策略也如此)。如有其它策略配置可点击一下链接了解相关配置
- Spring Cloud Feign
- Spring Cloud Hystrix_熔断器
- Spring Cloud Ribbon_负载均衡
| Gateway | Feign | |
|---|---|---|
| 接口入口 | 统一服务入口 | 单一微服务入口 |
| 接口安全 | 接口隐蔽应用 | 接口暴露应用 |
| 路由处理 | 可以处理 | 固有。不能处理 |
| 应用场景 | 权限检查、控制流量 | 微服务内部调用更方便 |



