使用 Spring cloud Gateway 构建微服务网关
云栖号资讯:【点击查看更多行业资讯】
在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来!
使用 Spring cloud Gateway 构建微服务网关
Spring Cloud Gateway 是 Spring Cloud 的一个子项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。
Spring Cloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Netflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。
相关概念
- Route(路由):网关的基本构件块,类似于 nginx 的 location 配置。由一个 ID、一个目标 URI、一组 Predicate 和一组 Filter 定义
- Predicate(断言):路由组成的一部分,主要负责路由的匹配,来决定此次请求是否匹配路由,我们可以使用它匹配来自 HTTP 请求的任何内容,比如路径、参数或者 header 信息等等
- Filter(过滤器):这个是 GatewayFilter 的实例,请求经过 Predicate 匹配路由之后执行 Filter,我们可以使用它修改请求和响应。
快速上手
Spring Cloud Gateway 网关路由有两种配置方式:
- 通过配置文件配置
- 通过 @Bean 自定义 RouteLocator 去配置
这两种方式是等价的,建议使用配置文件配置。因为 Spring Cloud Gateway 使用响应式编程框架,学习曲线相对陡峭。
引入依赖:
<properties>
<java.version>1.8</java.version>
<!-- springcloud 版本 -->
<spring-cloud.version>Hoxton.SR1</spring-cloud.version>
</properties>
<dependencies>
<!-- 服务注册发现相关 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- gateway 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
Spring cloud gateway 是使用 netty+webflux 实现,因此不需要再引入 web 模块。
配置文件:
server:
port: 8088
eureka:
client:
serviceUrl:
# 注册中心地址
defaultZone: http://dev-crm-host001.ymt.io:8761/eureka
spring:
application:
name: test-gateway
cloud:
gateway:
routes:
- id: test1
uri: http://www.baidu.com
predicates:
- Path=/baidu/**
filters:
- StripPrefix=1
各字段含义如下:
- id:我们自定义的路由 ID,保持唯一
- uri:目标服务地址,大部分场景我们是转发到某个服务上,配置 uri: lb://user-service 意思是请求要转发到注册中心的 user-service 服务上。
- predicates:路由条件,接受一个参数,返回一个布尔结果决定是否匹配。Gateway 为我们内置了多种路由条件,包括 Path、Cookie、Param、Header、Before、After 等等,开箱即用,当然我们也可以自己实现 predicates
- filters:过滤规则,当请求经过 predicate 匹配成功后,执行 filter,我们可以使用它修改请求和响应,示例表示目标服务收到的 path 将无第一级。
启动程序,当我们访问 localhost:8088/baidu 时,gateway 会根据我们配置的路由规则转发到 https://www.baidu.com
路由规则:Predicate 介绍
Spring Cloud Gateway 的功能很强大,我们仅仅通过 Predicates 的设计就可以看出来,前面我们只是使用了 predicates 进行了简单的条件匹配,Spring Cloud Gateway 内置了很多 Predicates 工厂,这些 Predicates 工厂通过不同的 HTTP 请求参数来匹配,多个 Predicates 工厂可以组合使用。
网上有一张图总结了 Spring Cloud 内置的集中 Predicate:
说白了 Predicate 就是实现了一组匹配规则,方便让请求过来找到对应的 Route 进行处理。接下来介绍一下内置几种 Predicate 的使用。
通过时间匹配
Predicate 支持设置一个时间,在请求进行转发的时候,可以通过判断在这个时间之前或者之后进行转发。比如我们现在设置只有在 2020 年 1 月 1 日才会转发到 https://www.baidu.com/,在这之前不进行转发,我就可以这样配置:
spring:
cloud:
gateway:
routes:
- id: time_route
uri: http://www.baidu.com
predicates:
- After=2020-01-01T01:01:01+08:00[Asia/Shanghai]
Spring 是通过 ZonedDateTime 来对时间进行的对比,ZonedDateTime 是 Java 8 中日期时间功能里,用于表示带时区的日期与时间信息的类,ZonedDateTime 支持通过时区来设置时间,中国的时区是:Asia/Shanghai。
Before Predicate 刚好相反,在某个时间之前的请求的请求都进行转发。我们把上面路由规则中的 After 改为 Before,如下:
spring:
cloud:
gateway:
routes:
- id: time_route
uri: http://www.baidu.com
predicates:
- Before=2020-01-01T01:01:01+08:00[Asia/Shanghai]
就表示在这个时间之前可以进行路由,在这时间之后停止路由。
除过在时间之前或者之后外,Gateway 还支持限制路由请求在某一个时间段范围内,可以使用 Between Predicate 来实现。
spring:
cloud:
gateway:
routes:
- id: after_route
uri: http://www.baidu.com
predicates:
- Between=2019-01-01T01:01:01+08:00[Asia/Shanghai], 2020-01-01T01:01:01+08:00[Asia/Shanghai]
通过 Cookie 匹配
Cookie Route Predicate 可以接收两个参数,一个是 Cookie name,一个是正则表达式。
spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: http://www.baidu.com
predicates:
- Cookie=name, ymt
通过 Header 属性匹配
Header Route Predicate 和 Cookie Route Predicate 一样,也是接收 2 个参数,一个 header 中属性名称和一个正则表达式。
spring:
cloud:
gateway:
routes:
- id: header_route
uri: http://www.baidu.com
predicates:
- Header=name, ymt
通过 Host 匹配
spring:
cloud:
gateway:
routes:
- id: host_route
uri: http://www.baidu.com
predicates:
- Host=**.baidu.com
通过 Request Method 匹配
可以通过是 POST、GET、PUT、DELETE 等不同的请求方式来进行路由。
spring:
cloud:
gateway:
routes:
- id: method_route
uri: http://www.baidu.com
predicates:
- Method=GET
通过请求路径匹配
之前示例是使用的请求路径去匹配的。
spring:
cloud:
gateway:
routes:
- id: test1
uri: http://www.baidu.com
predicates:
- Path=/baidu/**
filters:
- StripPrefix=1
通过请求参数匹配
Query Route Predicate 支持传入两个参数,一个是属性名一个为属性值,属性值可以是正则表达式。
spring:
cloud:
gateway:
routes:
- id: query_route
uri: http://www.baidu.com
predicates:
- Query=type,baidu
如上图所示,输入 localhost:8088/?type=baidu 会被转发到 https://www.baidu.com/?type=baidu
如果写成 - Query=type,这样配置,只要请求中包含 type 属性的参数即可匹配路由。
通过请求 ip 地址进行匹配
spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: http://www.baidu.com
predicates:
- RemoteAddr=192.168.1.1/24
组合使用
以上示例演示了单个 Predicate 的使用,Predicate 也可以放在一起组合使用。
spring:
cloud:
gateway:
routes:
- id: combination_route
uri: http://ityouknow.com
predicates:
- RemoteAddr=192.168.1.1/24
- Query=type,baidu
- Path=/baidu/**
各种 Predicates 同时存在于同一个路由时,请求必须同时满足所有的条件才被这个路由匹配。
一个请求满足多个路由的 Predicate 条件时,请求只会被首个成功匹配的路由转发
如何自己实现 Predicate
以上介绍了内置的 Predicate 的使用,但是在一些特殊的场景下,内置的 Predicate 可能满足不了我们的需求,这个时候我们就可以根据 Gateway 提供的接口实现自己的 Predicate。
需求背景
系统中有一些请求需要根据参数去转发,比如根据查询参数的某一个范围去转发,例如 /server?type=A,当 type 为 A、B、C 三个其中一个值时转发到 server1 服务,type 为 D、E、F 三个其中一个值时转发到 server2 服务。我们可以通过继承 org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory 实现
/**
* 工作流相关的断言
*
* @author zhangtao
* @since 2020-01-06 7:26 下午
*/
@Component
public class TypeRoutePredicateFactory extends AbstractRoutePredicateFactory<WorkFlowRoutePredicateFactory.Config> {
public WorkFlowRoutePredicateFactory() {
super(WorkFlowRoutePredicateFactory.Config.class);
}
private static final String DATETIME_KEY = "type";
@Override
public List<String> shortcutFieldOrder() {
return Collections.singletonList(DATETIME_KEY);
}
// 配置参数的类型,此时指定为List
@Override
public ShortcutType shortcutType() {
return ShortcutType.GATHER_LIST;
}
// 判断的逻辑,如果返回为true则匹配成功
@Override
public Predicate<ServerWebExchange> apply(WorkFlowRoutePredicateFactory.Config config) {
return new GatewayPredicate() {
@Override
public boolean test(ServerWebExchange exchange) {
// 判断参数中是否有配置的type
List<String> types = exchange.getRequest().getQueryParams().get("type");
if (types != null && types.size() == 1 && config.getType().contains(types.get(0))) {
return true;
}
return false;
}
};
}
@Validated
public static class Config {
private List<String> type = new ArrayList<>();
public List<String> getType() {
return type;
}
public void setType(List<String> type) {
this.type = type;
}
}
}
配置文件:
spring:
cloud:
gateway:
routes:
- id: server1-route
uri: http://www.baidu.com
predicates:
# Type为,TypeRoutePredicateFactory类 RoutePredicateFactory前面的值
- Type=A,B,C
- id: server2-route
uri: https://cn.bing.com/
predicates:
# Type为,TypeRoutePredicateFactory类 RoutePredicateFactory前面的值
- Type=D,E,F
以上配置为,当请求参数中 type 的值为 A、B、C 其中一个时则匹配成功,通过 server1-route 路由转发到 http://www.baidu.com,当请求参数中 type 的值为 D、E、F 其中一个时则匹配成功,通过 server2-route 路由转发到 https://cn.bing.com/
总结
Spring Cloud Gateway 使用非常的灵活,可以根据不同的情况来进行路由分发,在实际项目中可以自由组合使用。同时 Spring Cloud Gateway 还有更多很酷的功能,比如 Filter、熔断和限流等。
【云栖号在线课堂】每天都有产品技术专家分享!
课程地址:https://yqh.aliyun.com/live立即加入社群,与专家面对面,及时了解课程最新动态!
【云栖号在线课堂 社群】https://c.tb.cn/F3.Z8gvnK
关注公众号
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
金融投资新范式,一场人工智能技术带来的进化
云栖号资讯:【点击查看更多行业资讯】在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! 因技术变革而至的金融科技是当前的一个热门话题,在过去几年中呈现运动式发展,除了百度、阿里、腾讯等互联网公司,银行、证券、保险、基金公司等传统金融机构及其他科技企业都被卷入这场变革式洪流之中。 那么,人工智能作为金融科技的一个重要分支,在金融投资领域能起到什么样的作用?当下的真实市场需求又是怎样的?6 月 24 日,由路孚特主办的 ReFinTech 大咖直播室邀请了创新工场南京 AI 研究院执行院长、倍漾科技创始人冯霁博士 和 路孚特中国区财富管理业务发展总监赵玉成,从金融投资的业务出发,为大家分享了人工智能在金融投资领域的应用和发展。 以数据解读金融投资领域的业务场景及痛点机器学习已经成为金融机构投资决策的重要环节路孚特于 2018 年完成了从汤森路透金融与风险业务部门独立成为路孚特的转变。这家 160 多年历史的金融科技企业,为全球 190 多个国家的 4 万多家机构和 40 万用户提供金融信息服务。同时,在路孚特金融开放平台上,超过 1 万 3 千名开发者和 2200 多家合作伙伴...
-
下一篇
Kubernetes之上到底该构建什么?这些或许能给你启发
云栖号资讯:【点击查看更多行业资讯】在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! Kubernetes已经成为各种规模企业在生产环境事实上的容器编排平台,在各种应用中设置Kubernetes都是基础。 那么在Kubernetes集群之上到底要构建什么?比如,Web和API层中的无状态应用程序是很好的初始用例,Kubernetes帮助其补足了安全性,可伸缩性和开发者生产力方面的差距。但不限于此! 服务网格 建立在Kubernetes之上的微服务网络带来了分布式计算问题。尽管Kubernetes解决了服务发现,可扩展性问题,但Kubernetes生态系统需要适用于第7层流量网络的解决方案。Istio和Linkerd等服务网格为微服务带来了高级功能,例如流量控制,安全性和可观察性等。服务网格与Envoy等代理相结合,可以为微服务提供强大的安全性和网络抽象。而且,开发者和企业可以受益于通用框架的改编,从而提高了效率和生产率。 有状态的工作负载 在Kubernetes中运行有状态工作负载是一个快速发展的方向。因为Kubernetes有名为StatefulSets的内置对象,可为...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS关闭SELinux安全模块
- SpringBoot2全家桶,快速入门学习开发网站教程
- MySQL数据库中FOR UPDATE的使用
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- MySQL数据库在高并发下的优化方案
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS6,CentOS7官方镜像安装Oracle11G
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题



微信收款码
支付宝收款码