返回顶部
首页 > 资讯 > 前端开发 > node.js >浅谈Koa服务限流方法实践
  • 447
分享到

浅谈Koa服务限流方法实践

浅谈方法Koa 2022-06-04 17:06:55 447人浏览 八月长安
摘要

最近接了一个需求,很简单,就是起一个server,收到请求时调用某个提供好的接口,然后把结果返回。因为这个接口的性能问题,同时在请求的不能超过特定数目,要在服务中进行限流。 限流的要求是,限制同时执行的数目

最近接了一个需求,很简单,就是起一个server,收到请求时调用某个提供好的接口,然后把结果返回。因为这个接口的性能问题,同时在请求的不能超过特定数目,要在服务中进行限流。

限流的要求是,限制同时执行的数目,超出这个数目后要在一个队列中进行缓存

koa 中间件不调用 next

最初的想法是在 koa 中间件中进行计数,超过6个时将next函数缓存下来。等正在进行中的任务结束时,调用next继续其他请求。

之后发现 koa 中间件中,不执行next函数请求并不会停下,而是不再调用之后的中间件,直接返回内容。


const Koa = require('koa');
const app = new Koa();
app.use((ctx, next) => {
 console.log('middleware 1');
 setTimeout(() => {
  next();
 }, 3000);
 ctx.body = 'hello';
});
app.use((ctx, next) => {
 console.log('middleware 2');
});
app.listen(8989);

以上代码首先在控制台打出 ‘middleware 1' => 浏览器收到 ‘hello' => 控制台打出 ‘middleware 2'。

这里还有一个要注意的地方,就是一个请求已经结束(finish)后,他的next方法还是可以继续调用,之后的middleware还是继续运行的(但是对ctx的修改不会生效,因为请求已经返回了)。同样,关闭的请求(close)也是同样的表现。

使用 await 让请求进行等待

延迟next函数执行不能达到目的。接下来自然想到的就是使用await让当前请求等待。await的函数返回一个Promise,我们将这个Promise中的resolve函数存储到队列中,延迟调用。


const Koa = require('koa');
const app = new Koa();
const queue = [];
app.use(async (ctx, next) => {
 setTimeout(() => {
  queue.shift()();
 }, 3000);
 await delay();
 ctx.body = 'hello';
});
function delay() {
 return new Promise((resolve, reject) => {
  queue.push(resolve);
 });
}
app.listen(8989);

上面这段代码,在delay函数中返回一个Promise,Promise的resolve函数存入队列中。设置定时3s后执行队列中的resolve函数,使请求继续执行。

针对路由进行限流,还是针对请求进行限流?

限流的基本原理实现后,下面一个问题就是限流代码该写在哪里?基本上,有两个位置:

针对接口进行限流

由于我们的需求中,限流是因为要请求接口的性能有限。所以我们可以单独针对这个请求进行限流:


async function requestSomeapi() {
 // 如果已经超过了最大并发
 if (counter > maxAllowedRequest) {
  await delay();
 }
 counter++;
 const result = await request('Http://some.api');
 counter--;
 queue.shift()();
 return result;
}

下面还有一个方便复用的版本。


async function limitWrapper(func, maxAllowedRequest) {
 const queue = [];
 const counter = 0;
 return async function () {
  if (counter > maxAllowedRequest) {
   await new Promise((resolve, reject) => {
    queue.push(resolve);
   });
  }
  counter++;
  const result = await func();
  counter--;
  queue.shift()();
  return result;
 }
}

针对路由进行限流

这种方式是写一个koa中间件,在中间件中进行限流:


async function limiter(ctx, next) => {
 // 如果超过了最大并发数目
 if (counter >= maxAllowedRequest) {
  // 如果当前队列中已经过长
  await new Promise((resolve, reject) => {
   queue.push(resolve);
  });
 }
 store.counter++;
 await next();
 store.counter--;
 queue.shift()();
};

之后针对不同路由在router中使用这个中间件就好了:


router.use('/api', rateLimiter);

比较

实现了针对接口进行限流,觉得逻辑有些乱,于是改用了针对路由进行限流,一切运行的很完美。

直到我又接了个需求,是要请求三次这个接口返回三次请求的结果数组。现在问题来了,我们不能直接调用接口,因为要限流。也不能直接调用请求接口的函数因为我们的限流是以路由为单位的。那怎么办呢?我们只有请求这个路由了,自己请求自己。。。

需要注意的地方

监听close事件,将请求从队列中移出
已经存储在队列中的请求,有可能遇到用户取消的情况。前面说过koa中即使请求取消,之后的中间件还是会运行,也就是还会执行需要限流的接口,造成浪费。

可以监听close事件来达到这个目的,每个请求我们需要用hash值来标记:


ctx.res.on('close', () => {
 const index = queue.findIndex(item => item.hash === hash);
 if (index > -1) {
  queue.splice(index, 1);
 }
});

设置超时时间

为了防止用户等待过长时间,需要设置超时时间,这在koa中很容易实现:


const server = app.listen(config.port);
server.timeout = DEFAULT_TIMEOUT;

当前队列已经过长

如果当前队列已经过长了,即使加入队列中也会超时。因此我们还需要处理队列过长的情况:


if (queue.length > maxAllowedRequest) {
 ctx.body = 'error message';
 return;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: 浅谈Koa服务限流方法实践

本文链接: https://lsjlt.com/news/12302.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 浅谈Koa服务限流方法实践
    最近接了一个需求,很简单,就是起一个server,收到请求时调用某个提供好的接口,然后把结果返回。因为这个接口的性能问题,同时在请求的不能超过特定数目,要在服务中进行限流。 限流的要求是,限制同时执行的数目...
    99+
    2022-06-04
    浅谈 方法 Koa
  • Koa服务限流的示例分析
    小编给大家分享一下Koa服务限流的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!koa 中间件不调用 next最初的想法...
    99+
    2024-04-02
  • 浅谈Redis在直播场景的实践方案
    背景信息 视频直播间作为直播系统对外的表现形式,是整个系统的核心之一。除了视频直播窗口外,直播间的在线用户、礼物、评论、点赞、排行榜等数据信息时效性高,互动性强,对系统时延有着非常...
    99+
    2024-04-02
  • 浅谈python中的实例方法、类方法和静态方法
    在学习python代码时,看到有的类的方法中第一参数是cls,有的是self,经过了解得知,python并没有对类中方法的第一个参数名字做限制,可以是self,也可以是cls,不过根据人们的惯用用法,sel...
    99+
    2022-06-04
    方法 浅谈 静态
  • 浅谈springioc实例化bean的三个方法
    1.构造器也就是在上一篇讲的那个例子,调用默认的无参构造函数2.静态工厂方法1)创建需要执行的方法的类public class HelloWorld { public HelloWorld(){ System.out.prin...
    99+
    2023-05-31
    spring ioc 实例化
  • 浅谈Android实践之ScrollView中滑动冲突处理解决方案
    1. 前言  在Android开发中,如果是一些简单的布局,都很容易搞定,但是一旦涉及到复杂的页面,特别是为了兼容小屏手机而使用了ScrollView以后,就会出现很...
    99+
    2022-06-06
    scrollview 解决方案 Android
  • Java实现5种限流算法及7种限流方式
    目录前言1. 限流2. 固定窗口算法2.1. 代码实现3. 滑动窗口算法3.1. 代码实现4. 滑动日志算法4.1. 代码实现5. 漏桶算法6. 令牌桶算法6.1. 代码实现6.2....
    99+
    2022-11-13
    Java 限流算法 Java 限流方式 Java 限流
  • 浅谈SpringBoot实现自动装配的方法原理
    目录1. 什么是自动装配2. 自动装配的原理3. 自动装配的步骤4. 自定义自动配置5.代码案例总结1. 什么是自动装配 在传统的Spring框架中,我们需要手动配置和管理Bean的...
    99+
    2023-05-20
    SpringBoot实现自动装配 SpringBoot自动装配
  • Go实现各类限流的方法
    前 言 在开发高并发系统时,我们可能会遇到接口访问频次过高,为了保证系统的高可用和稳定性,这时候就需要做流量限制,你可能是用的 Nginx 这种来控制请求,...
    99+
    2022-06-07
    GO 方法
  • redis实现限流的三种方法
    今天小编给大家分享的是redis实现限流的三种方法,相信很多人都不太了解,为了让大家更加了解,所以给大家总结了以下内容,一起往下看吧。一定会有所收获的哦。第一种:基于Redis的setnx的操作我们在使用R...
    99+
    2024-04-02
  • Java服务限流算法的6种实现
    目录固定窗口算法滑动窗口算法漏桶算法令牌桶算法中间件限流网关限流总结服务限流,是指通过控制请求的速率或次数来达到保护服务的目的,在微服务中,我们通常会将它和熔断、降级搭配在一起使用,...
    99+
    2023-05-20
    Java服务限流 服务限流
  • 云服务器限制流量的设置方法
    1. 了解云服务器流量限制 在使用云服务器时,流量限制是一种常见的安全措施,用于限制服务器的网络流量。这可以帮助防止恶意攻击、减少网络拥堵以及控制服务器资源的使用。流量限制通常通过防火墙或网络访问控制列表(ACL)来实现。 2. 设置云服...
    99+
    2023-10-27
    流量 服务器 方法
  • 云服务器限制流量的解除方法
    1. 了解云服务器流量限制 在使用云服务器时,有些云服务提供商会对服务器的流量进行限制。这是为了防止滥用和保护服务器的稳定性。流量限制可以是每月总流量限制,也可以是每秒或每分钟的最大传输速率限制。 2. 解除云服务器流量限制的方法 方法一...
    99+
    2023-10-27
    流量 服务器 方法
  • 浅谈线性表的原理及简单实现方法
    一、线性表原理:零个或多个同类数据元素的有限序列原理图:特点 :有序性有限性同类型元素第一个元素无前驱,最后一个元素无后继,中间的元素有一个前驱并且有一个后继线性表是一种逻辑上的数据结构,在物理上一般有两种实现 顺序实现和链表实现二、基于数...
    99+
    2023-05-31
    线性表
  • 使用Java实现Redis限流的方法
    1、概述   限流的含义是在单位时间内确保发往某个模块的请求数量小于某个数值,比如在实现秒杀功能时,需要确保在10秒内发往支付模块的请求数量小于500个。限流...
    99+
    2024-04-02
  • Redis限流的实现方法有哪些
    本篇内容主要讲解“Redis限流的实现方法有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Redis限流的实现方法有哪些”吧!一、简单的限流基本原理当系统处理能力有限,如何组织计划外的请求对...
    99+
    2023-06-22
  • spring 项目实现限流方法示例
    目录01、为什么AUSTIN项目需要限流02、如何实现限流?03、代码设计04、总结01、为什么AUSTIN项目需要限流 众所周知,服务器能处理的请求数是有限的,如果请求量特别大,我...
    99+
    2022-11-13
    spring 项目限流 项目限流
  • 云服务器流量限制怎么解决方法
    首先,云服务器的流量限制可以通过配置VLAN、限制下载上传速度、使用负载均衡器等方式来解决。例如,如果用户的网站需要访问大量的高并发流量,可以将用户的服务器分为多个VLAN,并配置每个VLAN下的用户访问流量,以确保高并发流量可以被合理利用...
    99+
    2023-10-27
    解决方法 流量 服务器
  • 浅谈Java实现分布式事务的三种方案
    目录一、问题描述二、分布式事务2.1、什么是分布式系统2.2、什么是事务2.3、什么是本地事务2.4、什么是分布式事务三、如何进行分布式事务控制3.1、CAP理论3.2、分布式系统如...
    99+
    2024-04-02
  • Redis实现限流器的方法有哪些
    这篇文章主要介绍了Redis实现限流器的方法有哪些的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Redis实现限流器的方法有哪些文章都会有所收获,下面我们一起来看看吧。 ...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作