ClientAbortException 問題分析
https://luyiisme.github.io/2017/02/18/conn-abort-problom/
https://yq.aliyun.com/articles/560413
基礎知識:
預設 proxy_ignore_client_abort 是關閉的,此時在請求過程中如果客戶端端主動關閉請求或者客戶端網路斷掉,那麼 Nginx 會記錄 499,同時 request_time 是 「後端已經處理」的時間,而 upstream_response_time 為 “-“ (已驗證)。
如果使用了 proxy_ignore_client_abort on ;
那麼客戶端主動斷掉連線之後,Nginx 會等待後端處理完(或者超時),然後 記錄 「後端的返回資訊」 到日誌。所以,如果後端 返回 200, 就記錄 200 ;如果後端放回 5XX ,那麼就記錄 5XX 。
如果超時(預設60s,可以用 proxy_read_timeout 設定),Nginx 會主動斷開連線,記錄 504。
話題:
基於WEB層面來討論分析問題,引出tcp層面的問題本質;
背景:
筆者常被問到 ClientAbortException 問題,正好就一種場景的分析來簡單分析下(其他場景地分析也較為類似)。下面討論的是使用 nginx 反向代理 tomcat java專案時,有時java應用會發現頻繁列印 ClientAbortException 錯誤日誌問題。
- 1、什麼情況下會出現“ClientAbortException: java.net.socketException: Broken pipe”日誌?
客戶端非正常(標準握手協議)退出連線,體現在http請求,可能是使用者等待頁面響應過程中,關閉瀏覽器,或停止了請求。
- 2、解決方法是 nginx 加個固定的proxy_ignore_client_abort on;就可以了?
nginx 加上這個頭效果一樣,處理客戶端非正常退出情況,保持與應用伺服器端的conn,讓其轉發的伺服器端還是可以繼續對其寫;
- 3、為什麼有的應用報這個問題,有的 nginx 無 proxy_ignore_client_abort 確沒有打錯誤日誌?
tomcat 的專門 coyoteWriter 的寫方法,已經替你忽略掉寫的時候發生的異常。因此,異常其實是產生的,只不過被吞了。但為什麼有的還列印出日誌呢?這些應用是直接使用response.getWriter()拿到的,而拿取 response.getOutputStream() 來構的writer,則沒有忽略異常,而是選擇了丟擲,因此你看到了這個問題;那麼更一般的情況下,我們會在 mvc 框架的 controller 裡(或者 servlet 裡,或其他場合),直接操作 response.getOutputStream() 來進行業務輸出響應流操作,異常會同樣丟擲
。
備註:一旦這個異常發生,如果你還嘗試去攔截處理的這個異常,並再次返回響應,但是因為你操作過了response.getOutputStream了,所有會再拋異常說...response has been commited
! 那麼解決的思路就是,加 nginx 的頭,或者在 controller 裡攔截這種 ClientAbortException,並忽略。
- 4、我自己在分析這個異常產生時,發現有的情況下套接字輸出會拋ClientAbortException,有的時候提交正常?
分析發現,對一個對端已經關閉的socket呼叫兩次write,即第二次嘗試寫才會生成SIGPIPE訊號(why? 因為tcp的四次揮手), 該訊號預設結束程式,會丟擲 Broken pipe 的 exception. 客戶端自己關閉 socket,但是伺服器端不知道,然後向客戶端寫一次資料,這時客戶端會回應伺服器端RST報文(Reset the connection), (如果你此時伺服器端,嘗試讀就會看到這個錯誤報文)。我們這裡是flush buffer,繼續寫第二次,那麼此時就會拋異常:ClientAbortException 而且cause by broken pipe;
- 5、最後,有些應用正確配置了’proxy_ignore_client_abort on;’,但是還是會拋上述異常?
比較常見的情況是,被轉發的請求處理耗時過久,已經超過了‘proxy_read_timeout’的時限,預設 60s。這種情況下「轉發連線」已經讀超時了,’proxy_ignore_client_abort‘當然也就沒有效果了。’proxy_ignore_client_abort‘是防止 Nginx 前置的連線斷掉請求,而對Nginx 後置(連線實際應用伺服器)「轉發連線」是不能防止的。 解決方法:根本是解決應用該慢請求問題。 那麼怎麼確認這個問題呢?可以看 Nginx 的錯誤日誌,裡面會有錯誤資訊 ...[error] 14345#0: *5 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 10.15...
總結:
(1)建議使用nginx的應用,都加上proxy_ignore_client_abort on;(加在Location的配置區域內)
(2)這個異常如果在到JAVA應用伺服器,除了異常fillstacktrace,和列印日誌io消耗,其他對業務本身服務是沒什麼影響的
轉:
Nginx 499 原因:
最近發現伺服器上出現很多499的錯誤,出現499錯誤的原因是客戶端關閉了連線,在我這篇文章:服務端在執行時中途關閉瀏覽器退出之後php還會繼續執行嗎?個人實踐實驗得到結果(http://www.04007.cn/article/356.html )裡,測試中斷時,伺服器nginx的日誌就是499記錄。nginx報49*錯誤
400-499 用於指出客戶端的錯誤。 (自己電腦這邊的問題) 自己電腦這邊的問題)
495 :https certificate error
496 :https no certificate
497 :http to https
498 :canceled
499 :client has closed connection
即499錯誤是客戶端主動斷開了連線。 如何關閉報499這個錯誤碼呢?可以通過配置:proxy_ignore_client_abort來處理。
proxy_ignore_client_abort:是否開啟proxy忽略客戶端中斷。即如果此項設定為on開啟,則伺服器會忽略客戶端中斷,一直等著代理服務執行返回。並且如果執行沒有發生錯誤,記錄的日誌是200日誌。如果超時則會記錄504。如果設定為off,則客戶端中斷後伺服器端nginx立即記錄499日誌,但要注意,此時代理端的PHP程式會依然繼續執行。可檢視上面寫的那篇文章。
nginx的proxy_ignore_client_abort預設是關閉的,即請求過程中如果客戶端端主動關閉請求或者客戶端網路斷掉,那麼Nginx會記錄499。所以如果不想看到499報錯,可以修改配置:
proxy_ignore_client_abort on ;
這樣來說,499錯誤並不是一個問題,如果出現了大量的499的話,需要考慮為什麼發生了這麼多的客戶端中斷的問題。
另外需要注意的一項是:proxy_ignore_client_abort配置只會對代理的配置,如果請求的是當前nginx伺服器,直接執行PHP程式返回。則設定proxy_ignore_client_abort為on也不會起作用,仍會是記錄499日誌。proxy_ignore_client_abort的配置是配置在代理處理時用。如下:
location =/b.php {
proxy_ignore_client_abort on;
proxy_pass http://service_backends;}
相關文章
- Rabbimtmq unack問題分析MQ
- Spring框架問題分析Spring框架
- HDFS Decommission問題分析
- JVM 問題分析思路JVM
- Linux磁碟滿問題分析Linux
- OOM分析之問題一)OOM
- sonar常見問題分析
- unexpected reloc type問題分析
- 問題賬戶需求分析
- MySQL 死鎖問題分析MySql
- 填報 - 分片問題分析
- OOM分析之問題定位(二)OOM
- 如何分析Sonar常見問題?
- JMeter-壓測問題分析JMeter
- 如何分析報表效能問題
- SQLServer記憶體問題分析SQLServer記憶體
- 教你如何 分析 Android ANR 問題Android
- openGauss資料庫分析問題資料庫
- ArrayList 原始碼分析 -- 擴容問題及序列化問題原始碼
- ArrayList 原始碼分析 — 擴容問題及序列化問題原始碼
- org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipeApacheclientExceptionJava
- SQLAlchemy in 查詢空列表問題分析SQL
- 利用 JavaScript Profiler 分析 Vue 效能問題JavaScriptVue
- HandlerThread解析以及相關問題分析thread
- JVM問題分析處理手冊JVM
- ANALYZE導致的阻塞問題分析
- SAP WebClient UI的白屏問題分析WebclientUI
- Get 所有 Redis 效能問題分析手段Redis
- 理性分析 AJAX 跨域問題跨域
- MySQL rr下幻讀問題分析MySql
- Java GBK 中文亂碼問題分析Java
- 陣列效能問題分析總結陣列
- 資料庫索引分裂 問題分析資料庫索引
- tempdb大量閂鎖等待問題分析
- 八皇后問題分析和實現
- Pod掛載Volume失敗問題分析
- 一個RESOURCE MANAGER引起的問題分析
- ORA-08103物件不再存在問題分析物件