Connection reset by peer 全解


文章很長,建議收藏起來,慢慢讀! 瘋狂創客圈為小伙伴奉上以下珍貴的學習資源:


價值連城:2021春招月薪過5萬 面試題 總系列

搞定下面這些面試題,2021春招月薪過5萬(猛!) 阿里、京東、美團、頭條.... 隨意挑、橫着走!!!
Java基礎
1: JVM面試題(史上最強、持續更新、吐血推薦) https://www.cnblogs.com/crazymakercircle/p/14365820.html
2:Java基礎面試題(史上最全、持續更新、吐血推薦) https://www.cnblogs.com/crazymakercircle/p/14366081.html
3:死鎖面試題(史上最強、持續更新) [https://www.cnblogs.com/crazymakercircle/p/14323919.html]
4:設計模式面試題 (史上最全、持續更新、吐血推薦) https://www.cnblogs.com/crazymakercircle/p/14367101.html
5:架構設計面試題 (史上最全、持續更新、吐血推薦) https://www.cnblogs.com/crazymakercircle/p/14367907.html
還有 10 幾篇價值連城 的面試題 具體..... 請參見【 瘋狂創客圈 高並發 總目錄

萬字長文: 瘋狂創客圈 springCloud 高並發系列

springCloud 高質量 博文
nacos 實戰(史上最全) sentinel (史上最全+入門教程)
springcloud + webflux 高並發實戰 Webflux(史上最全)
SpringCloud gateway (史上最全)
還有 10 幾篇 萬字長文 的高質量 博文 具體..... 請參見【 瘋狂創客圈 高並發 總目錄

1錯誤信息

Connection reset by peer

nginx的錯誤日志中會出現

Connection reset by peer) while reading response header from upstream, client: 1.1.1.1, server: 102.local, request: "GET / HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000

日志查看方法

這個錯誤是在nginx的錯誤日志中發現的,為了更全面的掌握nginx運行的異常,強烈建議在nginx的全局配置中增加

error_log   logs/error.log notice;

這樣,就可以記錄nginx的詳細異常信息。

2 原因一:連接已經被上游close。

服務端確實已經關閉了連接: upstream發送了RST,將連接重置。

errno = 104 錯誤表明你在對一個對端socket已經關閉的的連接調用write或send方法,在這種情況下,調用write或send方法后,對端socket便會向本端socket發送一個RESET信號,在此之后如果繼續執行write或send操作,就會得到errno為104,錯誤描述為connection reset by peer。

如果對方socket已經執行了close的操作,本端socket還繼續在這個連接上收發數據,就會觸發對端socket發送RST報文。按照TCP的四次握手原理,這時候本端socket應該也要開始執行close的操作流程了,而不是接着收發數據。

  • 比如,當后端為php程序時,如果php運行較慢,並超出php-fpm.conf的request_terminate_timeout設置的秒數。request_terminate_timeout用於設置當某個php腳本運行最長時間,若超出php-fpm進程管理器強行中止當前程序,並關閉fastcgi和nginx的網絡連接,然后nginx中就會出現Connection reset by peer的錯誤了。

也就是說,產生這個錯誤的原因是:php 程序的運行時間超出request_terminate_timeout設置的值。

在php-fpm環境下,在php的安裝目錄的etc/php-fpm.conf中有此值的設置項,可將其設置為0或更大的值。這樣將php的request_terminate_timeout設置為較大的值或0,可減少因php腳本執行時行過長導致nginx產生Connection reset by peer錯誤。

  • 比如,當后端為java 程序時

java 的也類似,不能Java端主動關閉連接。 如果上游的tomcat 或者 netty 已經關閉連接, 那么nginx 肯定就是 Connection reset by peer

3 原因二:數據長度不一致

​ 發送端和接收端事先約定好的數據長度不一致導致的,接收端被通知要收的數據長度小於發送端實際要發送的數據長度。

4 原因三: FastCGI 緩存小,timeout太小。

nginx的buffer太小,timeout太小。主要指php的環境,nginx如果要解析php腳本語言,就必須通過配置fastcgi模塊來提供對php支持。

問題概述:圖片bit 64生成數據流太大,導致小程序分享彈窗的二維碼圖片生成失敗

nginx http模塊添加以下參數配置:

fastcgi_buffer_size 128k;

fastcgi_buffers 4 128k;

fastcgi_busy_buffers_size 128k;

fastcgi_temp_file_write_size 128k;

后台報錯:

img

排查:

Client------>nginx------->h5------>nginx---------->client

客戶端通過h5的nginx頁面點擊,nginx反向代理到h5 [無異常]

h5通過客戶端請求調取相應接口 [無異常]

接口返回數據通過nginx展示給客戶端 [異常]

Ps: 圖片通過bit 64解析生成返回給客戶端,由於數據長度太長導致

解決方法:

調整nginx配置文件參數,修改后參數:

fastcgi_buffer_size 256k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;

先簡單的說一下 Nginx 的 buffer 機制,對於來自 FastCGI Server 的 Response,Nginx 將其緩沖到內存中,然后依次發送到客戶端瀏覽器。緩沖區的大小由 fastcgi_buffers 和 fastcgi_buffer_size 兩個值控制。

比如如下配置:

fastcgi_buffers      8 4K;
fastcgi_buffer_size  4K;

fastcgi_buffers 控制 nginx 最多創建 8 個大小為 4K 的緩沖區,而 fastcgi_buffer_size 則是處理 Response 時第一個緩沖區的大小,不包含在前者中。所以總計能創建的最大內存緩沖區大小是 84K+4K = 36k。而這些緩沖區是根據實際的 Response 大小動態生成的,並不是一次性創建的。比如一個 8K 的頁面,Nginx 會創建 24K 共 2 個 buffers。

當 Response 小於等於 36k 時,所有數據當然全部在內存中處理。如果 Response 大於 36k 呢?fastcgi_temp 的作用就在於此。多出來的數據會被臨時寫入到文件中,放在這個目錄下面。同時你會在 error.log 中看到一條類似 warning。

顯然,緩沖區設置的太小的話,Nginx 會頻繁讀寫硬盤,對性能有很大的影響,但也不是越大越好,沒意義,呵呵!

FastCGI緩沖設置主要參數

fastcgi_buffers 4 64k

這個參數指定了從FastCGI進程到來的應答,本地將用多少和多大的緩沖區讀取,假設一個PHP或JAVA腳本所產生頁面大小為256kb,那么會為其分配4個64kb的緩沖來緩存;若頁面大於256kb,那么大於256kb的部分會緩存到fastcgi_temp指定路徑中,這並非是個好辦法,內存數據處理快於硬盤,一般該值應該為站點中PHP或JAVA腳本所產生頁面大小中間值,如果站點大部分腳本所產生的頁面大小為256kb,那么可把值設置為16 16k,4 64k等。

fastcgi_buffer_size=64k

讀取fastcgi應答第一部分需要多大緩沖區,該值表示使用1個64kb的緩沖區讀取應答第一部分(應答頭),可以設置為fastcgi_buffers選項緩沖區大小。

fastcgi_connect_timeout=300

連接到后端fastcgi超時時間,單位秒,下同。

fastcgi_send_timeout=300

向fastcgi請求超時時間(這個指定值已經完成兩次握手后向fastcgi傳送請求的超時時間)

fastcgi_reAd_timeout=300

接收fastcgi應答超時時間,同理也是2次握手后。

5 原因四: proxy_buffer緩存小

原因就是請求的頭文件過大導致502錯誤

解決方法就是提高頭部的緩存

http{

client_header_buffer_size 5m;

 

location / {

  proxy_buffer_size 128k;
  proxy_busy_buffers_size 192k;
  proxy_buffers 4 192k;

  }

}


原因五:沒有設置keepalive

​ ngx_http_upstream_check_module這個模塊,在使用tcp檢測后端狀態時,只進行了TCP的三次握手,沒有主動斷開這個連接,而是等待服務端來斷開。當后端是nginx或者tomcat時(linux上),超時后后端會發fin包關閉這個連接。這個錯誤日志recv() failed (104: Connection reset by peer)是在后端為IIS的情況下拋出的,抓包發現IIS並不會發fin包來斷開鏈接,而是在超時后發RST包重置連接,所以導致了這個問題。
​ 從這個問題也反應出ngx_http_upstream_check_module這個模塊還是需要完善下檢測機制的,如果是在檢測后端狀態后主動關閉這個連接,應該就不會出現connect reset這個問題

通過修改源代碼已經解決了該問題

static ngx_check_conf_t ngx_check_types[] = {
{ NGX_HTTP_CHECK_TCP,
ngx_string("tcp"),
ngx_null_string,
0,
ngx_http_upstream_check_peek_handler,
ngx_http_upstream_check_peek_handler,
NULL,
NULL,
NULL,
0,
1 },

將最后一行的1改為0即可,根據數據結構分析可得知,這個1代表啟用keepalived,所以客戶端才不會主動斷開連接,因為這是tcp的端口連通性檢查,不需要keepalived,將其改為0禁止keepalived即可。

修改之后的代碼如下:

static ngx_check_conf_t ngx_check_types[] = {
{ NGX_HTTP_CHECK_TCP,
ngx_string("tcp"),
ngx_null_string,
0,
ngx_http_upstream_check_peek_handler,
ngx_http_upstream_check_peek_handler,
NULL,
NULL,
NULL,
0,
0 },

原因六:設置lingering_close

​ 即使你禁用了 http keepalive,nginx 仍然會嘗試處理 HTTP 1.1 pipeline 的請求。你可以配置
lingering_close off 禁用此行為,但這不是推薦的做法,因為會違反 HTTP 協議。見

http://nginx.org/en/docs/http/ngx_http_core_module.html#lingering_close

nginx快速定位異常

錯誤信息 錯誤說明
"upstream prematurely(過早的) closed connection" 請求uri的時候出現的異常,是由於upstream還未返回應答給用戶時用戶斷掉連接造成的,對系統沒有影響,可以忽略
"recv() failed (104: Connection reset by peer)" (1)服務器的並發連接數超過了其承載量,服務器會將其中一些連接Down掉; (2)客戶關掉了瀏覽器,而服務器還在給客戶端發送數據; (3)瀏覽器端按了Stop
"(111: Connection refused) while connecting to upstream" 用戶在連接時,若遇到后端upstream掛掉或者不通,會收到該錯誤
"(111: Connection refused) while reading response header from upstream" 用戶在連接成功后讀取數據時,若遇到后端upstream掛掉或者不通,會收到該錯誤
"(111: Connection refused) while sending request to upstream" Nginx和upstream連接成功后發送數據時,若遇到后端upstream掛掉或者不通,會收到該錯誤
"(110: Connection timed out) while connecting to upstream" nginx連接后面的upstream時超時
"(110: Connection timed out) while reading upstream" nginx讀取來自upstream的響應時超時
"(110: Connection timed out) while reading response header from upstream" nginx讀取來自upstream的響應頭時超時
"(110: Connection timed out) while reading upstream" nginx讀取來自upstream的響應時超時
"(104: Connection reset by peer) while connecting to upstream" upstream發送了RST,將連接重置
"upstream sent invalid header while reading response header from upstream" upstream發送的響應頭無效
"upstream sent no valid HTTP/1.0 header while reading response header from upstream" upstream發送的響應頭無效
"client intended to send too large body" 用於設置允許接受的客戶端請求內容的最大值,默認值是1M,client發送的body超過了設置值
"reopening logs" 用戶發送kill -USR1命令
"gracefully shutting down", 用戶發送kill -WINCH命令
"no servers are inside upstream" upstream下未配置server
"no live upstreams while connecting to upstream" upstream下的server全都掛了
"SSL_do_handshake() failed" SSL握手失敗
"ngx_slab_alloc() failed: no memory in SSL session shared cache" ssl_session_cache大小不夠等原因造成
"could not add new SSL session to the session cache while SSL handshaking" ssl_session_cache大小不夠等原因造成

參考:

https://github.com/alibaba/tengine/issues/901

https://my.oschina.net/u/1024107/blog/1838968

https://blog.csdn.net/zjk2752/article/details/21236725

http://nginx.org/en/docs/http/ngx_http_core_module.html#lingering_close

https://blog.csdn.net/crj121624/article/details/79956283t/u/1024107/blog/1838968

https://blog.csdn.net/zjk2752/article/details/21236725

http://nginx.org/en/docs/http/ngx_http_core_module.html#lingering_close

https://blog.csdn.net/crj121624/article/details/79956283

回到◀瘋狂創客圈

瘋狂創客圈 - Java高並發研習社群,為大家開啟大廠之門


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM