【问题标题】:How to test rate limited HTTP request function?如何测试速率受限的 HTTP 请求功能?
【发布时间】:2015-12-01 07:25:43
【问题描述】:

我有一个外部服务,我正在从 Node.js 发出 HTTP 请求。该服务目前的限制是每秒只能发出 10 个请求。我有一个天真的速率限制器,我写了我正在尝试测试,但在它的时间安排上失败了。我知道Javascript times are not very accurate,但我得到了截然不同的波动,最多相差 50 毫秒。

这是我正在做的事情的要点:

var RATE_LIMIT_MS = 100 // No more than 10 requests per second
var NEXT_WAIT_MS = 0

function goGetRequest(...) {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            function complete() {
                // Rollback next time after this request finishes
                NEXT_WAIT_MS = Math.max(0, NEXT_WAIT_MS - RATE_LIMIT_MS)
            }

            // ... requests are fired off here asynchronously...
            http.get(...).then(complete)

        }, NEXT_WAIT_MS)

        // Push time back on the queue
        NEXT_WAIT_MS += RATE_LIMIT_MS
    })
}

var chai = require('chai')
var expect = chai.expect

it('should rate limit requests properly', function() {
    var iterations = [0, 1, 2, 3, 4]
    var lastResponseMs = 0

    var promises = iterations.map(function(i) {
        return goGetRequest(...).
            then(function(result) {
                // Diff the times
                var thisResponseMs = Date.now()
                var thisDiffMs = Math.abs(thisResponseMs - lastResponseMs)

                expect(wrapper.results).to.not.be.empty
                expect(thisDiffMs, 'failed on pass ' + i).to.be.at.least(RATE_LIMIT_MS)

                // Move last response time forward
                lastResponseMs = thisResponseMs
            })
    })

    return Promise.all(promises)
})

接下来发生的事情是测试将在随机通过时失败。第 2 遍时 92 毫秒的时间差异,第 4 遍时 68 毫秒的时间差异......我在这里错过了什么?谢谢!

【问题讨论】:

  • 我不太理解您在问题中提出的问题。您是否在问如何修复您的速率限制器以限制为 10 个请求/秒?还是您在问其他问题(关于测试)?

标签: javascript node.js mocha.js chai rate-limiting


【解决方案1】:

Javascript setTimeout 和 setInterval(与 any 非实时代码一样)从来都不是精确的。但是,如果您使用的是 NodeJS,则可以尝试使用 Nanotimer:

https://www.npmjs.com/package/nanotimer

var NanoTimer = require('nanotimer');

var timerA = new NanoTimer();

timerA.setTimeout(yourFunction, '', NEXT_WAIT_MS);

或者,我建议简单地测试发生速率限制,而不必太担心精确度。如果你连续 11 个请求向它发送垃圾邮件(希望不到一秒),它就被阻止了,一秒后就没事了,那么你的测试就可以被认为是通过了。

一个最终的解决方案是使用exec() 并调用操作系统sleep 命令,这明显更精确。

【讨论】:

    猜你喜欢
    • 2019-02-28
    • 2013-07-15
    • 2013-12-13
    • 2022-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-07
    相关资源
    最近更新 更多