有多少请求,被网关截胡;

一、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实践总结的更多相关文章

  1. 微服务网关实战——Spring Cloud Gateway

    导读 作为Netflix Zuul的替代者,Spring Cloud Gateway是一款非常实用的微服务网关,在Spring Cloud微服务架构体系中发挥非常大的作用.本文对Spring Clou ...

  2. 微服务网关 Spring Cloud Gateway

    1.  为什么是Spring Cloud Gateway 一句话,Spring Cloud已经放弃Netflix Zuul了.现在Spring Cloud中引用的还是Zuul 1.x版本,而这个版本是 ...

  3. Kong 微服务网关在 Kubernetes 的实践

    来源:分布式实验室译者:qianghaohao本文主要介绍将 Kong 微服务网关作为 Kubernetes (https://www.alauda.cn)集群统一入口的最佳实践,之前写过一篇文章使用 ...

  4. SpringCloud Gateway微服务网关实战与源码分析-上

    概述 定义 Spring Cloud Gateway 官网地址 https://spring.io/projects/spring-cloud-gateway/ 最新版本3.1.3 Spring Cl ...

  5. 微服务网关哪家强?一文看懂Zuul, Nginx, Spring Cloud, Linkerd性能差异

      导语:API Gateway是实现微服务重要的组件之一.面对诸多的开源API Gateway,如何进行选择也是架构师需要关注的焦点.本文作者对几个较大的开源API Gateway进行了压力测试,对 ...

  6. 王院生:Apache APISIX 微服务网关极致性能架构解析

    2019 年 10 月 27 日,又拍云联合 Apache APISIX 社区举办 API 网关与高性能服务最佳实践丨Open Talk 杭州站活动,Apache APISIX PPMC 成员王院生做 ...

  7. SpringCloud Alibaba实战(11:引入服务网关Gateway)

    源码地址:https://gitee.com/fighter3/eshop-project.git 持续更新中-- 大家好,我是三分恶. 在前面的章节中,我们已经完成了服务间的调用.统一配置等等,在这 ...

  8. 微服务API Gateway

    翻译-微服务API Gateway 原文地址:http://microservices.io/patterns/apigateway.html,以下是使用google翻译对原文的翻译. 让我们想象一下 ...

  9. Bumblebee微服务网关的部署和扩展

    Bumblebee是.netcore下开源基于BeetleX.FastHttpApi扩展的HTTP微服务网关组件,它的主要作用是针对WebAPI集群服务作一个集中的转发和管理:作为应用网关它提供了应用 ...

随机推荐

  1. .Net CLR GC动态获取函数头地址,C++的骚操作(慎入)

    前言: 太懒了,从没有在这里正儿八经的写过文章.看到一些人的高产,真是惭愧.决定稍微变得不那么懒.如有疏漏,请指正. .net的GC都谈的很多了,本篇主要是剑走偏锋,聊聊一些个人认为较为核心的细节方面 ...

  2. 南京大学 静态软件分析(static program analyzes)-- introduction 学习笔记

    一.Programming Languages体系 静态程序分析是编程语言中应用层面下的一个细分领域,它是一个非常重要的核心内容. 在理论部分,考虑的是如何设计一个语言的语法和语义,如何设计语言的类型 ...

  3. React.js中JSX的原理与关键实现

    在开始开发之前,我们需要创建一个空项目文件夹.安装 初始化 npm init -y 2.安装webpack相关依赖 npm install webpack webpack-cli -D 安装babel ...

  4. Qt项目开发实例 (含源码)

    源码传送门: 啊渊 / QT博客案例 · GitCode 目前QT的研发都是基于windows操作系统的,本文分享在国产操作系统中学QT的路线图,其实学习路线差不多,为了全面的回顾自己的学习知识,打算 ...

  5. STM32 移植 RT-Thread 标准版的 FinSH 组件

    一.移植准备 开发版STM32F10xC8T6 准备好移植RT-Thread的移植工程 没动手移植过RT-Thread的小伙伴,可以看RT-Thread移植到stm32 我这里是将控制台信息打印到串口 ...

  6. exe4j下载和使用

    https://blog.csdn.net/weixin_44678104/article/details/101015065

  7. Django定时任务Django-crontab的使用

    在使用的django做测试平台时,,多多少少都会遇到需要定时任务的功能,比如定时执行任务,检查订单之类 的.可能是一段时间,比如每隔 10分钟执行一次,也可能是定点时间,比如 14:00 执行,也可能 ...

  8. python特殊运算符

    一.逻辑运算符 x = False y = True print(x & y)#仅在布尔中使用 print(x and y)#并且 print(x | y)#仅在布尔中使用 print(x o ...

  9. 零基础学Java(9)在mac上运行命令行提示"找不到或无法加载主类"

    天坑 遇到的问题:使用命令行执行命令:java EightSample,会报以下错误 错误: 找不到或无法加载主类 EightSample 运行环境 mac系统 IntelliJ IDEA编译器 Ja ...

  10. jdbc 06: 实现登陆页面

    jdbc连接mysql,实现简单的登陆验证 package com.examples.jdbc.o6_实现登录界面; import java.sql.*; import java.util.HashM ...