boost::async_write 大文件和内存消耗

boost::async_write large files and memory consumption

我正在使用 boost::asio 编写一个 Http 服务器。对于大文件,为了避免将整个文件读入内存并将其发送到网络,我使用 boost::asio::async_write.[=11 逐个读取并发送到网络上=]

问题是我的生产者(从文件中读取的函数)比消费者(boost::asio::async_write)快得多,这导致大量内存消耗文件。

我想通过限制缓冲区列表来避免这个问题。这似乎是一个简单的 producer/consumer 问题,但是,我不想在这样做时阻塞线程。

我使用 boost::io_service 和一个可配置的 n 线程线程池,以防我们对大文件有太多请求,我不希望服务器不再为任何请求提供服务。

所以我的问题是: - 如何在不阻塞线程的情况下设计这种机制? - 我是否应该测试列表大小,然后在它已经太大的情况下生成一个截止日期计时器,该计时器将执行 io_service::post 并继续读取我的文件? - 有更好的方法来处理吗?

如果你想防止 dos 攻击,阻塞读取线程不是一个好主意。您要避免的是同时分配过多的资源(内存)。但是打开的文件流的数量也是有限的。如果您在过载情况下开始阻塞读取线程,您可以非常快地获得大量打开的文件流。如果您发现错误,您的程序可能不会崩溃,但它肯定是不受欢迎的行为,因为您无法打开其他文件(例如日志文件)。

为防止出现此问题,您必须照顾好这两种资源。有许多算法可以限制分配的资源量。对于内存,您可以使用环形缓冲区来读取数据块。您还可以使用原子计数器来跟踪分配的资源量并建立上限。信号量也可以用来解决这类问题。我更喜欢最后一个。伪代码看起来像这样。

Semaphore filestreams(maxNumberOfFilestreams);
Semaphore memory(maxNumberOfAllocatedChunks);

// Worker thread to read
void run() {
    filestream.wait();
    while(!eof) {
        memory.wait();
        // Allocate and read
    }
    file.close();
    filestream.notify()
}

// Sending thread()

void run() {
    while(true) {
        // grab chunk, send and free memory
        memory.notify();
    }
}

请记住,开放的 TCP 连接也是一种有限的资源。