php CURL 伺服器響應慢的問題

atp1992發表於2018-06-23

用c++搭了個簡單的http伺服器,但是發現接收資料很慢,一個php伺服器傳送http請求,內容大概100k,千兆內網,百兆網路卡,但總是需要1秒時間才能接受完請求報文,開始如下分析

先看接收的http伺服器程式碼

clock_t start, end;
int ctn = 0;
start = clock();
for(;;)
{
	ctn++;
	DWORD EventCaused = WSAWaitForMultipleEvents(
           MAX_WSAEVENTS,	
           EventArray,  	
           FALSE,  	
           pGenericServer->PersistenceTO ? pGenericServer->PersistenceTO : WSA_INFINITE, 	   FALSE
        );
	result = WSAEnumNetworkEvents(s, Event, &NetworkEvents);
	if(NetworkEvents.lNetworkEvents & FD_READ)
	{
		result = WSARecv(s, &Buffers, dwBufferCount, &NumberOfBytesRecvd,
				&Flags,	NULL, NULL);
		if(pGenericServer->IsGet(szRequest))
		{
					. . .
		}else{
			if (!pGenericServer->IsComplete(szRequest)){
				continue;
			}
			end = clock();
			TRACE("recv cost:%d -- times:%d total-length:%d\n", end - start, ctn, szRequest.length());
		}
         }
}

對recv 進行時間累計分析,每次接收的recv消耗時間幾乎為0,大部分時間耗在WSAWaitForMultipleEvents上,對每次迴圈消耗時間進行分析,總是接收第一次資料包後要等待幾乎一秒(前後差幾毫秒)時間。

進一步檢查每次接收到的資料,第一次伺服器只傳送了請求頭,而等待1秒後才開始接收伺服器內容,因而懷疑是php伺服器的卡頓導致,檢查php伺服器程式碼, 用的curl_exec()執行請求傳送,網上搜尋php呼叫curl慢,主要問題都是指向DNS, ipv6解析,但將curl響應設定更改後仍然沒有改觀,於是去看php的curl官網解釋http://php.net/manual/zh/function.curl-setopt.php,看有什麼可能的影響設定,比如TCP資料包大小優化等待,但始終不得解決。

再回頭看接收到的請求頭,看到了陌生的一行,Except:100-continue, 網上一查,是HTTP 1.1協議裡當請求方的請求包大於1024位元組,會先傳送 該句請求頭,以期確認伺服器具備大於1024位元組資料包處理能力,然後才傳送剩餘資料,而我們的傳送方的請求包必然大於1024位元組,故而crul先傳送該詢問,等待伺服器超時(預設1秒)後才開始傳送剩餘資料,所幸curl考慮到該協議各伺服器支援不是很規範,所以當curl等待超時後沒有直接放棄傳輸,而是繼續傳輸,綜合出現了上述情況。

更多資訊見原部落格:

http://www.straka.cn/blog/php_curl_low_response_bugfix/

參考:

解決PHP CURL中Expect:100-continue問題:  http://www.pooy.net/solve-expect100-continue-problems-in-php-curl.html

CURL_SETOPT:  http://php.net/manual/zh/function.curl-setopt.php

相關文章