冒著被大家厭煩的風險,今天再發一篇“云計算之路-阿里云上”。這是在前一篇發過之后真實發生的事情,我們覺得定位問題的過程值得分享。而且估計園子里不少朋友被這個問題騷擾過,我們有責任讓大家知道問題的真正原因。
快下班之前,園區里另外一家公司的朋友說他們公司有的人不能正常訪問園子——會出現HTTP Error 400錯誤,而其他人可以正常訪問。這個問題立即引起了我們的警覺,因為之前也有園友反饋過同樣的問題,當時什么也沒動,后來就好了,以為是他們公司網絡代理服務器的問題。由于我們從未遇到過這個問題,而且無法重現,也就無從下手。現在再次出現這個問題,也是有代理服務器的網絡環境,難得的機會,我們立即去現場一看究竟。
在遇到這個問題的電腦上,不管用什么瀏覽器,訪問www.cnblogs.com都會出現錯誤:
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搞錯,也就沒深究。
這次一定要找出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日修復這個問題。
文章列表