最近在做團購酒店APP分享到qzone功能,使用libcurl訪問qzone的分享cgi接口,酒店分享信息以POST方式傳輸,在測試的時候發現分享接口平均有2s的延遲,這延遲也太大了吧,於是乎問了空間的接口人,答曰:怎么可能,這個接口的平均調用時延是100-200ms,肯定是你的代碼有問題。好吧,開始檢查代碼,使用strace -p跟蹤系統調用,發現curl發送了兩次請求,其中第一次請求的響應特別的慢,額,原來這個才是導致延遲的罪魁禍首,tcpdump之后發現curl發送的第一個請求包含一個Expect: 100-continue的頭,這是為什么呢,於是開始百度,google,得到的解釋如下:
當使用libcurl的POST方式時,如果POST數據的大小大於1024個字節,libcurl不會直接發送POST請求,而是會分為兩步執行請求:
1、發送一個請求,該請求頭部包含一個Expect: 100-continue的字段,用來詢問server是否願意接受數據
2、當接收到從server返回的100-continue的應答后,它才會真正的發起POST請求,將數據發送給server。
對於“100-continue"這個字段,RFC文檔(http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.2.3)是這么解釋的:它可以讓客戶端在發送請求數據之前去判斷服務器是否願意接收該數據,如果服務器願意接收,客戶端才會真正發送數據,這么做的原因是如果客戶端直接發送請求數據,但是服務器又將該請求拒絕的話,這種行為將帶來很大的資源開銷。所以為了避免這種情況,libcurl在發送大於1024字節的POST請求時采用了這種方法,但是相對的,它會引起請求延遲的加大,另外並不是所有的server都會正確處理並且應答”100-continue“,比如lighttpd,就會返回417”Expectation Failed“,造成請求邏輯出錯。
如果確定服務器不會拒絕1024個字節以上的POST請求,就可以不使用該方法而且也可以避免以上提到的兩個副作用,解決的辦法如下:
- // disable Expection header
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, array('Expect:'));
禁用該機制后,測試了一下qzone分享接口平均調用時延減小到了200ms,這才是正常的延時嘛,嘿嘿。
參考資料:
http://www.laruence.com/2011/01/20/1840.html
from:http://blog.csdn.net/zxgfa/article/details/7604624