【问题标题】:How to limit the bandwidth when read data under libuvlibuv下读取数据时如何限制带宽
【发布时间】:2020-05-09 06:08:59
【问题描述】:

众所周知,libuv 是一个异步网络库。
现在我用libuv编写了一个http下载客户端,但是我不知道如何限制下载时的速度。也就是说,在libuv或异步网络库下读取数据时如何控制IO带宽?

类似问题:
1.How to control the transmission speed under libuv?
2.Rate-limiting plan in libuv #738

【问题讨论】:

    标签: limit bandwidth libuv


    【解决方案1】:

    我最近实现了一个限制代理,我是这样做的:

    在本示例中,我假设最大带宽为 100kbps,超时时间为 10ms,并由您自行处理错误。

    • 为您的传入流致电read_start
    • 在回调中立即调用read_stop
    • 根据您的最大 bps 和超时 (0.01s * maxBps = 1kB) 计算块大小
    • 将分块数据存储在某种集合中
    • 用我们的 10 毫秒超时启动一个计时器
    • 在您的计时器回调中:
      • 检查是否有剩余块
      • 将数据块写入输出流
      • 如果还有更多块,则重新启动计时器
      • 否则为您的输入流再次调用read_start
    • 重复。

    我在 Lua 中使用 luvit 进行了此操作,luvit 是 libuv 的包装器(+ 更多),但您应该能够轻松翻译有趣的部分。

    这是 Lua 代码的相关部分供参考。请注意,我在这里的写回调中启动了我的计时器,但这应该没什么区别。 send_data_to_upstream 是传入的流读取回调。

    
    local send_next_chunk
    local send_data_to_upstream
    
    send_data_to_upstream = function(err, data)
        if err then debug_print("Client error:" .. err) end
        if data then
            -- throttle reads
            self.sock.tcp_client:read_stop()
    
            -- chunkify the data
            self.chunks = splitByChunk(data, self:_get_chunk_size())
            debug_print("[DOWN]", "Client request: " .. #data)
            send_next_chunk()
        else
            -- Client disconnected, cleanup handles
            self:disconnect()
            debug_print("Client disconnected")
        end
    end
    
    send_next_chunk = function()
        if #self.chunks > 0 then
            debug_print("[DOWN]", "Chunks remaining: ", #self.chunks,
                        "next in:", self.throttle.delay)
            timer.setTimeout(self.throttle.delay, function()
                -- throttle transfer for consecutive chunks
                self.throttle.delay = self.throttle.timeout_ms
    
                -- send next chunk
                local head = table.remove(self.chunks, 1)
                self.sock.tcp_upstream:write(head, send_next_chunk)
                collectgarbage("step")
            end)
        else
            -- restart the client data pump
            self.throttle.delay = 0
            debug_print("[DOWN]", "Client request completed")
            self.sock.tcp_client:read_start(send_data_to_upstream)
        end
    end
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-26
      相关资源
      最近更新 更多