使用场景

在开发中,我们可能会遇到一些对异步请求数做并发量限制的场景,比如说微信小程序的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. webpack文件笔记

    webpack.prod.conf.js里面的ExtractTextPlugin,把css文件提取出来,专门进行打包minify :压缩 依赖的第三方库打包到vendor.js里面 每次项目打包的时候 ...

  2. js常用函数整理

    类型转换:parseInt\parseFloat\toString 类型判断:typeof;eg:if(typeof(var)!="undefined")\isNaN 字符处理函数 ...

  3. 【python】time和datetime的strptime不是线程安全的!

    来源:http://blog.csdn.net/kevin6216/article/details/9021039 在多线程中用strptime需要加锁!!!

  4. cf689d ST表RMQ+二分

    类似hdu5289,但是二分更复杂.本题枚举左端点,右端点是一个区间,需要二分找到区间的左端点和右端点(自己手动模拟一次),然后区间长度就是结果增加的次数 另外结果开long long 保存 /** ...

  5. 向集合中添加自定义类型--建议在自定义类型的时候要重写equals方法

    package com.bjpowernode.t01list; import java.util.ArrayList; /* * 向集合中添加自定义类型 */public class TestLis ...

  6. BBC 记录片planet earth

    He'll have to remain on guard for another two weeks, but in the jungle, just surviving the day can c ...

  7. 用两个int值实现读写锁

    private int readcount = 0; private int writecount = 0; public void lockread() throws InterruptedExce ...

  8. Zookeeper笔记(二)Paxos算法与Zookeeper的工作原理

    Zookeeper 分布式服务框架是 Apache Hadoop 的一个子项目, 它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务.状态同步服务.集群管理.分布式应用配置项的管 ...

  9. python 字符串组成MySql 命令时,字符串含有单引号或者双引号导致出错解决办法

    引用自:https://blog.csdn.net/zhaoya_huangqing/article/details/48036839 一.在组成SQL语句并发送命令时完全按照Python中的样式去传 ...

  10. 洛谷 P1004 方格取数 【多进程dp】

    题目链接:https://www.luogu.org/problemnew/show/P1004 题目描述 设有N*N的方格图(N<=9),我们将其中的某些方格中填入正整数,而其他的方格中则放 ...