最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

go進(jìn)行http請求偶發(fā)EOF問題分析

 更新時間:2025年01月09日 08:49:44   作者:刀山羊  
go使用連接池進(jìn)行http請求,一般都能請求成功,但偶然會出現(xiàn)請求失敗返回EOF錯誤的情況,本文主要來帶大家分析一下為什么會出現(xiàn)這樣的問題并提供解決方法,需要的可以參考下

簡介

go使用連接池進(jìn)行http請求,一般都能請求成功,但偶然會出現(xiàn)請求失敗返回EOF錯誤的情況;類似java的org.apache.http.NoHttpResponseException

分析

客戶端通過keep alive機(jī)制保障性能,簡單理解就是復(fù)用tcp五元會話,用于進(jìn)行多次http請求;但如果服務(wù)端的空閑?;顣r間是10s,在第一次請求完的10s進(jìn)行了第二次請求,此時客戶端認(rèn)為連接仍然有效繼續(xù)發(fā)起請求,但服務(wù)端發(fā)出了FIN報(bào)文不再對此連接進(jìn)行響應(yīng),從而導(dǎo)致客戶端請求失敗并出現(xiàn)EOF錯誤。

偶發(fā)就是因?yàn)閮蓚€時間要恰好碰到一起才可能觸發(fā)這個問題

  • 服務(wù)器發(fā)送了FIN報(bào)文,但是客戶端還沒有收到,但是客戶端已經(jīng)發(fā)送了請求數(shù)據(jù)包
  • 如果在服務(wù)器超時前發(fā)起了請求,那連接此時還可用,正常
  • 如果在服務(wù)器超時后發(fā)起了請求,那連接已經(jīng)完成FIN關(guān)閉流程,請求會觸發(fā)新的會話,正常

解決方式:

  • 在出現(xiàn)EOF的時候,進(jìn)行重試,此時會觸發(fā)新的五元組連接進(jìn)行請求(推薦)
  • 設(shè)置客戶端的空閑?;顣r間小于服務(wù)端的空閑?;顣r間
    • IdleConnTimeout 此時客戶端會在超時時主動向服務(wù)端發(fā)送RST進(jìn)行連接重置

代碼

package main

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"time"
)

func main() {
	// 創(chuàng)建自定義的 Transport,設(shè)置連接池參數(shù)
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{
			InsecureSkipVerify: true, // 忽略 TLS 證書驗(yàn)證
		},
		MaxIdleConns:        1,                // 限制最大空閑連接數(shù)為1
		MaxIdleConnsPerHost: 1,                // 限制每個host最大空閑連接數(shù)為1
		IdleConnTimeout:     20 * time.Second, // 本地空閑連接超時設(shè)置為20s
		DisableKeepAlives:   false,            // 啟用 keep-alive
		MaxConnsPerHost:     1,                // 限制每個host的最大連接數(shù)為1,強(qiáng)制復(fù)用連接
		ForceAttemptHTTP2:   false,            // 禁用 HTTP/2
	}

	// 創(chuàng)建 HTTP 客戶端
	client := &http.Client{
		Transport: tr,
		Timeout:   5 * time.Second, // 設(shè)置請求超時時間
	}

	// 準(zhǔn)備請求參數(shù)
	url := "https://192.168.24.70:2018/api/zguard/sysmng/syscfg/basecfg/sysname/651d5b9f-225b-4c8c-9f06-80bfad3fa977"
	cookie := "session-id=f416b188c91bc72a06853b362d5cb7b3a6b68a43"

	// 準(zhǔn)備請求體數(shù)據(jù)
	requestBody := map[string]string{
		"sys_name": "N-GUARD",
	}
	// 將 map 轉(zhuǎn)換為 JSON
	jsonBody, err := json.Marshal(requestBody)
	if err != nil {
		fmt.Printf("JSON 編碼失敗: %v\n", err)
	}

	// 循環(huán)發(fā)送請求,模擬使用已關(guān)閉的連接
	for i := 0; i < 5; i++ { // 只測試兩次請求即可

		// 每次請求都創(chuàng)建新的 bytes.Buffer,確保 Body 可以重復(fù)讀取
		bodyReader := bytes.NewBuffer(jsonBody)

		req, err := http.NewRequest("PUT", url, bodyReader)
		if err != nil {
			fmt.Printf("創(chuàng)建請求失敗: %v\n", err)
			continue
		}

		// 設(shè)置 Content-Length
		req.ContentLength = int64(len(jsonBody))
		// 設(shè)置請求頭
		req.Header.Set("Cookie", cookie)
		req.Header.Set("Content-Type", "application/json")

		fmt.Printf("發(fā)送第 %d 個請求...\n", i+1)
		// 發(fā)送請求
		resp, err := client.Do(req)
		if err != nil {
			fmt.Printf("請求失敗: %v\n", err)
			if errors.Is(err, io.EOF) {
				fmt.Printf("連接不再可用: 重試:新的五元重新發(fā)起連接\n")
				bodyReader := bytes.NewBuffer(jsonBody)

				reqretry, err := http.NewRequest("PUT", url, bodyReader)
				if err != nil {
					fmt.Printf("創(chuàng)建請求失敗: %v\n", err)
					continue
				}

				// 設(shè)置 Content-Length
				reqretry.ContentLength = int64(len(jsonBody))
				// 設(shè)置請求頭
				reqretry.Header.Set("Cookie", cookie)
				reqretry.Header.Set("Content-Type", "application/json")

				resp, err = client.Do(reqretry)
				if err != nil {
					fmt.Printf("err:\n", err)
					continue
				}
			} else {
				continue
			}
		}

		// 讀取響應(yīng)
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Printf("讀取響應(yīng)失敗: %v\n", err)
		}
		resp.Body.Close()

		fmt.Printf("請求 %d - 狀態(tài)碼: %d, 響應(yīng): %s\n", i+1, resp.StatusCode, string(body))

		fmt.Println("等待10秒后發(fā)送第二個請求...")
		time.Sleep(10 * time.Second) // 等待10秒,此時服務(wù)端已經(jīng)關(guān)閉連接(10s)
		time.Sleep(500 * time.Millisecond)
	}
}

運(yùn)行

[xiaofeng@localhost httpkeepalive]$ go run main.go 
發(fā)送第 1 個請求...
請求 1 - 狀態(tài)碼: 200, 響應(yīng): {"code":0,"result":"0","message":"成功"}
等待10秒后發(fā)送第二個請求...
發(fā)送第 2 個請求...
請求 2 - 狀態(tài)碼: 200, 響應(yīng): {"code":0,"result":"0","message":"成功"}
等待10秒后發(fā)送第二個請求...
發(fā)送第 3 個請求...
請求失敗: Put "https://192.168.24.70:2018/api/zguard/sysmng/syscfg/basecfg/sysname/651d5b9f-225b-4c8c-9f06-80bfad3fa977": EOF
連接不再可用: 重試:新的五元重新發(fā)起連接
請求 3 - 狀態(tài)碼: 200, 響應(yīng): {"code":0,"result":"0","message":"成功"}
等待10秒后發(fā)送第二個請求...
發(fā)送第 4 個請求...
請求失敗: Put "https://192.168.24.70:2018/api/zguard/sysmng/syscfg/basecfg/sysname/651d5b9f-225b-4c8c-9f06-80bfad3fa977": EOF
連接不再可用: 重試:新的五元重新發(fā)起連接
請求 4 - 狀態(tài)碼: 200, 響應(yīng): {"code":0,"result":"0","message":"成功"}
等待10秒后發(fā)送第二個請求...
發(fā)送第 5 個請求...
請求 5 - 狀態(tài)碼: 200, 響應(yīng): {"code":0,"result":"0","message":"成功"}
等待10秒后發(fā)送第二個請求...

報(bào)文

到此這篇關(guān)于go進(jìn)行http請求偶發(fā)EOF問題分析的文章就介紹到這了,更多相關(guān)go http請求偶發(fā)EOF內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于go-cqhttp與Flask搭建定制機(jī)器人項(xiàng)目實(shí)戰(zhàn)示例

    基于go-cqhttp與Flask搭建定制機(jī)器人項(xiàng)目實(shí)戰(zhàn)示例

    這篇文章主要為大家介紹了基于go-cqhttp與Flask搭建定制機(jī)器人項(xiàng)目實(shí)戰(zhàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • golang時間及時間戳的獲取轉(zhuǎn)換

    golang時間及時間戳的獲取轉(zhuǎn)換

    本文主要介紹了golang時間及時間戳的獲取轉(zhuǎn)換,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • 詳解Golang編程中的常量與變量

    詳解Golang編程中的常量與變量

    這篇文章主要介紹了詳解Golang編程中的常量與變量,是Go語言入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-10-10
  • Go語言命令行操作命令詳細(xì)介紹

    Go語言命令行操作命令詳細(xì)介紹

    這篇文章主要介紹了Go語言命令行操作命令詳細(xì)介紹,本文重點(diǎn)介紹了go build、go clean、go fmt、go get等命令,需要的朋友可以參考下
    2014-10-10
  • Go語言中處理錯誤的技巧分享

    Go語言中處理錯誤的技巧分享

    編寫 Go 語言程序時,有效地處理錯誤是至關(guān)重要的,Go 語言提供了一些強(qiáng)大的工具和模式來處理錯誤,本文將介紹這些方法,以便編寫健壯的 Go 代碼,更好地處理錯誤,需要的朋友可以參考下
    2023-09-09
  • Go語言并發(fā)范式之future模式詳解

    Go語言并發(fā)范式之future模式詳解

    編程中經(jīng)常遇到在一個流程中需要調(diào)用多個子調(diào)用的情況,此時就可以使用Go并發(fā)編程中的future模式,下面小編就來和大家聊聊future模式的具體使用,需要的可以參考一下
    2023-06-06
  • Go語言中Once懶加載的藝術(shù)詳析

    Go語言中Once懶加載的藝術(shù)詳析

    Go語言以其簡潔高效的并發(fā)模型贏得了無數(shù)開發(fā)者的青睞,下面這篇文章主要介紹了Go語言中Once懶加載的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2026-04-04
  • 關(guān)于Go 是傳值還是傳引用?

    關(guān)于Go 是傳值還是傳引用?

    這篇文章主要討論Go語言 是傳值還是傳引用?文章先從Go 官方的定義展開,隨后是傳值和傳引用得介紹到map 和 slice得區(qū)別,需要的小伙伴可以參考一下文章得具體內(nèi)容
    2021-10-10
  • Go設(shè)計(jì)模式之備忘錄模式圖文詳解

    Go設(shè)計(jì)模式之備忘錄模式圖文詳解

    備忘錄模式是一種行為設(shè)計(jì)模式, 允許在不暴露對象實(shí)現(xiàn)細(xì)節(jié)的情況下保存和恢復(fù)對象之前的狀態(tài),本文主要通過一些圖片來給大家介紹一下Go的備忘錄模式,需要的朋友可以參考下
    2023-08-08
  • GoLang channel使用介紹

    GoLang channel使用介紹

    Channel 和 goroutine 的結(jié)合是 Go 并發(fā)編程的大殺器。而 Channel 的實(shí)際應(yīng)用也經(jīng)常讓人眼前一亮,通過與 select,cancel,timer 等結(jié)合,它能實(shí)現(xiàn)各種各樣的功能。接下來,我們就要梳理一下 channel 的應(yīng)用
    2022-10-10

最新評論

海盐县| 西安市| 微山县| 临江市| 崇信县| 偏关县| 六枝特区| 七台河市| 乌鲁木齐县| 合水县| 高雄县| 睢宁县| 揭西县| 土默特左旗| 铜陵市| 吉隆县| 东光县| 虹口区| 洞口县| 信阳市| 西畴县| 固原市| 财经| 清徐县| 临朐县| 商南县| 山东| 兴化市| 翼城县| 措美县| 江津市| 浪卡子县| 浦县| 西华县| 建德市| 阿克| 贵德县| 乡城县| 永川市| 阜城县| 龙海市|