問題背景
線上某個web應(yīng)用頁面,偶發(fā)性的報502 Bad Gateway異常。線上環(huán)境是Nginx反向代理和SpringBoot的后端服務(wù)組合症见。針對這個問題,記錄一下解決過程狰晚。
環(huán)境準備
如果環(huán)境是Mac并且已經(jīng)安裝了Homebrew的話筒饰,安裝Nginx還是非常方便的。
brew install nginx
Mac Homebrew安裝指導(dǎo)http://www.reibang.com/p/ebd854196c4c
如果已經(jīng)安裝過了Docker環(huán)境壁晒,則更為便利瓷们,直接運行一個Nginx鏡像即可。
Homebrew安裝完后秒咐,可以通過以下命令操作Nginx谬晕。
#啟動
brew services start nginx
# 停止
brew services stop nginx
# 重啟
brew services restart nginx
安裝后nginx的日志路徑為
/usr/local/var/log/nginx
Nginx配置文件路徑為
/usr/local/etc/nginx
問題定位和解決
我們到線上撈取了對應(yīng)異常時間點的Nginx日志,在其中發(fā)現(xiàn)了這樣的異常信息携取。
61112#0: *1 upstream sent too big header while reading response header from upstream
這個異常是由于響應(yīng)中Header信息過大導(dǎo)致的攒钳。為此我們需要寫一個簡單的服務(wù)端代碼驗證一下。
@RestController
public class HomeController {
@RequestMapping(value = "/home")
public String home(HttpServletRequest request, HttpServletResponse response) {
String headCount = request.getParameter("headCount");
if (!StringUtils.hasText(headCount)) {
headCount = "300";
}
for (int i = 0; i < Integer.parseInt(headCount); i++) {
response.setHeader(String.valueOf(i), String.valueOf(i));
}
return "success";
}
}
上述代碼比較簡單雷滋,就是根據(jù)入?yún)⒌囊粋€headCount參數(shù)不撑,向響應(yīng)中增加Header的數(shù)量。
我們先讓服務(wù)不經(jīng)過Nginx反向代理來驗證一下晤斩。headCount設(shè)置為3000焕檬,看是否正常。
??澳泵,怎么服務(wù)端自己先報錯了呢实愚,還是看看日志吧。
An attempt was made to write more data to the response headers than there was room available in the buffer. Increase maxHttpHeaderSize on the connector or write less data into the response headers.
根據(jù)異常信息判斷兔辅,是SpringBoot自身對Header也有限制大小腊敲,異常也給出了解決方案,那就是增加maxHttpHeaderSize的大小维苔。
通過找尋maxHttpHeaderSize關(guān)鍵詞碰辅,我們找到了SpringBoot自動加載的ServerProperties中的這個屬性,可以看到默認大小是8K介时。
我們可以通過application.properties將該大小增加到128K后重啟服務(wù)没宾。
server.maxHttpHeaderSize=128KB
此時單獨訪問服務(wù)端是正常的了忍法。那再加上Nginx的負載均衡會是什么樣子呢?
我們找到Nginx的配置文件榕吼,在路徑/usr/local/etc/nginx/nginx.conf中饿序,找到http 80端口對應(yīng)的server配置,配置路由信息到本機的SpringBoot服務(wù)羹蚣。
location / {
proxy_pass http://127.0.0.1:8080;
}
修改完后啟動Nginx服務(wù)原探,然后通過瀏覽器請求同樣的后端服務(wù)。
哇哦顽素,502 Bad Gateway啦咽弦,抓緊時間取看一下Ngxin的日志。
2022/03/05 14:42:35 [error] 63112#0: *14 upstream sent too big header while reading response header from upstream, client: 127.0.0.1, server: localhost, request: "GET /home?headCount=3000 HTTP/1.1", upstream: "http://127.0.0.1:8080/home?headCount=3000", host: "localhost"
可以看到的確是因為響應(yīng)中Header過大導(dǎo)致的胁出,那么有什么解決辦法呢型型。感謝萬能的谷歌-> https://ma.ttias.be/nginx-proxy-upstream-sent-big-header-reading-response-header-upstream/。
從這篇文章中可以看到全蝶,Nginx對于響應(yīng)Header會進行緩存闹蒜,如果Header超過了緩存的大小就會報這樣的錯誤。所以接下來那就是按照文章中給的設(shè)置修改Nginx配置抑淫。
location / {
proxy_pass http://127.0.0.1:8080;
proxy_buffer_size 128K;
proxy_buffers 4 256K;
proxy_busy_buffers_size 256K;
}
重新啟動服務(wù)驗證绷落,現(xiàn)在可以看到請求已經(jīng)可以正常返回了。