springcloud(十五):Spring Cloud 终于按捺不住推出了自己的服务网关 Gateway
本文内容纲要:
-SpringCloudGateway
-快速上手
-路由规则
-Predicate介绍
-通过时间匹配
-通过Cookie匹配
-通过Header属性匹配
-通过Host匹配
-通过请求方式匹配
-通过请求路径匹配
-通过请求参数匹配
-通过请求ip地址进行匹配
-组合使用
-总结
-参考
Spring官方最终还是按捺不住推出了自己的网关组件:SpringCloudGateway,相比之前我们使用的Zuul(1.x)它有哪些优势呢?Zuul(1.x)基于Servlet,使用阻塞API,它不支持任何长连接,如WebSockets,SpringCloudGateway使用非阻塞API,支持WebSockets,支持限流等新特性。
SpringCloudGateway
SpringCloudGateway是SpringCloud的一个全新项目,该项目是基于Spring5.0,SpringBoot2.0和ProjectReactor等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的API路由管理方式。
SpringCloudGateway作为SpringCloud生态系统中的网关,目标是替代NetflixZuul,其不仅提供统一的路由方式,并且基于Filter链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。
相关概念:
- Route(路由):这是网关的基本构建块。它由一个ID,一个目标URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配。
- Predicate(断言):这是一个Java8的Predicate。输入类型是一个ServerWebExchange。我们可以使用它来匹配来自HTTP请求的任何内容,例如headers或参数。
- Filter(过滤器):这是
org.springframework.cloud.gateway.filter.GatewayFilter
的实例,我们可以使用它修改请求和响应。
工作流程:
客户端向SpringCloudGateway发出请求。如果GatewayHandlerMapping中找到与请求相匹配的路由,将其发送到GatewayWebHandler。Handler再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。
过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。
SpringCloudGateway的特征:
- 基于SpringFramework5,ProjectReactor和SpringBoot2.0
- 动态路由
- Predicates和Filters作用于特定路由
- 集成Hystrix断路器
- 集成SpringCloudDiscoveryClient
- 易于编写的Predicates和Filters
- 限流
- 路径重写
快速上手
SpringCloudGateway网关路由有两种配置方式:
- 在配置文件yml中配置
- 通过
@Bean
自定义RouteLocator,在启动主类Application中配置
这两种方式是等价的,建议使用yml方式进配置。
使用SpringCloudFinchley版本,Finchley版本依赖于SpringBoot2.0.6.RELEASE。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
<relativePath/><!--lookupparentfromrepository-->
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
经测试Finchley.RELEASE有bug多次请求会报空指针异常,SR2是SpringCloud的最新版本。
添加项目需要使用的依赖包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
SpringCloudGateway是使用netty+webflux实现因此不需要再引入web模块。
我们先来测试一个最简单的请求转发。
server:
port:8080
spring:
cloud:
gateway:
routes:
-id:neo_route
uri:http://www.ityouknow.com
predicates:
-Path=/spring-cloud
各字段含义如下:
- id:我们自定义的路由ID,保持唯一
- uri:目标服务地址
- predicates:路由条件,Predicate接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如:与,或,非)。
- filters:过滤规则,本示例暂时没用。
上面这段配置的意思是,配置了一个id为neo_route的路由规则,当访问地址http://localhost:8080/spring-cloud
时会自动转发到地址:http://www.ityouknow.com/spring-cloud
。配置完成启动项目即可在浏览器访问进行测试,当我们访问地址http://localhost:8080/spring-cloud
时会展示页面展示如下:
证明页面转发成功。
转发功能同样可以通过代码来实现,我们可以在启动类GateWayApplication中添加方法customRouteLocator()
来定制转发规则。
@SpringBootApplication
publicclassGateWayApplication{
publicstaticvoidmain(String[]args){
SpringApplication.run(GateWayApplication.class,args);
}
@Bean
publicRouteLocatorcustomRouteLocator(RouteLocatorBuilderbuilder){
returnbuilder.routes()
.route("path_route",r->r.path("/about")
.uri("http://ityouknow.com"))
.build();
}
}
上面配置了一个id为path_route的路由,当访问地址http://localhost:8080/about
时会自动转发到地址:http://www.ityouknow.com/about
和上面的转发效果一样,只是这里转发的是以项目地址/about
格式的请求地址。
上面两个示例中uri都是指向了我的个人网站,在实际项目使用中可以将uri指向对外提供服务的项目地址,统一对外输出接口。
以上便是SpringCloudGateway最简单的两个请求示例,SpringCloudGateway还有更多实用的功能接下来我们一一介绍。
路由规则
SpringCloudGateway的功能很强大,我们仅仅通过Predicates的设计就可以看出来,前面我们只是使用了predicates进行了简单的条件匹配,其实SpringCloudGataway帮我们内置了很多Predicates功能。
SpringCloudGateway是通过SpringWebFlux的HandlerMapping
做为底层支持来匹配到转发路由,SpringCloudGateway内置了很多Predicates工厂,这些Predicates工厂通过不同的HTTP请求参数来匹配,多个Predicates工厂可以组合使用。
Predicate介绍
Predicate来源于Java8,是Java8中引入的一个函数,Predicate接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如:与,或,非)。可以用于接口请求参数校验、判断新老数据是否有变化需要进行更新操作。
在SpringCloudGateway中Spring利用Predicate的特性实现了各种路由匹配规则,有通过Header、请求参数等不同的条件来进行作为条件匹配到对应的路由。网上有一张图总结了SpringCloud内置的几种Predicate的实现。
说白了Predicate就是为了实现一组匹配规则,方便让请求过来找到对应的Route进行处理,接下来我们接下SpringCloudGateWay内置几种Predicate的使用。
通过时间匹配
Predicate支持设置一个时间,在请求进行转发的时候,可以通过判断在这个时间之前或者之后进行转发。比如我们现在设置只有在2019年1月1日才会转发到我的网站,在这之前不进行转发,我就可以这样配置:
spring:
cloud:
gateway:
routes:
-id:time_route
uri:http://ityouknow.com
predicates:
-After=2018-01-20T06:06:06+08:00[Asia/Shanghai]
Spring是通过ZonedDateTime来对时间进行的对比,ZonedDateTime是Java8中日期时间功能里,用于表示带时区的日期与时间信息的类,ZonedDateTime支持通过时区来设置时间,中国的时区是:Asia/Shanghai
。
AfterRoutePredicate是指在这个时间之后的请求都转发到目标地址。上面的示例是指,请求时间在2018年1月20日6点6分6秒之后的所有请求都转发到地址http://ityouknow.com
。+08:00
是指时间和UTC时间相差八个小时,时间地区为Asia/Shanghai
。
添加完路由规则之后,访问地址http://localhost:8080
会自动转发到http://ityouknow.com
。
BeforeRoutePredicate刚好相反,在某个时间之前的请求的请求都进行转发。我们把上面路由规则中的After改为Before,如下:
spring:
cloud:
gateway:
routes:
-id:after_route
uri:http://ityouknow.com
predicates:
-Before=2018-01-20T06:06:06+08:00[Asia/Shanghai]
就表示在这个时间之前可以进行路由,在这时间之后停止路由,修改完之后重启项目再次访问地址http://localhost:8080
,页面会报404没有找到地址。
除过在时间之前或者之后外,Gateway还支持限制路由请求在某一个时间段范围内,可以使用BetweenRoutePredicate来实现。
spring:
cloud:
gateway:
routes:
-id:after_route
uri:http://ityouknow.com
predicates:
-Between=2018-01-20T06:06:06+08:00[Asia/Shanghai],2019-01-20T06:06:06+08:00[Asia/Shanghai]
这样设置就意味着在这个时间段内可以匹配到此路由,超过这个时间段范围则不会进行匹配。通过时间匹配路由的功能很酷,可以用在限时抢购的一些场景中。
通过Cookie匹配
CookieRoutePredicate可以接收两个参数,一个是Cookiename,一个是正则表达式,路由规则会通过获取对应的Cookiename值和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行。
spring:
cloud:
gateway:
routes:
-id:cookie_route
uri:http://ityouknow.com
predicates:
-Cookie=ityouknow,kee.e
使用curl测试,命令行输入:
curlhttp://localhost:8080--cookie"ityouknow=kee.e"
则会返回页面代码,如果去掉--cookie"ityouknow=kee.e"
,后台汇报404错误。
通过Header属性匹配
HeaderRoutePredicate和CookieRoutePredicate一样,也是接收2个参数,一个header中属性名称和一个正则表达式,这个属性值和正则表达式匹配则执行。
spring:
cloud:
gateway:
routes:
-id:header_route
uri:http://ityouknow.com
predicates:
-Header=X-Request-Id,\d+
使用curl测试,命令行输入:
curlhttp://localhost:8080-H"X-Request-Id:666666"
则返回页面代码证明匹配成功。将参数-H"X-Request-Id:666666"
改为-H"X-Request-Id:neo"
再次执行时返回404证明没有匹配。
通过Host匹配
HostRoutePredicate接收一组参数,一组匹配的域名列表,这个模板是一个ant分隔的模板,用.
号作为分隔符。它通过参数中的主机地址作为匹配规则。
spring:
cloud:
gateway:
routes:
-id:host_route
uri:http://ityouknow.com
predicates:
-Host=**.ityouknow.com
使用curl测试,命令行输入:
curlhttp://localhost:8080-H"Host:www.ityouknow.com"
curlhttp://localhost:8080-H"Host:md.ityouknow.com"
经测试以上两种host均可匹配到host_route路由,去掉host参数则会报404错误。
通过请求方式匹配
可以通过是POST、GET、PUT、DELETE等不同的请求方式来进行路由。
spring:
cloud:
gateway:
routes:
-id:method_route
uri:http://ityouknow.com
predicates:
-Method=GET
使用curl测试,命令行输入:
#curl默认是以GET的方式去请求
curlhttp://localhost:8080
测试返回页面代码,证明匹配到路由,我们再以POST的方式请求测试。
#curl默认是以GET的方式去请求
curl-XPOSThttp://localhost:8080
返回404没有找到,证明没有匹配上路由
通过请求路径匹配
PathRoutePredicate接收一个匹配路径的参数来判断是否走路由。
spring:
cloud:
gateway:
routes:
-id:host_route
uri:http://ityouknow.com
predicates:
-Path=/foo/{segment}
如果请求路径符合要求,则此路由将匹配,例如:/foo/1或者/foo/bar。
使用curl测试,命令行输入:
curlhttp://localhost:8080/foo/1
curlhttp://localhost:8080/foo/xx
curlhttp://localhost:8080/boo/xx
经过测试第一和第二条命令可以正常获取到页面返回值,最后一个命令报404,证明路由是通过指定路由来匹配。
通过请求参数匹配
QueryRoutePredicate支持传入两个参数,一个是属性名一个为属性值,属性值可以是正则表达式。
spring:
cloud:
gateway:
routes:
-id:query_route
uri:http://ityouknow.com
predicates:
-Query=smile
这样配置,只要请求中包含smile属性的参数即可匹配路由。
使用curl测试,命令行输入:
curllocalhost:8080?smile=x&id=2
经过测试发现只要请求汇总带有smile参数即会匹配路由,不带smile参数则不会匹配。
还可以将Query的值以键值对的方式进行配置,这样在请求过来时会对属性值和正则进行匹配,匹配上才会走路由。
spring:
cloud:
gateway:
routes:
-id:query_route
uri:http://ityouknow.com
predicates:
-Query=keep,pu.
这样只要当请求中包含keep属性并且参数值是以pu开头的长度为三位的字符串才会进行匹配和路由。
使用curl测试,命令行输入:
curllocalhost:8080?keep=pub
测试可以返回页面代码,将keep的属性值改为pubx再次访问就会报404,证明路由需要匹配正则表达式才会进行路由。
通过请求ip地址进行匹配
Predicate也支持通过设置某个ip区间号段的请求才会路由,RemoteAddrRoutePredicate接受cidr符号(IPv4或IPv6)字符串的列表(最小大小为1),例如192.168.0.1/16(其中192.168.0.1是IP地址,16是子网掩码)。
spring:
cloud:
gateway:
routes:
-id:remoteaddr_route
uri:http://ityouknow.com
predicates:
-RemoteAddr=192.168.1.1/24
可以将此地址设置为本机的ip地址进行测试。
curllocalhost:8080
果请求的远程地址是192.168.1.10,则此路由将匹配。
组合使用
上面为了演示各个Predicate的使用,我们是单个单个进行配置测试,其实可以将各种Predicate组合起来一起使用。
例如:
spring:
cloud:
gateway:
routes:
-id:host_foo_path_headers_to_httpbin
uri:http://ityouknow.com
predicates:
-Host=**.foo.org
-Path=/headers
-Method=GET
-Header=X-Request-Id,\d+
-Query=foo,ba.
-Query=baz
-Cookie=chocolate,ch.p
-After=2018-01-20T06:06:06+08:00[Asia/Shanghai]
各种Predicates同时存在于同一个路由时,请求必须同时满足所有的条件才被这个路由匹配。
一个请求满足多个路由的谓词条件时,请求只会被首个成功匹配的路由转发
总结
通过今天的学习发现SpringCloudGateway使用非常的灵活,可以根据不同的情况来进行路由分发,在实际项目中可以自由组合使用。同时SpringCloudGateway还有更多很酷的功能,比如Filter、熔断和限流等,下次我们继续学习SpringCloudGateway的高级功能。
示例代码-github
示例代码-码云
参考
SpringCloudGateway
SpringCloudGateway(路由)
本文内容总结:SpringCloudGateway,快速上手,路由规则,Predicate介绍,通过时间匹配,通过Cookie匹配,通过Header属性匹配,通过Host匹配,通过请求方式匹配,通过请求路径匹配,通过请求参数匹配,通过请求ip地址进行匹配,组合使用,总结,参考,
原文链接:https://www.cnblogs.com/ityouknow/p/10141740.html