最近,發現主站nginx的log中有很多400的錯誤,每天有幾千萬條,故決定對產生400錯誤的原因進行排查。分析nginx log,發現這種無效的400請求,總是在乙個正常訪問之後產生,一般出現乙個或者幾個。log格式如下:
下面對這種情況進行分析:
一,nginx 400狀態碼含義
上面是http1.1的rfc關於host部分的解釋,從上面我們了解到如果乙個http1.1的請求沒有host域,那麼server應該給client段傳送400的狀態碼,表明這個請求server不能處理。而對於nginx server來說,也遵循這樣的方式,說明client傳送了乙個無效的請求,nginx server無法處理,故返回400的狀態碼。
參見:二,重現400請求
1,我使用pc端的chrome和ucweb瀏覽器,對**進行訪問,發現nginx log中的確會產生400的log,在nginx server端通過netstat看了一下client和server段建立的tcp連線數,每乙個請求都是在3個以上。而是用ie和firefox瀏覽器對**進行訪問,發現不能重現400的log,在nginx server端通過netstat看了一下client和server段建立的tcp連線數,每乙個請求都是只有1個。
2,使用telnet登入nginx的80埠
[@zw-81-90 ~]# telnet 10.13.82.96 80
trying 10.13.82.96...
connected to 10.13.82.96 (10.13.82.96).
escape character is '^]'.
connection closed by foreign host.
使用telnet連線後,直接斷開連線即可
三,問題分析
第一種情況:
通過分析nginx的log,發現400請求中chrome和ucweb的ua比較多,通過檢視相關的文章發現,這種請求和瀏覽器的自身策略有關係。
通常我們訪問乙個**時,第乙個獲取的是乙個html主檔案,而裡面鏈結了網頁所需要的css、js、等其他**資源檔案,而一般資源檔案和主html檔案是在乙個域下的,而像chrome這種瀏覽器就會使用pre-connection,即在獲取html之前就與nginx server建立多個的tcp連線,而不是等到獲取到html檔案之後再去連線伺服器獲取這個網域名稱下的其他檔案,因為連線伺服器是需要消耗一些時間的,所以這項技術可以很大程度上加快網頁的呈現速度。當然,瀏覽器同一時間針對同一網域名稱下的請求也是有一定數量限制。
第二種情況:
使用telnet與nginx server建立個tcp連線,但是沒有傳送任何資料,當然也沒有host頭,之後四次揮手斷開了連線。這種情況,nginx也是當作400的錯誤來處理的。使用tcpdump抓包,wireshark分析過程的截圖如下:
當然,我們發現使用nagios的check_tcp外掛程式對nginx server埠做檢測或者使用keepalived的tcp_check功能對後端nginx埠的存活做檢測,這兩種情況都會在nginx log中產生400的請求。原因也很簡單,就是第二種情況的理由,一般tcp check的方式,就是建立tcp連線,然後再reset或者四次揮手斷開連線。
四,解決辦法
nginx官方提供了一種方法,使用虛擬主機來匹配那些在nginx上沒有匹配到host的請求。這樣那些空host的請求,會被這個虛擬主機所匹配。如果不加這個虛擬主機的話,如果nginx上的虛擬主機沒有對應client請求的host,nginx預設是用nginx.conf中第乙個虛擬主機的處理,故400的請求就會出現在第乙個虛擬主機的log中。虛擬主機配置如下:
server
總之,目前分析來看這類400的無效請求屬於正常現象,可以用虛擬主機來消除400的請求。
nginx 400 報錯,故障排查
nginx的400錯誤比較難查詢原因,因為此錯誤並不是每次都會出現的,另外,出現錯誤的時候,通常在瀏覽器和日誌裡看不到任何有關提示。經長時間觀察和大量試驗查明,此乃request header過大所引起,request過大,通常是由於cookie中寫入了較大的值所引起。解決辦法這 在nginx.co...
記一次Nginx 400錯誤
在乙個非cdn的網域名稱下有乙個頁面,需要請求cdn網域名稱下的資源。所以在cdn的那臺源站的nginx上設定了 add header access control allow headers x requested with add header access control allow meth...
記一次Nginx 400錯誤
在乙個非cdn的網域名稱下有乙個頁面,需要請求cdn網域名稱下的資源。所以在cdn的那臺源站的nginx上設定了 add header access control allow headers x requested with add header access control allow meth...