go-getter和context deadline exceeded

huangapple go评论83阅读模式
英文:

go-getter and context deadline exceeded

问题

我想使用go-getter v2从HTTP下载一些巨大的ZIP文件并将它们解压缩。

我尝试了以下代码(注意:defaultProgressBar是从这里获取的):

package main

import (
	"context"
	"log"

	getter "github.com/hashicorp/go-getter/v2"
)

func main() {
	ctx := context.Background()
	req := &getter.Request{
		Src:              "https://huge-file.zip",
		Dst:              "data/",
		Pwd:              "./",
		GetMode:          getter.ModeAny,
		ProgressListener: defaultProgressBar,
	}
	// client := getter.DefaultClient
	client := getter.Client{}
	_, err := client.Get(ctx, req)

	if err != nil {
		log.Fatal(err)
	}
}

这段代码总是返回context deadline exceeded。我应该了解关于上下文使用的内容吗?

英文:

I would like to use go-getter v2 to download from http some huge zip files and have them unpacked.

I try this code (note: defaultProgressBar taken from here)

package main

import (
	"context"
	"log"

	getter "github.com/hashicorp/go-getter/v2"
)

func main() {
	ctx := context.Background()
	req := &getter.Request{
		Src:              "https://huge-file.zip",
		Dst:              "data/",
		Pwd:              "./",
		GetMode:          getter.ModeAny,
		ProgressListener: defaultProgressBar,
	}
	// client := getter.DefaultClient
	client := getter.Client{}
	_, err := client.Get(ctx, req)

	if err != nil {
		log.Fatal(err)
	}
}

This code always returns context deadline exceeded. What should i known about context usage?

答案1

得分: 0

这是关于getter.Client的文档:

type Client struct {
	// Getters 是此客户端支持的协议列表。如果为nil,则使用默认的 Getters 变量。
	Getters []Getter

	// 其他字段被省略。
}

默认的 Getters 中的 HttpGetter 配置了一个 30秒ReadTimeout(参见 源代码):

httpGetter := &HttpGetter{
	Netrc:                 true,
	XTerraformGetDisabled: true,
	HeadFirstTimeout:      10 * time.Second,
	ReadTimeout:           30 * time.Second,
}

因此,错误是由默认的 HttpGetter 报告的。如果下载大文件需要超过30秒的时间,你应该使用合理的值配置 HttpGetter。请参考下面的示例:

package main

import (
	"context"
	"log"
	"net/http"
	"net/http/httptest"
	"time"

	getter "github.com/hashicorp/go-getter/v2"
)

func main() {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte{'a'})
		time.Sleep(31 * time.Second)
		w.Write([]byte{'b'})
	}))
	defer ts.Close()

	ctx := context.Background()
	req := &getter.Request{
		Src:     ts.URL,
		Dst:     "data.txt",
		Pwd:     "./",
		GetMode: getter.ModeAny,
	}
	client := &getter.Client{
		Getters: []getter.Getter{
			&getter.HttpGetter{
				Netrc:                 true,
				XTerraformGetDisabled: true,
				HeadFirstTimeout:      10 * time.Second,
				// 将 ReadTimeout 设置为大文件的合理值。
				ReadTimeout: 60 * time.Second,
			},
		},
	}

	log.Println("开始下载")

	_, err := client.Get(ctx, req)
	if err != nil {
		log.Fatal(err)
	}

	log.Println("完成!")
}
英文:

Here is the doc for getter.Client:

> go
> type Client struct {
> // Getters is the list of protocols supported by this client. If this
> // is nil, then the default Getters variable will be used.
> Getters []Getter
>
> // other fields are omitted.
> }
>

And the HttpGetter in the default Getters is configured with a ReadTimeout of 30s (see the source code):

httpGetter := &HttpGetter{
	Netrc:                 true,
	XTerraformGetDisabled: true,
	HeadFirstTimeout:      10 * time.Second,
	ReadTimeout:           30 * time.Second,
}

So the error is reported by the default HttpGetter. If the huge file takes more than 30s to download, you should configure the HttpGetter with a reasonable value. See the demo below:

package main

import (
	"context"
	"log"
	"net/http"
	"net/http/httptest"
	"time"

	getter "github.com/hashicorp/go-getter/v2"
)

func main() {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte{'a'})
		time.Sleep(31 * time.Second)
		w.Write([]byte{'b'})
	}))
	defer ts.Close()

	ctx := context.Background()
	req := &getter.Request{
		Src:     ts.URL,
		Dst:     "data.txt",
		Pwd:     "./",
		GetMode: getter.ModeAny,
	}
	client := &getter.Client{
		Getters: []getter.Getter{
			&getter.HttpGetter{
				Netrc:                 true,
				XTerraformGetDisabled: true,
				HeadFirstTimeout:      10 * time.Second,
				// Set the ReadTimeout to a reasonable value for the huge file.
				ReadTimeout: 60 * time.Second,
			},
		},
	}

	log.Println("begin downloading")

	_, err := client.Get(ctx, req)
	if err != nil {
		log.Fatal(err)
	}

	log.Println("done!")
}

huangapple
  • 本文由 发表于 2023年3月25日 22:35:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/75842389.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定