Spring Cloud 微服务五:Spring cloud gateway限流
前言:在互联网应用中,特别是电商,高并发的场景非常多,比如:秒杀、抢购、双11等,在开始时间点会使流量爆发式地涌入,如果对网络流量不加控制很有可能造成后台实例资源耗尽。限流是指通过指定的策略削减流量,使到达后台实例的请求在合理范围内。本章将介绍spring cloud gateway如何实现限流。
前情回顾请参考:
Spring Cloud 微服务二:API网关spring cloud zuul
Spring Cloud 微服务三: API网关Spring cloud gateway
Spring Cloud 微服务四:熔断器Spring cloud hystrix
- 限流算法
- 主流的限流算法有两种:漏桶(leaky bucket)和令牌桶(token bucket)。漏桶算法 有一个固定容量的桶,对于流入的水无法预计速率,流出的水以固定速率,当水满之后会溢出。

令牌桶算法,有一个固定容量的桶,桶里存放着令牌(token)。桶最开始是空的,token以一个固定速率向桶中填充,直到达到桶的容量,多余的token会被丢弃。每当一个请求过来时,都先去桶里取一个token,如果没有token的话请求无法通过。

两种算法的最主要区别是令牌桶算法允许一定流量的突发,因为令牌桶算法中取走token是不需要时间的,即桶内有多少个token都可以瞬时拿走。基于这个特点令牌桶算法在互联网企业中应用比较广泛,我们在实现限流的时候也会基于这个算法。
- gateway如何实现限流
方法1:Spring cloud gateway实现限流的方式主要是通过添加自定义filter来实现,自定义filter需要实现GatewayFilter和Ordered接口。本章将结合开源的Bucket4j来实现,Bucket4j是基于令牌桶算法实现,Bucket4j代码参考:https://github.com/vladimir-bukhtoyarov/bucket4j
- 首先修改api-gateway module,pom中添加Bucket4j依赖,最新版本是4.3.0,工程的版本已经在父工程中定义好了
<dependency>
<groupId>com.github.vladimir-bukhtoyarov</groupId>
<artifactId>bucket4j-core</artifactId>
</dependency>
第二步,添加filter实现GatewayFilter和Ordered,添加相应的参数,并使用一个ConcurrentHashMap存储ip以及bucket,实现filter方法,对客户端访问ip进行过滤
public class LimitFilter implements GatewayFilter, Ordered {
private static final Logger logger = LoggerFactory.getLogger(LimitFilter.class);
private int capacity;
private int refillTokens;
private Duration refillDuration;
public LimitFilter(int capacity, int refillTokens, Duration refillDuration) {
this.capacity = capacity;
this.refillTokens = refillTokens;
this.refillDuration = refillDuration;
}
private static final Map<String, Bucket> CACHE = new ConcurrentHashMap<>();
private Bucket createNewBucket() {
Refill refill = Refill.greedy(refillTokens, refillDuration);
Bandwidth limit = Bandwidth.classic(capacity, refill);
return Bucket4j.builder().addLimit(limit).build();
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
Bucket bucket = CACHE.computeIfAbsent(ip, k -> createNewBucket());
logger.info("IP: "+ip+", available tokens :"+bucket.getAvailableTokens());
if (bucket.tryConsume(1L)) {
return chain.filter(exchange);
}
logger.info("IP: "+ip+", available tokens :"+bucket.getAvailableTokens()+" too many requests");
exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
return exchange.getResponse().setComplete();
}
@Override
public int getOrder() {
return 0;
}
}
第三步,添加自定义路由,添加配置类,RouteLocator构造器中添加filter以及相应的地址信息,设置同一ip同时只能访问一次,多余的将被忽略。另外,由于我们在程序中配置了路由,需要将application.yml中的gateway相关属性删除。
@Configuration
public class RouteLocatorConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
System.out.println("============================RouteLocatorConfig "+ builder.routes());
return builder
.routes()
.route(r -> r.path("/*")
.filters(f -> f.filter(new LimitFilter(1,
1, Duration.ofSeconds(1))))
.uri("http://localhost:10080/")
.order(0)
.id("user_route"))
.build();
}
}
最后,测试,重启api-gateway,访问http://localhost:8088/users,第一次访问成功,频繁刷新会出现空白页,控制台会输出相关信息
方法2:使用spring cloud 原生的redis方式
第一步,搭建redis服务器,具体方法参考redis官网
第二步,pom中添加redis依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
自定义resolver
@Configuration
public class CustomResolver {
@Bean
public KeyResolver ipKeyResolver(){
System.out.println("##############ipKeyResolver########################");
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}
}
第三步,修改application.yml配置
routes:
- id: user_route
uri: http://localhost:10080
predicates:
- Path=/*
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 1
redis-rate-limiter.burstCapacity: 1
key-resolver: "#{@ipKeyResolver}
最后做测试,并使用monitor命令监控redis
Spring Cloud 微服务五:Spring cloud gateway限流的更多相关文章
- Spring Cloud微服务安全实战_3-3_API安全之流控
这几篇将API安全的 流控.认证.审计.授权 简单的过一遍,对这些概念先有个初步印象.后边还会详细讲解. 本篇说API安全之流控~第一印象. 一.概念 流控,流量控制,只放系统能处理的请求的数量过去, ...
- Spring Cloud微服务Sentinel+Apollo限流、熔断实战总结
在Spring Cloud微服务体系中,由于限流熔断组件Hystrix开源版本不在维护,因此国内不少有类似需求的公司已经将眼光转向阿里开源的Sentinel框架.而以下要介绍的正是作者最近两个月的真实 ...
- Spring Cloud 微服务六:调用链跟踪Spring cloud sleuth +zipkin
前言:随着微服务系统的增加,服务之间的调用关系变得会非常复杂,这给运维以及排查问题带来了很大的麻烦,这时服务调用监控就显得非常重要了.spring cloud sleuth实现了对分布式服务的监控解决 ...
- 微服务与Spring Cloud概述
微服务与Spring Cloud随着互联网的快速发展, 云计算近十年也得到蓬勃发展, 企业的IT环境和IT架构也逐渐在发生变革,从过去的单体应用架构发展为至今广泛流行的微服务架构. 微服务是一种架构风 ...
- Spring Cloud 微服务三: API网关Spring cloud gateway
前言:前面介绍了一款API网关组件zuul,不过发现spring cloud自己开发了一个新网关gateway,貌似要取代zuul,spring官网上也已经没有zuul的组件了(虽然在仓库中可以更新到 ...
- 只需五分钟-用Maven快速搭建Spring Cloud微服务
Maven安装手册 1.准备安装包 安装包: apache-maven-3.5.4-bin.zip (最好JDK 1.7及以上版本) 集成包: eclipse-maven3-plugin.zip 2 ...
- spring cloud微服务实践五
本篇我们来看看怎么实现spring cloud的配置中心. 在分布式系统中,特别是微服务架构下,可能会存在许多的服务,每个服务都会存在一个或多个的配置文件.那怎么多的配置文件的管理就会成为一个大问题. ...
- Dubbo和Spring Cloud微服务架构'
微服务架构是互联网很热门的话题,是互联网技术发展的必然结果.它提倡将单一应用程序划分成一组小的服务,服务之间互相协调.互相配合,为用户提供最终价值.虽然微服务架构没有公认的技术标准和规范或者草案,但业 ...
- 在阿里云容器服务上开发基于Docker的Spring Cloud微服务应用
本文为阿里云容器服务Spring Cloud应用开发系列文章的第一篇. 一.在阿里云容器服务上开发Spring Cloud微服务应用(本文) 二.部署Spring Cloud应用示例 三.服务发现 四 ...
随机推荐
- Intellij IDEA 14.x 菜单项中Compile、Make和Build的区别
Compile.Make和Build的区别 针对Java的开发工具,一般都有Compile.Make和Build三个菜单项,完成的功能的都差不多,但是又有区别. 编译,是将源代码转换为可执行代码的过程 ...
- Android kernel Crash后,定位出错点的方法
转载:http://blog.csdn.net/wlwl0071986/article/details/11635749 1. 将/prebuild/gcc/linux-x86/arm/arm-lin ...
- u-boot-2015.01在tq2440上的初步移植
作者: 彭东林 邮箱: pengdonglin137@163.com QQ: 405728433 开发板: tq2440 工具: Win7 + VMware + Debian6 ...
- cocurrent包ExecutorService线程池
16. 执行器服务 ExecutorService java.util.concurrent.ExecutorService 接口表示一个异步执行机制,使我们能够在后台执行任务.因此一个 Execut ...
- Unable to list target platforms. Please make sure the android sdk path is correct. See the Console for more details.
在android上发布遇到 androidSDK无法找到的问题 http://www.jianshu.com/p/fe4c334ee9fe
- 记录一次ceph recovery经历
一次ceph recovery经历 背景 这是一个測试环境. 该环境中是cephfs 一共12个节点, 2个client.2个mds.8个osd mds: 2颗CPU,每一个4核.一共是8核. 128 ...
- Windows为什么双击打开‘我的电脑’, 没有了‘前进’‘ 后退’‘向上’等按钮?
如图所示 点击查看 工具栏 标准按钮即可 左侧的数值虚线可以拖动到任意,还可以添加按钮如搜索,删除,复制,剪切等
- Metadata publishing for this service is currently disabled.
Reason 1: In your web.config <service name="A.B.C"> but your class is: namespace A.B ...
- 偶遇 smon 进程cpu 开销高异常分析
今天突然发现线上一台oracle 数据库 servercpu 跑的非常高.感觉不是非常正常,细致看了下.发现是smon 进程吃掉了一个cpu. 那么这个smon 进程究竟在倒腾啥玩意 对smon 进程 ...
- my_interface
import flask,osserver=flask.Flask(__name__) #当前这个python文件,当做一个服务 @server.route('/error',methods=['ge ...