go - 随机 REFUSED_STREAM 发出 POST 多部分表单请求

标签 go

这是使用 golang 将 apk 文件(几 MB)上传到 appetize.io 的代码:

func uploadToAppetize(file multipart.File, branchName string, displayName string) (result *AppetizeRes, ok bool) {
    file.Seek(0, 0)
    url, _ := getUrl()
    var buffer bytes.Buffer
    writer := multipart.NewWriter(&buffer)
    fileName := displayName + "/" + branchName
    part, err := writer.CreateFormFile("file", fileName)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Error creating form file %v: %v\n", fileName, err)
        return nil, false
    }

    size, err := io.Copy(part, file)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Error copying apk file data: %v\n", err)
        return nil, false
    }
    fmt.Fprintf(os.Stdout, "Copied %v bytes for uploading to appetize...\n", size)
    writer.Close()
    response, err := http.Post(url, writer.FormDataContentType(), &buffer) // Random error on this line
    if err != nil || response == nil {
        fmt.Fprintf(os.Stderr, "Error occurred uploading apk data to appetize.io: %v %v\n", err, response)
        return nil, false
    }
    defer response.Body.Close()
    if response.StatusCode != http.StatusOK {
        return nil, false
    }

    var appetizeRes AppetizeRes
    if err := json.NewDecoder(response.Body).Decode(&appetizeRes); err != nil {
        return nil, false
    }
    return &appetizeRes, true
}

但是我在 http.Post(...) 行收到一个随机错误。它返回一个零响应和一个错误。错误是“流错误:流 ID 1;REFUSED_STREAM”。它是随机发生的,但肯定会在 go 程序启动后第一次发出请求时发生。

这是 go 版本:

go version go1.8.1 darwin/amd64

如果没有失败,这是来自服务器的响应头: enter image description here

我也在另一台运行 go 1.6.* 的 mac 上运行这个程序。我不记得我曾经在那台 mac 上遇到过这个问题。

知道发生了什么吗?

最佳答案

golang 标准库 net/http 中存在一个错误,无法正确处理 REFUSED_STREAM http/2 错误。这是可能发生的事情:

  1. golang 客户端打开到 HTTP/2 www 服务器的 TCP 连接,将连接中的最大 HTTP 流数设置为 1000 并立即开始上传。

  2. HTTP/2 www 服务器告诉 golang 客户端只使用给定数量的流,但 golang 客户端已经启动了超过该数量的流。

  3. HTTP/2 www 服务器通过重置多余的流对此作出 react 。

  4. golang net/http 代码中缺乏对重试的适当支持导致流在服务器重置后失败,最终上传也失败。

在 github 上有一个关于这个问题的票:x/net/http2: retry requests rejected with REFUSED_STREAM - golang/go/issues/20985

**此问题已在 master 分支中关闭,修复将包含在未来的 Golang 1.10 版本中

关于go - 随机 REFUSED_STREAM 发出 POST 多部分表单请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44089111/

相关文章:

mongodb - Mgo 如何在嵌套数组中查找嵌套文档?

go - 如何将一个 go 程序在终端中的输出传输到另一个程序?

arrays - 如何在 Go 中将数字列表读入数组

go - 为什么没有类型不匹配错误?

go - 进行测试可以访问生产功能,但不能访问测试功能

GoLang-术语框 : panic: open/dev/tty: no such device or address

go - 无法使用 goprotobuf 解码消息

sqlite - 无法在Windows上通过TDM-GCC使用cgo编译Go应用程序

firebase - 连接到 Firebase 存储桶

go - 检查go代码是否已经格式化