簡體   English   中英

C ++ Boost.ASIO async_read_until慢

[英]C++ Boost.ASIO async_read_until slow

我有一個不尋常的問題。 我有一個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
    )
);

(其中“ socket_”是我的boost :: asio :: ip :: tcp :: socket和“ response_”是我的boost :: asio :: streambuf)

我試圖僅獲取請求的標頭,然后稍后再進行第二個async_read_until,其transfer_exactly匹配從請求標頭解析的“ Content-Length”。 問題在於上面的代碼要花費100-900ms才能在非常現代的服務器上返回(從該讀取塊開始,直到調用handle_read_headers()為止)。 傳入請求看起來像:

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)

標頭似乎以\\ r \\ n \\ r \\ n終止,並且確實在讀取所有EOF之前觸發了handle_read_headers()函數(因此,它不會讀取整個頁面)-實際上,它使正則表達式出錯。 這些請求是來自Google的,因此我非常有信心,這不會落后於他們。

我有什么可以忽略的,為什么花這么長時間才能回來? 我可能還錯過了aync_read_until的其他任何捕獲嗎?

謝謝!

編輯/更新:好的,現在我很困惑。 在嘗試兆字節的建議時,我從streambuf切換到字符數組(沒有運氣),然后將代碼重構為使用async_read_some而不是async_read_until,並且僅手動掃描定界符。 我還將所有OS變量(sysctrl.conf)重置為默認的默認設置(以縮小可能性)。 不幸的是,我仍然在以下代碼中看到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
    )
);

現在response_現在是:

boost::array<char, 4096> response_;

無濟於事(相同的100-900ms延遲)。 這不可能是正常的-有什么想法嗎?

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

async_accept和async_receive之間有700毫秒以上的時間。 在代碼中,它來自此塊(實際上直接來自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
        )
);

從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
        )
    );
}

當調用handle_read_headers()時,已經過去了700毫秒。

有人有任何想法嗎? 我完全迷路了。

非常感謝!

讓我們看一下處理程序日志

[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

從日志中我們可以看到async_receive被調用了兩次:第一次是在處理程序設置(#506)之后734毫秒被調用(#508)。 現在,在設置處理程序(#508)后53微秒調用了第二個async_receive (#510)。 就是這樣,第二次處理程序調用被快速觸發,因為數據(那些404字節)已經在TCP堆棧中准備好了。

結論 :這不是處理程序調用延遲,而是傳輸延遲。 可能是ISP或平衡器出現了問題,或者Google確實不想讓您打擾您的請求和設置延遲。

UPD:我認為您可以使用tcpdump進行檢查

PS我不喜歡HTTP Server 2示例中的io_service_pool_實現。 這也會引起一些問題,但是我認為不是當前情況。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM