Gateway
有一部分没搞明白,路过的朋友有不错的学习资料,麻烦发一下留给我学习学习
扩展
Reactor
Reactive-Programming 响应式编程、反应式编程。ES6通过Promise 引入类似的异步编程方式。
spring5 加入了响应式编程实现了Reactive、programming
WebFlux
Spring WebFlux 是 spring5.0 引入的响应式框架,区别于Spring MVC(同步阻赛I/O),它不需要依赖Servlet API ,采用异步非阻赛结构,底层基于Reactor 来实现响应式流规范。
后续在 Servlet 3.1 支持了异步非阻塞。
Spring WebFlux 不是 Spring MVC 的替代方案Spring WebFlux可以运行在 Servlet 3.1 上,主要还是应用异步非阻塞的业务。(网关 就很好的实现)
- Spring WebFlux 默认情况下使用 Netty 作为服务器
- Spring WebFlux 暂时不支持 MySQL,支持 Redis、MongoDB、PostgreSQL
- Spring WebFlux 使用的响应式流并不是用 JDK 9 提供的,而是基于 Reactor 响应式流库
- Spring WebFlux 也可以使用 Spring MVC 注解,如
@Controller ,方便在两个 Web 框架中自由转换 - Spring WebFlux 与 Spring MVC 都可以使用 Tomcat、Jetty、Undertow 等 Servlet 容器(Servlet 3.1+)
- Spring MVC 因为是使用的同步阻塞式 I/O 模型,更方便开发人员开发和测试代码;一般来说,如果 Spring MVC 能够满足的场景,就尽量不要用 Spring WebFlux
正文
Spring Cloud Gateway 是基于 Spring 5.x 、SpringBoot 2.x 、Spring WebFlux 、Reactor 实现 的网关。
Gateway 提供了统一的路由方式,基于Filter链 提供了,熔断、重试、安全、监控/指标、限流等 官网
网关提供API全托管服务,协议匹配、协议转发、安全策略(WAF)、防刷、流量、监控日志等。网关对外暴露URL或接口信息,统称为路由信息。
- 路由(route): 网关的基础部分,路由信息由一个ID、一个目的URL、一组断言工厂和一组Filter组成;路由断言为真,则URL和配置路由匹配。
- 断言(predicate): java8中的断言函数,Gateway中的断言函数输入类型是,Spring 5.0 中的
ServerWebExchange 断言函数允许开发者去定义匹配来自于Http Request 中的任何信息,比如请求头和参数等。 - 过滤器(filter): Gateway中的Filter分两种类,Gateway Filter 和 Global Filter ,过滤器会对请求和响应进行修改处理。
- Gateway客户端向
Spring Cloud Gateway 发起请求 请求被HttpWebHanderAdapter 提取组成网关对上下文,传递给DispatcherHandler - DispatcherHandler (请求分发处理器) 吧请求分发到对应的处理器,例如
RoutePredicateHandlerMapping - RoutePredicateHandlerMapping (路由断言处理映射器) 找到路由后返回对应的
FilteringWebHandler - FilteringWebHandler 负责组装Filter 链表并调用Filter执行一系列的Filter处理,然后把请求转到后端对应的代理服务,服务处理结束后,将
Response 返回到Gateway客户端
- Filter 链虚线,是过滤前,响应返回后
- Pre 类的Filter 执行完毕后,才会将请求转发到代理服务器
- Post 类的Fiter 等代理服务器吧请求处理完后才会生效
路由断言
断言可以通过 java代码的方式写成 配置类,但是这种方法,可读性,维护性比较差。 这里只记录 配置文件的实现
spring:
cloud:
gateway:
routes:
- id: baidu_route
uri: lb:http://www.baidu.com
predicates:
- Path=/baidu/test/**
After 请求在UTC 时间之后
After 路由断言 会提取一个 UTC 时间格式参数,当请求进来的时间在 配置时间之后,匹配成功
ZonedDateTime.now().minusHours(1).format(DateTimeFormatter.ISO_ ZONED_DATE_TIME);
spring:
cloud:
gateway:
routes:
- id: after_route
uri: http://baidu.com
predicates:
- After=2022-05-17T21:55:18.146+08:00[Asia/Shanghai]
Before 请求在UTC 时间之前
Before 路由断言工厂 提取一个 UTC 时间格式参数,请求访问时间在配置UTC时间之后,匹配成功
spring:
cloud:
gateway:
routes:
- id: before_route
uri: http://baidu.com
predicates:
- After=2022-05-17T21:55:18.146+08:00[Asia/Shanghai]
Between 请求在 UTC 时间之间
spring:
cloud:
gateway:
routes:
- id: between_route
uri: http://baidu.com
predicates:
- After=2022-05-17T21:55:18.146+08:00[Asia/Shanghai],
After=2022-05-18T21:55:18.146+08:00[Asia/Shanghai]
Cookie
根据cookie 的key value 来匹配
例如 Cookie key = lf value = weixiao
spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: http://baidu.com
predicates:
- Cookie=lf, weixiao
Header 请求头断言
路由工厂根据配置路由 header 信息进行断言匹配路由,匹配成功转发。
请求头中添加 X-Request-Id=Peter
spring:
cloud:
gateway:
routes:
- id: header_route
uri: http://baidu.com
predicates:
- Header=X-Request-Id, Peter
Host
访问 例如: www.lf.com
spring:
cloud:
gateway:
routes:
- id: host_route
uri: http://baidu.com
predicates:
- Host = **.lf.com
Method 请求方式
根据请求方式 get、post、update等
spring:
cloud:
gateway:
routes:
- id: method_route
uri: http://baidu.com
predicates:
- Method=GET
Query 请求中参数
例如 :localhsot ?lf=weixiao
spring:
cloud:
gateway:
routes:
- id: query_route
uri: http://baidu.com
predicates:
- Query=lf,weixiao
Path 请求路径
/lf/weixiao/** 多级匹配
/lf/weixiao/ 需要以/ 结尾 lf/weixiao 会匹配失败
spring:
cloud:
gateway:
routes:
- id: path_route
uri: http://baidu.com
predicates:
- Path=/lf/weixiao/**
Weight 权重
添加了两个/test 路由配置,把两个路由分配到同一个路由分组 分组名 group 其中60%的流量分给V1
spring:
cloud:
gateway:
routes:
- id: provider_service-v1
uri: http://baidu.com
predicates:
- Path=/test
- Weight=group, 60
- id: provider_service-v2
uri: http://cn.bing.com/
predicated:
- Path/test
- Weight=group, 40
RemoteAddr ip网段
通过 Ipv4或Ipv6 来匹配,192.168.0.1/16 网段 , 192.168.0.1 ip地址,16是子网掩码,也可以直接配置一个ip
spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: http://baidu.com
predicates:
- RemoteAddr=127.0.0.1
内置Filter
Spring Cloud Gateway 中内置很多路由过滤工厂,也可以自定义过滤工厂。路由过滤工厂允许以某种方式来修改HTTP请求,或HTTP响应。主要有七类过滤器Header、Parameter、Path、Status、Redirect跳转、Hytrix熔断、RateLimiter限流
AddRequestHeader 匹配的请求添加 Header
@Configuration
public class CommonConfiguration {
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("add_request_header_route", r ->
r.path("/addRequestHeader")
.filters(f -> f.addRequestHeader("X-Request-Id", "Peter"))
.uri("http://127.0.0.1:8080/addRequestHeader/")
).build();
}
}
AddRequestParameter 匹配请求添加请求参数
@Configuration
public class CommonConfiguration {
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("add_request_parameter_route", r ->
r.path("/addRequestParameter")
.filters(f -> f.addRequestParameter("book", "java"))
.uri("http://127.0.0.1:8080/addRequestParameter/")
).build();
}
}
RewritePath 改写请求路径
请求结尾不能是 /
访问 http://127.0.0.1:9092/foo/cache/sethelp/help.html ,路由会转发到 http://www.baidu.com/cache/sethelp/help.html ,这里相当于把 foo 前缀去掉。
@Configuration
public class CommonConfiguration {
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("rewrite_path_route", r ->
r.path("/foo/**")
.filters(f -> f.rewritePath("/foo/(?<segment>.*)", "/$\\{segment}"))
.uri("http://www.baidu.com")
).build();
}
}
AddResponseHeader 网关返回的响应添加 Header
@Configuration
public class CommonConfiguration {
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("add_response_header_route", r ->
r.path("/addResponseHeader")
.filters(f -> f.addResponseHeader("X-Request-Id", "Peter"))
.uri("http://www.baidu.com/")
).build();
}
}
StripPrefix 前缀
StripPrefixGatewayFilterFactory URL前缀去除
PrefixPathGatewayFilterFactory URL前缀增加
例如: http://localhost:8080/baidu/test 去除前缀后 访问 https://www.baidu.com 去除 了前缀 /baidu/test
spring:
cloud:
gateway:
routes:
- id: baidu_route
uri: http://www.baidu.com
predicates:
- Path=/baidu/test/**
filters:
- StripPrefix=2
Retry 重试
接口需要做幂等(同一个请求多次访问)处理。
config.setRetries(2).setStatus(INTERNAL_SERVER_ERROR) 重试2次,调用失败,返回状态码500
@Configuration
public class CommonConfiguration {
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("retry_route", r -> r.path("/test/retry")
.filters(f -> f.retry(config -> config.setRetries(2)
.setStatuses(HttpStatus.INTERNAL_SERVER_ERROR)))
.uri("http://127.0.0.1:8080/retry?key=abc&count=2"))
.build();
}
}
Hystrix 熔断
TODO
Global Filters
官网
GateWay Filter Factories 是内部定义好的过滤器,一般用的不多
Global Filters 自定义过滤规则,全局规则(生效 所有接口,路由),需要实现GlobalFilter接口、Ordered接口(顺序)
底部
|