热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

简述微服务中的限流功能

任何系统都有流量的限制,为了使我们的服务保持高可用性,我们必须对系统进行限流。说到流


任何系统都有流量的限制, 为了使我们的服务保持高可用性, 我们必须对系统进行限流。说到流量,可能来自于微服务集群外部,也可能来自微服务集群内部。如图一所示,服务A自身必须具备限流能力,以确保来自微服务网关的流量和内部应用的流量在自身可控范围内,保证服务高可用。除此之外微服务网关也应该具备限流能力,将外部流量先行进行拦截。


微服务流量分析



限流算法


说到限流,算法才是灵魂。下面来说一下限流比较主流的四种算法:计数器算法,漏桶,令牌桶,滑动窗口。


计数器算法:比如一秒内只允许50个请求通过。算法实现思路是第一个请求进来计数为1,后面每通过一个请求计数加1,当计数器满50,后面请求全部拒绝。优点实现简单,利用计数器实现。缺点:当流量突然爆发,一旦计数器满,拒绝了所有后续请求。


漏桶算法:海量请求扑面而来,
可能瞬时就会把服务压垮, 而漏桶就可以用来限流削峰.漏桶是总容量是不变的, 水滴(请求) 以任意速率流入, 但总是以恒定速率流出,
如果请求来得太多太快, 桶的容量就会撑满, 后续的请求就会被拒绝, 也就是说当一个请求到来, 就流一滴水进桶里,如果可以放入, 则处理此请求,
否则漏桶已满, 则拒绝此请求, 直到桶中水滴不再满时。


令牌桶算法:令牌桶算法是对漏桶算法的改进,漏桶算法只能均匀的处理请求。令牌桶算法能够在均匀处理请求的情况下,处理一定程度的突发流量。令牌桶需要一个容器来存储令牌,令牌以一定速率均匀地向桶中存放,当超过桶的容量,桶会丢弃多余令牌。请求到来时从令牌桶中领取一个令牌才可继续处理服务, 如果取不到令牌, 则拒绝此请求。


滑动窗口:一种改进算法综合了固定窗口和滑动日志。有兴趣的小伙伴可以单独去了解这两种算法。 它结合了固定窗口算法的低处理成本和滑动日志的改进边界值, 将当前时间窗口与过去时间窗口综合考虑。与固定窗口算法一样,根据请求更改每个固定窗口的计数器。接下来,再根据当前时间戳计算出当前窗口的加权值, 以及上一个窗口的请求率的加权值,以限制流量突发。例如,如果当前窗口加权是20%,那么我们将前一个窗口的计数加权80%。



代码示例分析


Spring cloud gateway限流实现,在Spring Cloud Gateway中,有Filter过滤器,因此可以在“pre”类型的Filter中自行实现上述计数器算法,漏桶,令牌桶限流算法。但是限流作为网关最基本的功能,Spring Cloud Gateway官方就提供了RequestRateLimiterGatewayFilterFactory这个类,使用Redis和lua脚本实现令牌桶算法进行限流。具体实现逻辑在RequestRateLimiterGatewayFilterFactory类种,lua脚本如所示。



首先在工程的pom文件中引入Gateway的起步依赖和Redis的reactive依赖,代码如下:



   org.springframework.cloud
   spring-cloud-starter-gateway


   org.springframework.boot
spring-boot-starter-data-redis-reactive
 


在工程配置文件application.yml中添加一下配置:


server:
 port: 8081
spring:
 application:
  name: gateway-limiter
 redis:
   host: localhost
port: 6379
database: 0
 cloud:
   gateway:
     routes:
     - id: limit_route
       uri: http://httpbin.org:80/get
       predicates:
       - After=2017-01-20T17:42:47.789-07:00[America/Denver]
       filters:
       - name: RequestRateLimiter
         args:
           key-resolver: '#{@hostAddrKeyResolver}'
           redis-rate-limiter.replenishRate: 1
           redis-rate-limiter.burstCapacity: 3


上述配置文件,指定应用端口为8081,配置了redis的连接信息,并配置了RequestRateLimiter的限流过滤器,该过滤器需要配置3个参数。


· burstCapacity:令牌桶总容量。

· replenishRate:令牌桶每秒填充平均速率。

· key-resolver:用于限流的键的解析器的 Bean 对象的名字。它使用 SpEL 表达式,根据#{@beanName}从 Spring 容器中获取 Bean 对象。


KeyResolver需要实现resolve方法,比如根据Hostname进行限流时,需要用hostAddress去判断。实现了KeyResolver之后,需要将这个类的Bean注册到Ioc容器中,具体代码如下:


public class HostAddrKeyResolver implements KeyResolver {
@Override
public Mono  resolve(ServerWebExchange exchange) {
      return  Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
   }
}
@Bean
public HostAddrKeyResolver hostAddrKeyResolver() {
   return new HostAddrKeyResolver();
}
接口限流
public class ApiKeyResolver implements KeyResolver {
@Override
public Mono  resolve(ServerWebExchange exchange) {
      return  Mono.just(exchange.getRequest().getPath().value());
   }
}
用户限流
public class UserResolver implements KeyResolver {
@Override
public Mono  resolve(ServerWebExchange exchange) {
      return  Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
   }
}


关于 sentinel与nacos集成实现限流,下一篇文章中重点介绍。本篇不再赘述。


撰稿 | 赵亮

编辑 | 于睿



作者简介


赵亮,2014年毕业于天津工业大学,现任职于北银金科银行转型业务开发部。主要擅长微服务架构,高并发和大数据处理,目前主要研究方向为微服务。






招聘启事


北银金融科技有限责任公司根植于北京银行,是一家致力于大数据、人工智能、云计算、区块链、物联网等新技术创新与金融科技应用的科技企业,公司充分发挥北京银行企业文化和技术积淀先天优势,通过对技术、场景、生态的完美融合,输出科技创新产品和技术服务。


现诚邀优秀人才加盟

共享金融科技时代硕果




扫描此二维码

期待您的加入





推荐阅读
author-avatar
男孩介于边缘
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有