周末出現事故,記錄一下。還好BOSS不在,趕緊整,出現400了。。 寫完回家!
同僚說測試站點通路接口出現400 Bad Request Request Header Or Cookie Too Large提示,心想還好是測試伺服器出現問題,影響不大,不過也趕緊上伺服器進行測試檢視,打開nginx與ugwsi日志與配置,發現後端服務日志記錄正常,而測試站點的通路日志有7百多M(才運作兩三天沒幾個通路,幾M的話才是正常現象),在浏覽器裡直接通路後端服務接口也正常沒有問題(我們的伺服器軟體架構是微服務架構,将很多子產品分拆後分别部署,前端是一個純HTML站點,通過AJAX通路後端各個服務,由于通路量不大,是以前端站點的nginx配置時,做了反向代理通路後端其他服務,這樣就不會出現跨域和需要處理多子域名事情——即通路不同的服務時,隻需要使用目前域名就可以了,這樣前端開發人員不必要知道後端挂載了多少服務需要使用什麼對應的域名通路)。通路這台伺服器上的其他站點都能正常通路,而問題站點的html頁面也能正常打開……在測試過程中發現,每通路一下問題接口,通路日志就增加30多M,刷了幾次,nginx日志大小直線上升……
由于日志比較大,隻能使用tail -n 5000 xxx_access.log >> xxx.log截取一下最新的日志記錄下載下傳下來,打開一看發現同一時間一個通路,生産了2000多條重複循環的通路記錄,而日志尾部$http_x_forwarded_for部分,有規律的存儲了相同的由多到少的IP字串,即:最後一條有一個IP字串(真實IP),倒數第二條有兩個IP字串(真實IP + 伺服器本地IP),倒數第三條有三個IP字串(真實IP + 兩個伺服器本地IP),以至類推
百度了一下“400 Bad Request Request Header Or Cookie Too Large”,查找出來的幾乎都是說“nginx 400 Bad request是request header過大所引起,request過大,通常是由于cookie中寫入了較大的值所引起。在nginx.conf中,将client_header_buffer_size和large_client_header_buffers都調大後可解決”,一看就知道這肯定不是我這種情況的解決辦法,這是由于不知道什麼原因引起的死循環将IP位址串寫入請求頭,直到緩存爆了才傳回400,如果将緩存設定更大,隻會造成日志增加速度變大而已。從分析來看應該是nginx出現的問題。
沒有辦法隻能在打開nginx配置檔案分析,問題站點的配置檔案,如下圖,并沒有發現什麼問題
打開nginx.conf進行慢慢研究,發現多了幾行代碼
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
複制
這是用來将目前通路使用者的IP傳給後端伺服器用的,将它們删除重新啟動一下伺服器nginx後測試了一下,發現能正常通路了…o my god,再将它放回去,重新開機,通路,挂了,去掉,重新開機,通路,正常……重試了好幾次,終于确定就是突然多出來的幾行代碼引起的。(後來問了一下同僚才知道是他進伺服器添加的)
難道真的是不能使用嗎?記得以前用過還是正常的。嘗試通路預生産環境接口,正常。打開預生産環境的nginx配置,包函有這三行代碼,如下圖
全面對比後發現,生産環境用的nginx配置是域名,而預生産環境用的是IP+端口,除此之外沒有任何差別,使用跳轉方式與反向代碼方式測試,結果都是一樣,添加port_in_redirect、server_name_in_redirect配置也沒能解決
綜合分析,應該是nginx在使用proxy_pass做跳轉時,如果直接使用域名,且需要向後端送出目前通路的IP位址時,引發nginx的bug造成死循環,不知道大家有沒有遇到過這種情況。
# 使用反向代理方式
# 正常的配置 upstream xxx{ server 127.0.0.1:23456; } upstream yyy { server 127.0.0.1:123455; }
# 異常配置 upstream xxx1{ server xx.xxx.com; } upstream yyy2 { server yyy.xxx.com; }
複制
# 使用跳轉方式 # 正常配置 proxy_pass http://127.0.0.1:23456; # 異常配置 proxy_pass http://xx.xxx.com;
複制