微服务网关Gateway实践总结
有多少请求,被网关截胡;
一、Gateway简介
微服务架构中,网关服务通常提供动态路由,以及流量控制与请求识别等核心能力,在之前的篇幅中有说过Zuul组件的使用流程,但是当下Gateway组件是更常规的选择,下面就围绕Gateway的实践做详细分析;
从架构模式上看,网关不管采用什么技术组件,都是在客户端与业务服务中间提供一层拦截与校验的能力,但是相比较Zuul来说,Gateway提供了更强大的功能和卓越的性能;
基于实践的场景来看,在功能上网关更侧重请求方的合法校验,流量管控,以及IP级别的拦截,从架构层面看,通常需要提供灵活的路由机制,比如灰度,负载均衡的策略等,并基于消息机制,进行系统级的安全通知等;
下面围绕客户端、网关层、门面服务的三个节点,分析Gateway的使用细节,即客户端向网关发出请求,经过网关路由到门面服务处理;
二、动态路由
1、基础概念
路由:作为网关中最核心的能力,从源码结构上看,包括ID、请求URI、断言集合、过滤集合等组成;
public class RouteDefinition {
private String id;
private URI uri;
private List<PredicateDefinition> predicates = new ArrayList<>();
private List<FilterDefinition> filters = new ArrayList<>();
}
断言+过滤:通常在断言中定义请求的匹配规则,在过滤中定义请求的处理动作,结构上看都是名称加参数集合,并且支持快捷的方式配置;
public class PredicateDefinition {
private String name;
private Map<String, String> args = new LinkedHashMap<>();
}
public class FilterDefinition {
private String name;
private Map<String, String> args = new LinkedHashMap<>();
}
2、配置路由
以配置的方式,添加facade
服务路由,以路径匹配的方式,如果请求路径错误则断言失败,StripPrefix设置为1,即在过滤中去掉第一个/facade
参数;
spring:
application:
name: gateway
cloud:
gateway:
routes:
- id: facade
uri: http://127.0.0.1:8082
predicates:
- Path=/facade/**
filters:
- StripPrefix=1
执行原理如下:
这里是以配置文件的方式,设置facade
服务的路由策略,其中指定了路径方式,在Gateway文档中提供了多种路由样例,比如:Header、Cookie、Method、Query、Host等断言方式;
3、编码方式
基于编码的方式管理路由策略,在Gateway文档同样提供了多种参考样例,如果路由服务少并且固定,配置的方式可以解决,如果路由服务很多,并且需要动态添加,那基于库表方式更适合;
@Configuration
public class GateConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("facade",r -> r.path("/facade/**").filters(f -> f.stripPrefix(1))
.uri("http://127.0.0.1:8082")).build();
}
}
4、库表加载
在常规的应用中,从库表中读取路由策略是比较常见的方式,定义路由工厂类并实现RouteDefinitionRepository
接口,涉及加载、添加、删除三个核心方法,然后基于服务类从库中读取数据转换为RouteDefinition
对象即可;
@Component
public class DefRouteFactory implements RouteDefinitionRepository {
@Resource
private ConfigRouteService routeService ;
// 加载
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
return Flux.fromIterable(routeService.getRouteDefinitions());
}
// 添加
@Override
public Mono<Void> save(Mono<RouteDefinition> route) {
return route.flatMap(routeDefinition -> { routeService.saveRouter(routeDefinition);
return Mono.empty();
});
}
// 删除
@Override
public Mono<Void> delete(Mono<String> idMono) {
return idMono.flatMap(routeId -> { routeService.removeRouter(routeId);
return Mono.empty();
});
}
}
在源码仓库中采用的就是库表管理的方式,代码逻辑的更多细节可以移步Git参考,此处不再过多粘贴;
三、自定义路由策略
- 自定义断言,继承
AbstractRoutePredicateFactory
类,注意命名以RoutePredicateFactory
结尾,重写apply
方法,即可执行特定的匹配规则;
@Component
public class DefCheckRoutePredicateFactory extends AbstractRoutePredicateFactory<DefCheckRoutePredicateFactory.Config> {
public DefCheckRoutePredicateFactory() {
super(Config.class);
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return new GatewayPredicate() {
@Override
public boolean test(ServerWebExchange serverWebExchange) {
log.info("DefCheckRoutePredicateFactory:" + config.getName());
return StrUtil.equals("butte",config.getName());
}
};
}
@Data
public static class Config { private String name; }
@Override
public List<String> shortcutFieldOrder() { return Collections.singletonList("name"); }
}
- 自定义过滤,继承
AbstractNameValueGatewayFilterFactory
类,注意命名以GatewayFilterFactory
结尾,重写apply
方法,即可执行特定的过滤规则;
@Component
public class DefHeaderGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
@Override
public GatewayFilter apply(AbstractNameValueGatewayFilterFactory.NameValueConfig config) {
return (exchange, chain) -> {
log.info("DefHeaderGatewayFilterFactory:"+ config.getName() + "-" + config.getValue());
return chain.filter(exchange);
};
}
}
- 配置加载方式,此处断言与过滤即快捷的配置方式,所以在命名上要遵守Gateway的约定;
spring:
cloud:
gateway:
routes:
- id: facade
uri: http://127.0.0.1:8082
predicates:
- Path=/facade/**
- DefCheck=butte
filters:
- StripPrefix=1
- DefHeader=cicada,smile
通常来说,在应用级的系统中都需要进行断言和过滤的策略自定义,以提供业务或者架构层面的支撑,完成更加细致的规则校验,尤其在相同服务多版本并行时,可以更好的管理路由策略,从而避免分支之间的影响;
四、全局过滤器
在路由中采用的过滤是GatewayFilter
,实际Gateway中还提供了GlobalFilter
全局过滤器,虽然从结构上看十分相似,但是其职责是有本质区别的;
- 全局过滤器1:打印请求ID
@Component
@Order(1)
public class DefOneGlobalFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("request-id:{}",exchange.getRequest().getId()) ;
return chain.filter(exchange);
}
}
- 全局过滤器2:打印请求URI
@Component
@Order(2)
public class DefTwoGlobalFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("request-uri:{}",exchange.getRequest().getURI()) ;
return chain.filter(exchange);
}
}
Gateway网关作为微服务架构系统中最先接收请求的一层,可以定义许多策略来保护系统的安全,比如高并发接口的限流,第三方授权验证,遭到恶意攻击时的IP拦截等等,尽量将非法请求在网关中拦截掉,从而保证系统的安全与稳定。
五、参考源码
应用仓库:
https://gitee.com/cicadasmile/butte-flyer-parent
组件封装:
https://gitee.com/cicadasmile/butte-frame-parent
微服务网关Gateway实践总结的更多相关文章
- 微服务网关实战——Spring Cloud Gateway
导读 作为Netflix Zuul的替代者,Spring Cloud Gateway是一款非常实用的微服务网关,在Spring Cloud微服务架构体系中发挥非常大的作用.本文对Spring Clou ...
- 微服务网关 Spring Cloud Gateway
1. 为什么是Spring Cloud Gateway 一句话,Spring Cloud已经放弃Netflix Zuul了.现在Spring Cloud中引用的还是Zuul 1.x版本,而这个版本是 ...
- Kong 微服务网关在 Kubernetes 的实践
来源:分布式实验室译者:qianghaohao本文主要介绍将 Kong 微服务网关作为 Kubernetes (https://www.alauda.cn)集群统一入口的最佳实践,之前写过一篇文章使用 ...
- SpringCloud Gateway微服务网关实战与源码分析-上
概述 定义 Spring Cloud Gateway 官网地址 https://spring.io/projects/spring-cloud-gateway/ 最新版本3.1.3 Spring Cl ...
- 微服务网关哪家强?一文看懂Zuul, Nginx, Spring Cloud, Linkerd性能差异
导语:API Gateway是实现微服务重要的组件之一.面对诸多的开源API Gateway,如何进行选择也是架构师需要关注的焦点.本文作者对几个较大的开源API Gateway进行了压力测试,对 ...
- 王院生:Apache APISIX 微服务网关极致性能架构解析
2019 年 10 月 27 日,又拍云联合 Apache APISIX 社区举办 API 网关与高性能服务最佳实践丨Open Talk 杭州站活动,Apache APISIX PPMC 成员王院生做 ...
- SpringCloud Alibaba实战(11:引入服务网关Gateway)
源码地址:https://gitee.com/fighter3/eshop-project.git 持续更新中-- 大家好,我是三分恶. 在前面的章节中,我们已经完成了服务间的调用.统一配置等等,在这 ...
- 微服务API Gateway
翻译-微服务API Gateway 原文地址:http://microservices.io/patterns/apigateway.html,以下是使用google翻译对原文的翻译. 让我们想象一下 ...
- Bumblebee微服务网关的部署和扩展
Bumblebee是.netcore下开源基于BeetleX.FastHttpApi扩展的HTTP微服务网关组件,它的主要作用是针对WebAPI集群服务作一个集中的转发和管理:作为应用网关它提供了应用 ...
随机推荐
- 最简单的离散概率分布,伯努利分布 《考研概率论学习之我见》 -by zobol
上文讲了离散型随机变量的分布,我们从最简单的离散型分布伯努利分布讲起,伯努利分布很简单,但是在现实生活中使用的很频繁.很多从事体力工作的人,在生活中也是经常自觉地"发现"伯努利分布 ...
- BUUCTF-小明的保险箱
小明的保险箱 16进制打开可以发现存在一个RAR压缩包,压缩包里面应该就是flag文本 使用ARCHPR破解即可
- OpenSSF安全计划:SBOM将驱动软件供应链安全
在 软件成分分析(SCA)一文中,我们简单提到软件物料清单(SBOM)在安全实践中的价值. 本期文章将带你深入了解 "SBOM 无处不在"计划是什么,以及 SBOM 对未来软件供应 ...
- RPA应用场景-自动轮询汇总报表
场景概述 自动轮询汇总报表 所涉系统名称 券商披露网站 人工操作(时间/次) 36小时 所涉人工数量 1 操作频率 每月 场景流程 1.每月初机器人自动登录网站轮询36家券商披露的财务报告,并下载 2 ...
- CODING DevOps 助力中化信息打造新一代研效平台,驱动“线上中化”新未来
中化信息技术有限公司,简称"中化信息",是世界 500 强企业中国中化控股有限责任公司(简称"中国中化")的全资直属公司,依托于中国中化的信息化建设实践,建立起 ...
- Arrays.asList的使用
Arrays.asList的作用是将数组转化为list,一般是用于在初始化的时候,设置几个值进去,简化代码,省去add的部分. 示例: List<String> menuList = Ar ...
- UML图记忆技巧
什么是UML类图 Class Diagram:用于表示类.接口.实例等之间相互的静态关系 虽然名字叫类图,但类图中并不只有类 记忆技巧 UML箭头方向: 从子类指向父类 我相信 很多同学都会有和我一样 ...
- Tapdata 与星环 KunDB 完成产品兼容互认证
近日, Tapdata 实时数据即服务平台(Tapdata Real Time DaaS)与星环 KunDB 完成产品兼容互认证.经深圳钛铂数据有限公司和星环信息科技(上海)股份有限公司共同严格测 ...
- 如何用Python实现配置热加载?
背景 由于最近工作需求,需要在已有项目添加一个新功能,实现配置热加载的功能.所谓的配置热加载,也就是说当服务收到配置更新消息之后,我们不用重启服务就可以使用最新的配置去执行任务. 如何实现 下面我分别 ...
- Kafka入门实战教程(7):Kafka Streams
1 关于流处理 流处理平台(Streaming Systems)是处理无限数据集(Unbounded Dataset)的数据处理引擎,而流处理是与批处理(Batch Processing)相对应的.所 ...