微服务实现不同登陆_微服务网关——实现篇

本文详细介绍了如何基于SpringCloud Gateway实现微服务网关,包括整体架构、限流实现、自定义拦截器、聚合服务以及非功能性需求。SpringCloud Gateway基于SpringWebFlux和Netty,支持路由、限流等功能,可以通过GatewayFilter和GlobalFilter进行扩展,适用于高并发场景,并可集成监控和日志平台。
摘要由CSDN通过智能技术生成

在《微服务网关——需求篇 》中,我们讨论了微服务网关的需求;而在《微服务网关——设计篇 》中,我们讨论了微服务网关的设计。本文将对微服务网关进行实现。

对于网关的开发,完全自研的难度比较大,特别是IO的处理。考虑到目前市面上有比较多的成熟框架,可以基于成熟的开源框架,进行二次开发。

对于Java来说,目前Spring提供了SpringCloud Gateway(下面简称SG),SG基于SpringWebFlux,底层默认使用的是Netty框架,支持高并发请求,同时提供了一些默认的组件,支持路由、限流等功能。可以基于SG进行二次开发。

如果对网关有特别多的自定义需求,可以直接基于Netty来进行更彻底的二次开发,适配自身系统的个性化需求。

本文将基于SG来讨论网关的实现。

基于SpringCloud Gateway的网关设计

这里针对前面的需求,梳理如何基于SpringCloud Gateway来实现。关于SpringCloud Gateway本身的设计和实现,会新开一篇专门讨论。

SpringCloud Gateway整体架构

SpringCloud Gateway基于SpringWebFlux,整体架构如下图所示:

b7b396a511cf7b55c5c12fdc8c6dbd0c.png

SG定义了几个概念:

  • 路由(Route):路由是网关的基本构成单元。它由一个ID、一个目标URL、一组谓词以及一组过滤器组成。当谓词判定为true时,表示请求与对应路由匹配
  • 谓词(Predicate):Java8函数式谓词。输入参数是Spring框架封装的ServerWebExchange对象。开发人员可以基于此对象来匹配HTTP请求的任意内容,比如请求头或请求参数
  • 过滤器(Filter):由特定工厂类构造的一组Spring框架提供的GatewayFilter对象。过滤器可以在请求或响应被处理前/后对其进行修改。

SG处理请求的大致流程如下:

GatewayHandlerMapping判定对应的请求是否匹配某个路由。如果匹配到某个路由,则将请求交给GatewayWebHandler处理。Handler调用一个Filter链来处理这个请求,具体执行流程如下:

  • 首先,会执行「pre」过滤器的逻辑
  • 然后执行请求处理逻辑
  • 最后再执行「post」过滤器的逻辑

SG提供了GatewayFilter和GlobalFilter两种类型的过滤器,从名字可以看出GlobalFilter是对全局生效的,而GatewayFilter是对特定请求生效的。

注意:这里的GlobalFilter是针对所有匹配了GatewayHandlerMapping的请求生效,而不是对所有进入网关的请求生效。

假设,你在网关中编写了一个Controller,但是路由配置中并没有匹配该Controller的路径,那么针对该Controller的请求并不会触发任何GlobalFilter。

SG针对一个请求的完整流程如下图所示:

769a3969cebb93e0bbdb5f0d61bee38d.png

可以看到,SG的扩展是基于一个个的Filter来实现的。前面提到的大部分需求也完全可以基于Filter去实现,包括但不限于路由、负载均衡、认证授权、过载保护、缓存、服务重试、日志记录等。

这里仅以限流为例,来说明SG的扩展逻辑。其它实现请自行阅读源码,或关注后续内容。

限流实现

SG提供了RequestRateLimiterGatewayFilterFactory过滤器支持限流,同时也支持基于histrix的过载保护,直接集成使用即可,具体请见histrix文档。

这里以RequestRateLimiterGatewayFilterFactory为例来分析SG如何基于拦截器来实现j限流的。SG中的限流是针对每个路由来单独定义的,配置内容如下:

a6fea014e9baa1bb7af559812bb85cbb.png

上面的配置,配置了一个路由:

  • id为test_route
  • 路由地址到lb://test。前面的lb://表示支持负载均衡,后面的test是服务名称
  • predicates是谓词,表示当请求以/test开头时,此路由生效
  • 同时配置了一个限流拦截器,包括名称和参数。基于此配置通过RequestRateLimiterGatewayFilterFactory来构建对应的Filter。其中的参数是用来配置请求速率的,即每秒允许10个请求,允许短时间(这里是1秒)涌入20个请求。

上面的配置会被构建为一个RouteLocator实例,该类根据配置构建Route、Predicates、Filter等实例。对于Filter来说,

  • 在创建RouteLocator实例时,已创建的GatewayFilterFactory实例列表会被作为参数传入
  • list被转换为map,key为去除了GatewayFilterFactory后缀名的Filter类名(与配置文件中的Filter的配置匹配),value是对应的GatewayFilterFactory实例
61315fb69c0ea8923edb4b9333862013.png
  • 在构建Route实例时,会根据配置文件中的Filter的配置获取Filter实例设置进Route实例中,提供给后续流程使用

RequestRateLimiterGatewayFilterFactory核心代码如下所示:

6a729e696423ce60ca3adaab105f0a48.png
  • 1处,获取配置参数。这里的KeyResolver是对获取请求的key逻辑的抽象。比如其中的一个实现是PrincipalNameKeyResolver,它从ServerWebExchange中获取Principal对象,并将Principal.getName()的返回值作为当前请求的key,如果值相同,则认定为同一个请求。
  • 2处,构建匿名GatewayFilter
  • 3处,基于限流器来处理限流逻辑

官方提供的分布式限流方案是基于redis实现。

8a1b1cba609b5f802811dc9ef40df289.png

核心逻辑在RedisRateLimiter的isAllowed()方法中:

cd3f7febd59d3cc0b168bfd8d1d2dde7.png
  • 1处,获取参数(上面已经解释过了)
  • 2处,构建lua参数,执行lua脚本
  • 3处,根据返回值判定是否允许访问

lua脚本就不贴出来了,使用的是令牌桶算法。

自定义拦截器

从上面的梳理,可以看出,要编写一个自定义的GatewayFilter的流程如下:

  • 编写一个FilterFactory类继承AbstractGatewayFilterFactory,这个类实现了GatewayFilterFactory接口,该接口提供了一个名叫name的默认方法,用于提供Factory的name,作为获取对应实例的名称。逻辑就是将对应FilterFactory类名后的「GatewayFilterFactory」去掉,例如上面的RequestRateLimiterGatewayFilterFactory,对应的配置名称就是RequestRateLimiter。
  • 在覆写的apply方法中构建对应的Filter,可以是直接返回匿名GatewayFilter,或返回对应Filter的实例
  • 如果返回的是Filter的实例,则需要编写一个实现了GatewayFilter的Filter类,实现其filter方法
  • 然后将FilterFactory、实现的Filter(如果有的话)配置给Spring管理
  • 最后,就可以在配置文件中针对需要的路由配置对应的Filter了

聚合服务

SG基于SpringWebFlux,支持编写异步RESTful接口,同时提供WebClient异步REST客户端来实现聚合服务的编写。不过由于是编码的形式,所以需要发布网关。对于集群部署的情况下,在可用性要求没有特别严格的情况下,此方式可以接受。

如果聚合服务较多且发布频繁,可以独立出聚合服务层。即基于SpringWebFlux构建微服务,使用WebClient来整合独立微服务的逻辑,网关路由至对应的服务即可。

关于WebClient的使用方法请自行搜索,这里就不赘述了。

非功能性需求

SG本身就基本符合前面提到的非功能性需求

  • 基于SpringWebFlux的非阻塞IO模型,支持高并发。
  • 基于分布式配置服务进行动态配置
  • 基于GatewayFilter和GlobalFilter进行扩展
  • 可以接入PinPoint的链路监控以及基于ELK的日志监控平台

主要注意保证无状态设计!

总结

本文及之前的「微服务网关——需求篇」和「 微服务网关——设计篇 」对微服务网关进行了梳理。

后面计划专栏基于SpringCloud来对整个微服务进行梳理,欢迎关注!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值