亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

多閱讀器的并發 POST 不返回響應

多閱讀器的并發 POST 不返回響應

Go
撒科打諢 2023-03-21 17:02:42
我有一個使用echo的概念驗證 http 服務器,它接受帶有 JSON 正文的 POST 請求。我正在嘗試使用管道和多寫入器將請求主體流式傳輸到多個 POST 請求,但它無法正常工作。在下面的示例中,我可以看到數據被發送到 2 個 POST 端點,我可以看到來自這些請求的日志,但我從未收到回復,似乎代碼掛起等待功能完成http.Post(...)。如果我直接調用這兩個端點,它們可以正常工作并給出有效的 json 響應,所以我相信問題出在這段代碼上,它是我的路由處理程序。func ImportAggregate(c echo.Context) error {    oneR, oneW := io.Pipe()    twoR, twoW := io.Pipe()    done := make(chan bool, 2)    go func() {        fmt.Println("Product Starting")        response, err := http.Post("http://localhost:1323/products/import", "application/json", oneR)        if err != nil {            fmt.Println(err)        } else {            fmt.Println(response.Body)        }        done <- true    }()    go func() {        fmt.Println("Import Starting")        response, err := http.Post("http://localhost:1323/discounts/import", "application/json", twoR)        if err != nil {            fmt.Println(err)        } else {            fmt.Println(response.Body)        }        done <- true    }()    mw := io.MultiWriter(oneW, twoW)    io.Copy(mw, c.Request().Body)    <-done    <-done    return c.String(200, "Imported")}控制臺中的輸出是:Product StartingImport Starting
查看完整描述

1 回答

?
心有法竹

TA貢獻1866條經驗 獲得超5個贊

OP 代碼中的問題是 http.Post 調用從不檢測所提供的 io.Reader 的 EOF。

發生這種情況是因為提供的半寫管道永遠不會關閉,因此,半讀管道永遠不會發出常規的 EOF 錯誤。

作為關于關閉半讀管道會產生不規則錯誤的 OP 評論的注釋,必須了解從關閉的管道讀取不是正確的行為。

因此在這種情況下,應注意在復制完內容后立即關閉半寫側。

生成的源代碼應更改為

func ImportAggregate(c echo.Context) error {

    oneR, oneW := io.Pipe()

    twoR, twoW := io.Pipe()


    done := make(chan bool, 2)


    go func() {

        fmt.Println("Product Starting")

        response, err := http.Post("http://localhost:1323/products/import", "application/json", oneR)

        if err != nil {

            fmt.Println(err)

        } else {

            fmt.Println(response.Body)

        }

        done <- true

    }()


    go func() {

        fmt.Println("Import Starting")

        response, err := http.Post("http://localhost:1323/discounts/import", "application/json", twoR)

        if err != nil {

            fmt.Println(err)

        } else {

            fmt.Println(response.Body)

        }

        done <- true

    }()


    mw := io.MultiWriter(oneW, twoW)

    io.Copy(mw, c.Request().Body)

    oneW.Close()

    twoW.Close()


    <-done

    <-done


    return c.String(200, "Imported")

}

OP 問題之外的旁注:

  • 必須圍繞 io.Copy 實施錯誤檢查以檢測傳輸錯誤。

  • 不需要關閉管道的半讀端,http.Post 將在收到 EOF 信號后執行此操作。

  • 必須在復制輸入請求之前聲明并啟動負責使用管道的 goroutine。Pipes 是同步的,代碼會在 io.Copy 等待另一端被消耗的過程中阻塞。

  • done chan 不需要無緩沖(長度為 2)

  • 一種將錯誤從傳出請求轉發到傳出響應的方法是使用 type 的通道(chan error),循環兩次,并檢查遇到的第一個錯誤。


查看完整回答
反對 回復 2023-03-21
  • 1 回答
  • 0 關注
  • 92 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號