版權聲明:本文由黃希彤 原創文章,轉載請注明出處:
文章原文鏈接:https://www.qcloud.com/community/article/668639001484812620
來源:騰雲閣 https://www.qcloud.com/community
有一個朋友開發的手機app,把大量文件都保存在騰訊雲COS上,然后通過CDN分發。
最近有一個特殊的需求,希望通過CVM來提供部分COS文件的訪問。因為服務器用的是Nginx,所以事情也很簡單:
1 到COS的管理頁面上查詢一下內網訪問域名
2 給nginx增加一個標准的upstream配置,上游指向騰訊雲COS的內網域名
照理說,配置好域名解析就可以開始工作了。但是一開始工作就出現很奇怪的現象:下載開始很快,隨后變得很慢,最終有很大概率失敗。
首先排除網絡原因的可能性。登錄服務器用wget通過訪問本機localhost驗證:
現象就是前面都下載的飛快,到了最后一部分就突然下載不動了。
打開nginx的error_log,發現了upstream timed out (Connection timed out)錯誤
再排除COS有問題的可能性:
現在問題就很詭異了:上游沒有問題,經過反向代理后文件的前面一大部分也都沒有問題,就是最后一小截文件要等待很久很久,並且發生了upstream timed out超時。
通過肥龍找到了熟悉nginx的ares同學協助抓包,才定位到了這個問題:
這里的UA是wget,wget默認使用的是http1.0協議。當前服務器使用的nginx是1.0.15這個比較古老的穩定版,還不支持 proxy_http_version 1.1這樣的參數(要到1.1.4版本以后才支持)。所以也是采用http1.0協議代理了請求。
照理說innercos服務接到這樣的請求應該按照http1.0的方式返回數據,但是我們看到服務器返回了 HTTP/1.1 200 OK 。也就是說不管客戶端支持什么http版本cos服務總是用http1.1協議來工作。
http1.1有一個重要的特性是keep-alive,也就是說http數據傳輸完畢后TCP連接繼續保持一段時間不斷開,可以給后續的http請求重用。而http1.0的客戶端原則上並不知道http1.1的這套原理。所以對於這個老版本的Nginx來講,它收到完整的數據以后,看到TCP鏈接一直沒有斷開,以為upstream還有話說,就一直掛在那里,等上游繼續送數據,直到上游連接超時,才在error_log里面記錄一個timed out錯誤,然后斷開下游的連接。
把proxy_buffering 關掉讓上下游直接對上話可以繞過這個問題,但是有附帶的損失。更好的辦法是把nginx升級到1.1.4以上的版本,並且開啟proxy_http_version 1.1 。
至此圓滿解決。
總結一下,騰訊雲COS的后台服務假設客戶端都支持http1.1協議,對http1.0協議沒有做很好的兼容,而騰訊雲CVM提供的帶Nginx的系統鏡像里面的Nginx版本又有點兒老舊了,proxy還只能工作在http1.0上,導致了這個問題的出現。