GAE Golang – urlfetch超时?

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

GAE Golang - urlfetch timeout?

问题

我在Google App Engine中使用Go语言的urlfetch遇到了超时问题。应用似乎不愿意接受超过5秒的超时时间(它会忽略更长的超时时间并在自己的时间后超时)。

我的代码是:

var TimeoutDuration time.Duration = time.Second*30

func Call(c appengine.Context, address string, allowInvalidServerCertificate bool, method string, id interface{}, params []interface{})(map[string]interface{}, error){
    data, err := json.Marshal(map[string]interface{}{
        "method": method,
        "id":     id,
        "params": params,
    })
    if err != nil {
        return nil, err
    }
    
    req, err:=http.NewRequest("POST", address, strings.NewReader(string(data)))
    if err!=nil{
        return nil, err
    }
    
    tr := &urlfetch.Transport{Context: c, Deadline: TimeoutDuration, AllowInvalidServerCertificate: allowInvalidServerCertificate}
    
    resp, err:=tr.RoundTrip(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }
    result := make(map[string]interface{})
    err = json.Unmarshal(body, &result)
    if err != nil {
        return nil, err
    }
    return result, nil
}

无论我将TimeoutDuration设置为什么值,应用都会在大约5秒后超时。如何防止这种情况发生?我的代码中是否有错误?

英文:

I am having issues with urlfetch's timeouts on Google App Engine in Go. The app does not appear to want to take a longer timeout than about 5 seconds (it ignores a longer timeout and times out after its own time).

My code is:

var TimeoutDuration time.Duration = time.Second*30

func Call(c appengine.Context, address string, allowInvalidServerCertificate bool, method string, id interface{}, params []interface{})(map[string]interface{}, error){
    data, err := json.Marshal(map[string]interface{}{
        "method": method,
        "id":     id,
        "params": params,
    })
    if err != nil {
        return nil, err
    }
    
    req, err:=http.NewRequest("POST", address, strings.NewReader(string(data)))
    if err!=nil{
        return nil, err
    }
    
    tr := &urlfetch.Transport{Context: c, Deadline: TimeoutDuration, AllowInvalidServerCertificate: allowInvalidServerCertificate}
    
    resp, err:=tr.RoundTrip(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }
    result := make(map[string]interface{})
    err = json.Unmarshal(body, &result)
    if err != nil {
        return nil, err
    }
    return result, nil
}

No matter what I try to set TimeoutDuration to, the app times out after about 5 seconds. How prevent it from doing that? Did I make some error in my code?

答案1

得分: 13

你需要像这样传递时间持续时间(否则它将默认为5秒超时):

tr := &urlfetch.Transport{Context: c, Deadline: time.Duration(30) * time.Second}

更新于2016年1月2日:

使用新的GAE golang包(google.golang.org/appengine/*),这已经改变了。在传输中,urlfetch不再接收截止时间持续时间。

现在,您应该通过新的上下文包设置超时。例如,这是如何设置1分钟截止时间的示例:

func someFunc(ctx context.Context) {
	ctx_with_deadline, _ := context.WithTimeout(ctx, 1*time.Minute)
	client := &http.Client{
		Transport: &oauth2.Transport{
			Base:   &urlfetch.Transport{Context: ctx_with_deadline},
		},
	}
英文:

You need to pass the time duration like this (otherwise it will default to the 5 sec timeout):

tr := &urlfetch.Transport{Context: c, Deadline: time.Duration(30) * time.Second}

Update Jan 2 2016:

With the new GAE golang packages (google.golang.org/appengine/*), this has changed. urlfetch no longer receives a deadline time duration in the transport.

You should now set the timeout via the new context package. For example, this is how you would set a 1 minute deadline:

func someFunc(ctx context.Context) {
	ctx_with_deadline, _ := context.WithTimeout(ctx, 1*time.Minute)
	client := &http.Client{
		Transport: &oauth2.Transport{
			Base:   &urlfetch.Transport{Context: ctx_with_deadline},
		},
	}

答案2

得分: 3

尝试下面的代码:

// createClient是带有截止时间的urlfetch.Client
func createClient(context appengine.Context, t time.Duration) *http.Client {
    return &http.Client{
        Transport: &urlfetch.Transport{
            Context:  context,
            Deadline: t,
        },
    }
}

以下是如何使用它的方法。

// urlfetch
client := createClient(c, time.Second*60)

感谢 @gosharplite

英文:

Try the code below:

// createClient is urlfetch.Client with Deadline
func createClient(context appengine.Context, t time.Duration) *http.Client {
    return &http.Client{
        Transport: &urlfetch.Transport{
            Context:  context,
            Deadline: t,
        },
    }
}

Here is how to use it.

// urlfetch
client := createClient(c, time.Second*60)

Courtesy @gosharplite

答案3

得分: 2

查看Go的appengine源代码:

以及生成的协议缓冲区代码:

看起来Duration本身应该没有问题。

我猜测整个在appengine中的应用程序在5秒后超时。

英文:

Looking at the source code of Go's appengine:

and the protobuffer generated code:

Looks like there should not be a problem with Duration itself.

My guess is that the whole application inside appengine timeouts after 5 seconds.

答案4

得分: 2

对我来说,这个方法有效:

ctx_with_deadline, _ := context.WithTimeout(ctx, 15*time.Second)
client := urlfetch.Client(ctx_with_deadline)
英文:

for me, this worked:

ctx_with_deadline, _ := context.WithTimeout(ctx, 15*time.Second)
client := urlfetch.Client(ctx_with_deadline)

答案5

得分: 1

这是最近对库进行的更新后所做的更改。现在超时/延迟的持续时间必须由上下文传递,urlfetch.transport中不再有截止日期字段。context.WithTimeoutcontext.WithDeadline是要使用的方法,这是链接https://godoc.org/golang.org/x/net/context#WithTimeout。

英文:

This is had now changed with the recent updates to the library . Now the Duration of timeout/delay have to carried by the context , urlfetch.transport no more has the Deadline field in it . context.WithTimeout or context.WithDeadline is the method to use , here is the link https://godoc.org/golang.org/x/net/context#WithTimeout

huangapple
  • 本文由 发表于 2012年11月10日 07:22:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/13317472.html
匿名

发表评论

匿名网友

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

确定