冒着被你們厭煩的風險,今天再發一篇「雲計算之路-阿里雲上」。這是在前一篇發過以後真實發生的事情,咱們以爲定位問題的過程值得分享。並且估計園子裏很多朋友被這個問題騷擾過,咱們有責任讓你們知道問題的真正緣由。css
快下班以前,園區裏另一家公司的朋友說他們公司有的人不能正常訪問園子——會出現HTTP Error 400錯誤,而其餘人能夠正常訪問。這個問題當即引發了咱們的警覺,由於以前也有園友反饋過一樣的問題,當時什麼也沒動,後來就行了,覺得是他們公司網絡代理服務器的問題。因爲咱們從未遇到過這個問題,並且沒法重現,也就無從下手。如今再次出現這個問題,也是有代理服務器的網絡環境,可貴的機會,咱們當即去現場一看究竟。html
在遇到這個問題的電腦上,無論用什麼瀏覽器,訪問www.cnblogs.com都會出現錯誤:web
Bad Request - Invalid Hostname
HTTP Error 400. The request hostname is invalid.瀏覽器
這是IIS返回的標準400錯誤,說明請求已經由SLB(阿里雲負載均衡)到達了Web服務器。服務器
咱們查看了瀏覽器的請求頭,一切正常。網絡
在查看Cookie時發現只有一個名爲SERVERID的Cookie,因而咱們清除一下這個Cookie,結果html頁面出來了,但後續的css/js文件加載時又出現400錯誤,再刷新瀏覽器,又變成400錯誤。負載均衡
這個SERVERID的Cookie讓咱們想起了在排查「黑色30秒」問題期間,咱們開啓了SLB的會話保持,這個Cookie是SLB爲了保持會話而產生的。難道與SLB會話保持有關?「Bad Request - Invalid Hostname」時,IIS收到的到底是什麼樣的hostname?阿里雲
帶着這些問題,咱們回到了本身的辦公室,當即想到了IIS的一個重要日誌——httperr日誌,默認存放位置是C:\Windows\System32\LogFiles\HTTPERR\文件夾,打開一個日誌文件一看,滿眼都是400錯誤,錯誤的緣由都是Hostname。雲計算
以前咱們在偶爾看httperr日誌時,也看到過這樣的400錯誤,當時想多是某些出問題的爬蟲引發的,SLB怎麼可能會把hostname搞錯,也就沒深究。spa
此次必定要找出IIS究竟收到的是什麼樣的hostname,那如何讓IIS在httperr中記錄hostname的信息呢?
在網上找到了一篇微軟的參考資料:Additional properties are now available for logging in the Httperr#.log file in IIS 6.0 and IIS 7.0。
只需2步操做實現:
1. 在註冊表項HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\HTTP\Parameters中添加名爲ErrorLoggingFields、類型爲REG_DWORD、值爲7DFF4E7 (十六進制)的項目。
2. 在命令行中運行命令:net stop http & net start http & iisreset
而後再查看httperr日誌,結果讓咱們驚呆了,cs-host中居然有這樣的值(見下圖):
第1張圖中SLB居然把http header中的max-age=259200看成host的值轉發給了IIS。
第2張圖片SLB居然把用戶在使用代理服務器的狀況下獲得的IP信息看成host的值轉發給了IIS。
難怪會出現Invalid Hostname的錯誤!
對於SLB這樣的角色,http header失之毫釐,謬以千里。出現這樣的問題,真的讓人以爲這地方的代碼寫得很糟糕。
若是SLB的代碼是開源的?哪一個開發人員敢寫出這樣的代碼?即便敢寫,也立刻會被人發現。
看來雲計算更須要開源,不是把開源變成本身的計算能力,而是把本身的計算能力開源,這樣才能更少問題、更讓人放心。
禁用SLB的會話保持後,這些400立馬消失。
一想到由於這個緣由形成不少用戶不能正常訪問,就有一種說不出的惱火。。。
【更新】
阿里雲已於2014年5月22日修復這個問題。