1. 程式人生 > >解決:The proxy server received an invalid response from an upstream server

解決:The proxy server received an invalid response from an upstream server

最近在App上的呼叫介面時出現下面的錯誤資訊,導致正常頁面無法訪問。

The proxy server received an invalid response from an upstream server. Sorry for the inconvenience.
Please report this message and include the following information to us.
Thank you very much!

分析報錯原因

根據資訊提示(代理伺服器無法得到正確響應)往下分析報錯原因。
首先檢查提示錯誤資訊出處,開啟站點nginx虛擬目錄的配置檔案看到如下配置項:

1
2
3
4
5
6
7
8
9
location~. * . * $ {
	client_max_body_size 15m;
	client_body_buffer_size 256k;
	proxy_next_upstream http_502 http_504 error timeout invalid_header;
	proxy_set_header Host $host;
	proxy_set_header X - Forwarded - For $remote_addr;
	proxy_pass http: //localhost:8980; }
	proxy_next_upstream
...

這個配置指定了nginx在從一個後端主機取資料遇到何種錯誤時會轉到下一個後端主機,裡頭寫上的就是會出現502的所有情況拉,預設是error timeout。

error就是當機、斷線之類的,timeout就是讀取堵塞超時。找到提示以後我們往下看,看到最後一行的proxy_pass代理位置(需要轉發的路徑配置),目前寫的是localhost:8980,查詢埠號得知此埠連線tomcat服務。所以在此判斷應該是tomcat連接出錯。

然後找到tomcat配置路徑(/opt/apache-tomcat-xxxx/conf)中的server.xml檔案查詢tomcat埠資訊,搜尋到如下程式碼:

1
2
3
4
5
6
7
8
9
<Connector port="8980" 
protocol="HTTP/1.1" 
connectionTimeout="20000" 
redirectPort="8443"
compression="on" 
compressionMinSize="2048" 
noCompressionUserAgents="gozilla, traviata"
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"
/>

在這可以看到http協議中的8980埠,結合上面的nginx反向代理配置資訊確定是在連線tomcat時候報錯。

使用top命令檢視程序,也並未看到相關程序。下面我們在/opt/apache-tomcat-xxxx/bin中通過命令暫停和重啟tomcat服務。

1
2
# sh shutdown.sh
# sh startup.sh

在暫停伺服器的時候出現錯誤資訊:

Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00000006f3000000, 1414856704, 0) failed;
error=’Cannot allocate memory’ (errno=12)。

這是JVM丟擲的錯誤,提示記憶體分配問題。檢查到這裡突然想到由於業務調整剛對伺服器做過調整,記憶體從4G降到1G,應該是這個原因導致JVM崩潰。

查詢解決方法

分析後,考慮再不升級記憶體的情況下,通過swap新增虛擬記憶體,嘗試重啟comcat服務,新增swap步驟如下:

1、通過df -h檢視磁碟使用,發現數據盤/dev/xvdb1 使用90%(共100G),清除附件到53%。

2、在/opt/下建立一個swap檔案。

1
mkdir swap cd swap sudo dd if=/dev/xvdb1 of=swapfile bs=1024 count=4194304

根據上面命令分配從資料盤分配4G空間給swap。

3、把生成的檔案轉換成 Swap 檔案

1
sudo mkswap swapfile

4、啟用 Swap 檔案。

1
sudo swapon swapfile

檢視 free -m 的結果,說明已經生效。

Swap: 4095,9 ,4086

重啟comcat伺服器,啟動正常。檢視介面,正常。

原本以為到這就結束了,40分鐘後又出現異常,檢視程序JVM崩潰。停止重啟伺服器沒有問題,好吧,繼續檢視原因。

使用top命令進行資源檢視,發現COMMAND(Java)的%MEM在30分鐘內從50%到85%,然後崩潰。
分析基本確定還是記憶體問題,檢視JVM和伺服器配置得知通常使用的JVM都是32位的,目前的64位的JVM會損失10-20%的效能,從這個點繼續出發做兩個修改:

1、Tomcat關閉日誌catalina.out,

catalina.out檔案會越來越大,對系統的穩定造成了一定的影響。

一般在部署Tomcat後,執行久了,catalina.out檔案會越來越大,對系統的穩定造成了一定的影響。可通過修改conf/logging.properties日誌配置檔案來遮蔽掉這部分的日誌資訊。

1
catalina.org.apache.juli.FileHandler.level = WARNING

將level級別設定成WARNING就可以大量減少日誌的輸出,當然也可以設定成OFF,直接禁用掉。

一般日誌的級別有:

SEVERE (highest value) > WARNING > INFO > CONFIG > FINE > FINER > FINEST (lowest value)

也可以在bin/catalina.sh程式碼中的修改:

“$CATALINA_BASE”/logs/catalina.out 2>&1 &
改為:
/dev/null 2>&1 &

我使用的是第二種方法,直接程式碼簡單粗暴。

2、修改tomcat為java分配的記憶體配置

linux下的tomcat:

修改TOMCAT_HOME/bin/catalina.sh

在“echo “Using CATALINA_BASE: $CATALINA_BASE””上面加入以下行:

1
JAVA_OPTS="-server -Xms256m -Xmx512m -XX:PermSize=64M -XX:MaxPermSize=128m"
其他說明

1、“m”說明單位是MB,否則預設是KB
2、一般使用實體記憶體的80%作為堆大小
3、一般把-Xms和-Xmx設為一樣大
4、一般把-Xmn設定為-Xmx值的1/4
5、一般將堆的總大小的50%到60%分配給新生成的池

修改完重啟comcat服務,top檢視,目前執行時間16小時,%MEM維持在65%左右,正常。後續持續跟進。