简体   繁体   English

C ++ Boost.ASIO async_read_until慢

[英]C++ Boost.ASIO async_read_until slow

I'm having an unusual issue. 我有一个不寻常的问题。 I have a C++ Boost.ASIO web server, and to handle incoming requests I'm using this code: 我有一个C ++ Boost.ASIO Web服务器,并且使用以下代码来处理传入的请求:

boost::asio::async_read_until(
    socket_,
    response_,
    "\r\n\r\n",
    boost::bind(
            &connection::handle_read_headers,
            shared_from_this(),
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred
    )
);

(where "socket_" is my boost::asio::ip::tcp::socket and "response_" is a boost::asio::streambuf) (其中“ socket_”是我的boost :: asio :: ip :: tcp :: socket和“ response_”是我的boost :: asio :: streambuf)

I'm trying to just grab the headers of the request, then I later do a second async_read_until with transfer_exactly matching the "Content-Length" that was parsed from the request header. 我试图仅获取请求的标头,然后稍后再进行第二个async_read_until,其transfer_exactly匹配从请求标头解析的“ Content-Length”。 The problem is that above code is taking 100-900ms to return on a very modern server (From that read block, until handle_read_headers() is called). 问题在于上面的代码要花费100-900ms才能在非常现代的服务器上返回(从该读取块开始,直到调用handle_read_headers()为止)。 The incoming request looks like: 传入请求看起来像:

POST /load HTTP/1.1
host: www.mysite.com
Accept: */*
Accept-Encoding: gzip,deflate
Content-type: application/x-www-form-urlencoded
From: googlebot(at)googlebot.com
Origin: http://www.mysite.com
Referer: http://www.mysite.com/another-page/
User-Agent: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
X-Forwarded-For: 66.249.75.103
X-Forwarded-Port: 80
X-Forwarded-Proto: http
Content-Length: 287
Connection: keep-alive

and-the-actual-content-is-here.... (287 bytes worth)

The headers seem to be terminated with a \\r\\n\\r\\n, and it does trigger the handle_read_headers() function before reading all the way to EOF (so it's not reading the whole page) - it actually is tripping the regex. 标头似乎以\\ r \\ n \\ r \\ n终止,并且确实在读取所有EOF之前触发了handle_read_headers()函数(因此,它不会读取整个页面)-实际上,它使正则表达式出错。 And these requests are coming from Google, so I'm quite confident it's not lag on their end. 这些请求是来自Google的,因此我非常有信心,这不会落后于他们。

Is there anything I could be overlooking on why it's taking so long to return? 我有什么可以忽略的,为什么花这么长时间才能回来? Any other catches with aync_read_until I might have missed? 我可能还错过了aync_read_until的其他任何捕获吗?

Thanks! 谢谢!

EDIT/UPDATE: Okay, now I'm very confused. 编辑/更新:好的,现在我很困惑。 In trying megabyte's suggestion, I switched from a streambuf to a character array (no luck), then I refactored my code to use async_read_some rather than async_read_until, and just scan for the delimited manually. 在尝试兆字节的建议时,我从streambuf切换到字符数组(没有运气),然后将代码重构为使用async_read_some而不是async_read_until,并且仅手动扫描定界符。 I also reset all OS variables (sysctrl.conf) to bone stock default (to narrow down possibilities). 我还将所有OS变量(sysctrl.conf)重置为默认的默认设置(以缩小可能性)。 Unfortunately I'm still seeing 100-900ms delays in the following code from calling handle_read() with the same incoming POST request: 不幸的是,我仍然在以下代码中看到100-900ms的延迟,这是通过使用相同的传入POST请求调用handle_read()来实现的:

socket_.async_read_some(
    boost::asio::buffer(response_),
    boost::bind(
        &connection::handle_read,
        shared_from_this(),
        boost::asio::placeholders::error,
        boost::asio::placeholders::bytes_transferred
    )
);

where response_ is now: 现在response_现在是:

boost::array<char, 4096> response_;

To no avail (same 100-900ms delays). 无济于事(相同的100-900ms延迟)。 There's no way this is normal - any thoughts? 这不可能是正常的-有什么想法吗?

EDIT2: Per the recommendation of Rhashimoto, I enabled handler tracking and found this oddity in the log: EDIT2:根据Rhashimoto的建议,我启用了处理程序跟踪并在日志中发现了这种奇怪情况:

[2013-07-05 15:58:39 - Thread 7fae57e3f700]: Incoming connection (0ms elapsed)
@asio|1373054319.874916|506*508|socket@0x7fae50004f98.async_receive
@asio|1373054319.874963|506*509|socket@0x7fffd40fed68.async_accept
@asio|1373054319.875008|<506|
@asio|1373054320.609088|>508|ec=system:0,bytes_transferred=512
@asio|1373054320.609233|508*510|socket@0x7fae50004f98.async_receive
@asio|1373054320.609264|<508|
@asio|1373054320.609284|>510|ec=system:0,bytes_transferred=404
[2013-07-05 15:58:40 - Thread 7fae57e3f700]: Received packet headers (638 bytes) - 734ms elapsed

There are over 700 milliseconds between the async_accept and async_receive. async_accept和async_receive之间有700毫秒以上的时间。 In the code, it goes from this block (virtually straight from the "HTTP Server 2" of http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/examples/cpp03_examples.html - server.cpp and connection.cpp): 在代码中,它来自此块(实际上直接来自http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/examples/cpp03_examples.html-服务器的“ HTTP Server 2”。 cpp和connection.cpp):

new_connection_->start();
new_connection_.reset(new connection(
        io_service_pool_.get_io_service()
));
acceptor_.async_accept(
        new_connection_->socket(),
        boost::bind(
                &server::handle_accept,
                this,
                boost::asio::placeholders::error
        )
);

and from the start() to: 从start()到:

void connection::start()
{
    boost::asio::async_read_until(
        socket_,
        response_,
        "\r\n\r\n",
        boost::bind(
            &connection::handle_read_headers,
            shared_from_this(),
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred
        )
    );
}

and when handle_read_headers() is called, 700ms have passed. 当调用handle_read_headers()时,已经过去了700毫秒。

Does anyone have ANY ideas? 有人有任何想法吗? I'm completely lost. 我完全迷路了。

Thanks so much! 非常感谢!

Lets look at the handlers log 让我们看一下处理程序日志

[2013-07-05 15:58:39 - Thread 7fae57e3f700]: Incoming connection (0ms elapsed)
@asio|1373054319.874916|506*508|socket@0x7fae50004f98.async_receive
@asio|1373054319.874963|506*509|socket@0x7fffd40fed68.async_accept
@asio|1373054319.875008|<506|
@asio|1373054320.609088|>508|ec=system:0,bytes_transferred=512
@asio|1373054320.609233|508*510|socket@0x7fae50004f98.async_receive
@asio|1373054320.609264|<508|
@asio|1373054320.609284|>510|ec=system:0,bytes_transferred=404
[2013-07-05 15:58:40 - Thread 7fae57e3f700]: Received packet headers (638 bytes) - 734ms elapsed

From log we can see async_receive is called twice: first is called(#508) 734ms after handler setup(#506). 从日志中我们可以看到async_receive被调用了两次:第一次是在处理程序设置(#506)之后734毫秒被调用(#508)。 Now, second async_receive is called(#510) 53 microseconds after handler setup(#508). 现在,在设置处理程序(#508)后53微秒调用了第二个async_receive (#510)。 Thats it, second handler call was fired blasingly fast because the data (those 404 bytes) was already ready in TCP stack. 就是这样,第二次处理程序调用被快速触发,因为数据(那些404字节)已经在TCP堆栈中准备好了。

Conclusion : it is not a handler call delay, it is transport delay. 结论 :这不是处理程序调用延迟,而是传输延迟。 Probably trouble with the ISP or a balancer, or maybe Google really dont want to bother you with requests and setting up delays. 可能是ISP或平衡器出现了问题,或者Google确实不想让您打扰您的请求和设置延迟。

UPD: I think you can check this with tcpdump UPD:我认为您可以使用tcpdump进行检查

PS I dont like io_service_pool_ implementation from HTTP server 2 example. PS我不喜欢HTTP Server 2示例中的io_service_pool_实现。 This can cause some problems too, but i think its not current case. 这也会引起一些问题,但是我认为不是当前情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM