使用场景

在开发中,我们可能会遇到一些对异步请求数做并发量限制的场景,比如说微信小程序的request并发最多为5个,又或者我们需要做一些批量处理的工作,可是我们又不想同时对服务器发出太多请求(可能会对服务器造成比较大的压力)。这个时候我们就可以对请求并发数进行限制,并且使用排队机制让请求有序的发送出去。

介绍

那么,接下来我们就来讲一下如何实现一个通用的能对请求并发数进行限制的RequestDecorator。我们先来介绍一下它的功能:

  1. 既然涉及到并发数限制,它就肯定允许用户传入最大并发数限制参数:maxLimit
  2. 既然是一个通用的RequestDecorator,那么它应该允许使用者传入其喜欢的异步api(比如ajax, fetch, axios等)。
  3. 为了方便起见,也为了开发便利性,被RequestDecorator封装后的request请求结果都返回一个promise。
  4. 由于使用者传入的异步api不一定是promise类型的,也可能是callback类型的,因此我们提供用户一个needChange2Promise参数,使用者若传入的是callback类型的api,它可以通过将这个参数设置为true来将callback类型转化为promise类型。

分析完功能后,接下来我们就来实现这个东西:

实现

具体代码如下,每一步我基本都做了注释,相信大家能看懂。

const pify = require('pify');

class RequestDecorator {
constructor ({
maxLimit = 5,
requestApi,
needChange2Promise,
}) {
// 最大并发量
this.maxLimit = maxLimit;
// 请求队列,若当前请求并发量已经超过maxLimit,则将该请求加入到请求队列中
this.requestQueue = [];
// 当前并发量数目
this.currentConcurrent = 0;
// 使用者定义的请求api,若用户传入needChange2Promise为true,则将用户的callback类api使用pify这个库将其转化为promise类的。
this.requestApi = needChange2Promise ? pify(requestApi) : requestApi;
}
// 发起请求api
async request(...args) {
// 若当前请求数并发量超过最大并发量限制,则将其阻断在这里。
// startBlocking会返回一个promise,并将该promise的resolve函数放在this.requestQueue队列里。这样的话,除非这个promise被resolve,否则不会继续向下执行。
// 当之前发出的请求结果回来/请求失败的时候,则将当前并发量-1,并且调用this.next函数执行队列中的请求
// 当调用next函数的时候,会从this.requestQueue队列里取出队首的resolve函数并且执行。这样,对应的请求则可以继续向下执行。
if (this.currentConcurrent >= this.maxLimit) {
await this.startBlocking();
}
try {
this.currentConcurrent++;
const result = await this.requestApi(...args);
return Promise.resolve(result);
} catch (err) {
return Promise.reject(err);
} finally {
console.log('当前并发数:', this.currentConcurrent);
this.currentConcurrent--;
this.next();
}
}
// 新建一个promise,并且将该reolsve函数放入到requestQueue队列里。
// 当调用next函数的时候,会从队列里取出一个resolve函数并执行。
startBlocking() {
let _resolve;
let promise2 = new Promise((resolve, reject) => _resolve = resolve);
this.requestQueue.push(_resolve);
return promise2;
}
// 从请求队列里取出队首的resolve并执行。
next() {
if (this.requestQueue.length <= 0) return;
const _resolve = this.requestQueue.shift();
_resolve();
}
} module.exports = RequestDecorator;

样例代码如下:

const RequestDecorator = require('../src/index.js')

// 一个callback类型的请求api
async function delay(num, time, cb) {
setTimeout(() => {
cb(null, num);
}, time);
} // 通过maxLimit设置并发量限制,needChange2Promise将callback类型的请求api转化为promise类型的。
const requestInstance = new RequestDecorator({
maxLimit: 5,
requestApi: delay,
needChange2Promise: true,
}); let promises = [];
for (let i = 0; i < 30; i++) {
// 接下来你就可以像原来使用你的api那样使用它,参数和原来的是一样的
promises.push(requestInstance.request(i, Math.random() * 3000).then(result => console.log('result', result), error => console.log(error)));
}
async function test() {
await Promise.all(promises);
} test();

这样,一个能对请求并发数做限制的通用RequestDecorator就已经实现了。当然,这里还有很多可以继续增加的功能点,比如

  1. 允许使用者设置每个请求的retry次数。
  2. 允许使用者对每个请求设置缓存处理。

结语

以上,就是本篇的全部内容。github仓库地址点击这里。欢迎大家点赞或者star下。如果大家有兴趣的话,也可以一起来完善这个东西。这个项目还不成熟,可能还会有bug,欢迎大家在github上提issue帮助我完善它。如果觉得有帮助的话,麻烦点个赞哦,谢谢。

转:https://www.cnblogs.com/chenjg/p/9638613.html

对请求并发数做限制的通用RequestDecorator的更多相关文章

  1. 不到50行代码实现一个能对请求并发数做限制的通用RequestDecorator

    使用场景 在开发中,我们可能会遇到一些对异步请求数做并发量限制的场景,比如说微信小程序的request并发最多为5个,又或者我们需要做一些批量处理的工作,可是我们又不想同时对服务器发出太多请求(可能会 ...

  2. Node爬虫之——使用async.mapLimit控制请求并发

    一般我们在写爬虫的时候,很多网站会因为你并发请求数太多当做是在恶意请求,封掉你的IP,为了防止这种情况的发生,我们一般会在代码里控制并发请求数,Node里面一般借助async模块来实现. 1. asy ...

  3. 吞吐量(Throughput)、QPS、并发数、响应时间(RT)对系统性能的影响

    首先对吞吐量().QPS.并发数.响应时间(RT)几个概念一直比较模糊,也不知道哪些指标可以较好的衡量系统的性能.今天特意查了些资料做一些记录:首先看一些概念(来自百度百科) 1. 响应时间(RT) ...

  4. 吞吐量(TPS)、QPS、并发数、响应时间(RT)概念

    开发的原因,需要对吞吐量(TPS).QPS.并发数.响应时间(RT)几个概念做下了解,查自百度百科,记录如下:1. 响应时间(RT)  响应时间是指系统对请求作出响应的时间.直观上看,这个指标与人对软 ...

  5. [笔记]吞吐量(TPS)、QPS、并发数、响应时间(RT)概念

    开发的原因,需要对吞吐量(TPS).QPS.并发数.响应时间(RT)几个概念做下了解,查自百度百科,记录如下: 1. 响应时间(RT) 响应时间是指系统对请求作出响应的时间.直观上看,这个指标与人对软 ...

  6. paip.提升性能---- 网站并发数的总结.txt

    paip.提升性能---- 网站并发数的总结.txt 作者Attilax ,  EMAIL:1466519819@qq.com  来源:attilax的专栏 地址:http://blog.csdn.n ...

  7. 【转载】nginx 并发数问题思考:worker_connections,worker_processes与 max clients

    注:这个文章主要是作者一直在研究nginx作为http server和反向代理服务器时候所谓最大的max_clients和 worker_connections的计算公式, 其实最后的结论也没有卡上公 ...

  8. windows下修改apache并发数

    还没有尝试 修改apache的最大连接数,方法如下: 步骤一 先修改 /path/apache/conf/httpd.conf文件. # vi httpd.conf 将“#Include conf/e ...

  9. tomcat 最大并发数

    只针对BIO模式,目标请求会sleep两秒再返回结果,通过jmeter测试工具进行并发测试 操作系统:windows && linux tomcat7测试: <Connector ...

随机推荐

  1. 转载:Linux操作系统(1.3.1)《深入理解Nginx》(陶辉)

    原文:https://book.2cto.com/201304/19611.html 1.3 准备工作 由于Linux具有免费.使用广泛.商业支持越来越完善等特点,本书将主要针对Linux上运行的Ng ...

  2. Linux服务器性能评估

    一.影响Linux服务器性能的因素 1. 操作系统级 CPU 内存 磁盘I/O带宽 网络I/O带宽 2. 程序应用级 二.系统性能评估标准 影响性能因素 影响性能因素 评判标准 好 坏 糟糕 CPU ...

  3. jQuery实现鼠标点击div外的地方div隐藏消失的效果

    css部分: <style type="text/css"> .pop { width:200px; height:130px; background:#080;} & ...

  4. 三元一次方程问题(for嵌套)

  5. STM32应用实例七:与宇电设备实现AI-BUS通讯

    宇电的设备使用基于RS-485的自定义协议,协议本身比较简单,只有2条指令: 读:地址代号+52H(82) +要读的参数代号+0+0+校验码 写:地址代号+43H(67)+要写的参数代号+写入数低字节 ...

  6. 性能测试十八:jmeter分布式

    一台压力机产生得压力是有限的,尤其是jmeter,java本来性能就不是很好,并发特别多的时候,jmeter的性能会急剧下降,正常的接口,若单台压力机,超过1000并发以后,jmeter的性能就不怎么 ...

  7. 改代码不是很熟悉------方法上加入synchronized关键字,会有性能问题---如何改善

    package com.bjpowernode.t14; import java.time.Duration;import java.time.LocalTime; public class Proc ...

  8. MVC的WebViewPage

    采用Razor引擎的View文件(.cshtml或者.vbhtml)最终都会编译成一个WebViewPage类型,所以通过RazorView/WebFormView体现的View的呈现机制最终体现在对 ...

  9. 3237: [Ahoi2013]连通图 线段树分治

    题解: cf765f cf671e bzoj4184 bzoj4552 线段树分治裸题 还是介绍一下线段树分治 这个东西其实挺简单但也挺有用的 可以把删除+插入操作变成只有插入(倒着就是删除) 像这一 ...

  10. Python subprocess方法

    import subprocess #subprocess.call("df -h",shell=True,stdout=subprocess.PIPE)#打印到视图,但是不能保存 ...