使用 fasthttp 時要注意的兩個點

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。# 我們做的是彙總支付系統,使用的是fasthttp 作為http server, http client 也是使用fasthttp ### 1. 第一個問題出現的情境是我們使用fasthttp client 請求支付時報了這個err ErrConnectionClosed```the server closed connection before returning the first response byte Make sure the server returns 'Connection: close' response header before closing the connection```![image.png](http://upload-images.jianshu.io/upload_images/5964227-96ef9323a9780a9f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)由於是線上問題 情況緊急,查了一些資料後覺得使用fasthttp client 估計有坑,零時換成 go 原生 http client ,果然解決了問題。那麼問題來了,怎麼會出現這中情況呢,這個錯誤的字面意思是 連結被對端關閉了,說到這裡 就有一個要 注意了,fasthttp 預設使用的是 http1.1 golang 裡面 預設是 keep-live 保持長連結的,但是對方關閉了連結我們 發包時 報的錯誤 應該是Connection reset by peer 呀,怎麼是這麼個玩意兒,只能抓包看看 囉, 結果發現 我們一個請求過去正常回包後,8秒過後 又收到一個FIN 包,此時就懷疑的 keep-live 時間了 ,那麼 我就列印了一下 回包的head ,果然 keep-live 時間就是8s ,也就是說 8s 後 關閉了連結,不巧 我們的fasthttp 空閑等待時間是 15s 。還是沒弄明白,按道理對端關閉了 ,client 端 應該是有感知的, 而且換成了 golang 原生 http client 就解決了問題,說明原生的client 是 有感知的,只能看代碼了,結果發現了有意思的![image.png](http://upload-images.jianshu.io/upload_images/5964227-c69e8c2ca3516a4f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)從可以看出來,這個fasthttp client write 和 read是 同步的如果第一個請求 之後 8s 之內不再請求 ,那麼我們是不會再進行read 操作的,那麼就無法感知 已經 被server 端關閉了。此時問題又來了, 8s 後請求 對端已經發了 FIN 我們再次write 應該是 Connection reset by peer 錯誤吧,其實不對 ,這裡就涉及 tcp 的 四次揮手了, server 發了FIN 包 只能說明 server 不再 write 了 ,但是 server 是可以再read 的 ,也就是說 client 是可以再 wirte 的,剛好錯誤就是在第二次 請求 的read 操作時報出的。這裡證明了錯誤的產生原因。但是有 一個疑問 沒解決,為什麼用 原生 http client 沒問題, 進一步來分析下,看代碼![image.png](http://upload-images.jianshu.io/upload_images/5964227-8e96471f7613ce43.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)可以看到兩個 協程 在 loop write read,所以對 server 端 FIN 是 及時響應的,也就是client 及時也關閉了連結。問題找到了如何解決呢,兩個方法:> 1. 簡單粗暴,直接 設定 head 要求標頭 keep-live close ,變成短連結,但是這個有損效能。> 2. 既然 keep-live 是 8s 那麼 只要 設定 IdleConnTimeout 小於 8s 就行了 比如 7s , 這樣就可以先於 關閉串連了,不會讓新的請求 使用 對端 發了 FIN 的連結 。# 第二個問題 fasthttp 優雅關閉關不掉我們使用了 fasthttp 作為 http server . 為了保證 業務完整性,做了一個 優雅關閉功能 ,其實優雅關閉思路很簡單:收到 signal QUIT 後 首先close 調 監聽 連接埠, 然後等所有的連結上的業務處理完畢後 退出程式 就OK 了 , 那麼如果 保證 所有連結處理完畢呢, 計數器!!! 建立一個連結時 +1 關閉一個連結時 -1 , 具體實現 其實就是實現 net.Listener 的 accept 和 close 介面 ,例如:![image.png](http://upload-images.jianshu.io/upload_images/5964227-090d5753ce31507a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)實現思路 是這樣的 按道理 就OK 了,其實不是的,我是這麼測試的:用一個 golang client for 迴圈 每隔5秒 發一個 請求, 然後在server 端 發送kill signal QUIT 結果發現程式一直沒有退出, 怎麼回事呢 ,除非 連結數 一直沒有 減到 0 ,後來列印日誌發現 確實沒有,但是沒道理啊, 一個請求處理了應該 close 呀, 此時 又想起了 http1.1 預設 keep-live 我每隔5秒 發一個請求,而設定的 server 最大空閑等待時間為15分鐘, 也就是雖然 listener 關閉了 不會再有新的連結進來,但是 正在跑的這個連結永遠不會主動關閉,因為每隔五秒 就有一個請求怎麼解決呢 ? 想到一個方法,就是設定一個標誌判斷是否程式 被關閉,當收到了signal QUIT 之後 就把正在處理的 連結的 resonse head 設定 connection close ,如何設定呢, 因為 我們我們處理的請求 都是在 一個 fasthttp.RequestHandler ,可以封裝一下 這個 函數 例如:![image.png](http://upload-images.jianshu.io/upload_images/5964227-afb221e685b29143.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)這樣我們每個請求完畢之後,檢測到stop 標誌後 必定處理會關閉連結。貌似 解決了,其實還有點漏洞,就是這個stop 標誌的檢測 是代碼要運行到這裡,如果設定了stop 標誌代碼,但此時這條連結上的沒有請求過來怎麼辦(j假如我是10分鐘發一個請求),那麼只能等待 IdleConnTimeout 逾時的時候關閉連結了,但是 我們關閉一個程式的時候 不希望等待那麼久,可以看看 這段代碼:![image.png](http://upload-images.jianshu.io/upload_images/5964227-f520649fae37eea7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) listener 有一個maxWaitTime,就是程式無論有沒有包在處理,到了這個時間程式 一定要退出,比如這個時間設定為 3秒,當然這個問題 也是有漏洞的萬一 我們一個請求 處理耗時 不止3s 呢,豈不是不能完整處理這個請求, 當然我們業務一般一個請求一秒就處理完了。 不過這個問題確實存在,目前我還沒想到一個好的辦法徹底解決這個問題,如果你們有想法可以告訴我一下。總結一下,這些主要是關於fasthttp 使用時要注意的問題,http協議 get post 雖然簡單,但是要用好 還是要好好研究下, tcp 協議也要好好理解下,三向交握,四次揮手 還是有很多值得深究的,也很有意思。今天太冷就不多寫了,寫的有問題之處,還望多多指點。 2126 次點擊  ∙  2 贊  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.