使用Golang 1.20.1.

在Golang的net/http和上下文包中,我无法设置超过30秒的超时.设置较短的超时时间很好,例如

代码:

    log.Infof("Elasticsearch URL is %v", elasticsearchURL)
    client := &http.Client{Timeout: time.Duration(time.Second * 60)}
    req, err := http.NewRequest("GET", listBackupsURL, nil)
    if err != nil {
        internalError(w, fmt.Sprintf("error creating request: %v", err))
        return
    }
    req.SetBasicAuth(username, password)
    resp, err := client.Do(req)
    if err != nil {
        // handle error
        internalError(w, fmt.Sprintf("error accessing elasticsearch: %v", err))
        return
    }

日志(log):

I0503 23:01:55.973821       1 somecode.go:85] URL is http://elasticsearch.example.ingest:9200
E0503 23:02:25.976345       1 caller_handler.go:63] 500 Internal Server Error: error accessing elasticsearch: Get "http://elasticsearch.example.ingest:9200/_cat/snapshots/object-store-repo?v&s=id": dial tcp 1.2.3.4:9200: i/o timeout

超时时间是30秒,而不是60秒.

如果我使用http.NewRequestWithContext(...)并使用上下文设置相同的超时,我会得到相同的行为:

代码:

    log.Infof("Elasticsearch URL is %v", elasticsearchURL)
    ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Second * 60)) 
    defer cancel()
    req, err := http.NewRequestWithContext(ctx, "GET", listBackupsURL, nil)
    if err != nil {
        internalError(w, fmt.Sprintf("error creating request: %v", err))
        return
    }
    req.SetBasicAuth(username, password)
    resp, err := client.Do(req)
    if err != nil {
        // handle error
        internalError(w, fmt.Sprintf("error accessing elasticsearch: %v", err))
        return
    }

日志(log):

I0503 23:31:10.941169       1 somecode.go:85] Elasticsearch URL is http://elasticsearch.example.ingest:9200
E0503 23:31:40.941642       1 caller_handler.go:63] 500 Internal Server Error: error accessing elasticsearch: Get "http://elasticsearch.example.ingest:9200/_cat/snapshots/object-store-repo?v&s=id": dial tcp 1.2.3.4:9200: i/o timeout

但是,如果我将超时更改为3秒(在任何一种方法中都是time.Duration(time.Second * 3))秒),它将按预期工作:

I0503 23:44:17.622121       1 somecode.go:85] Elasticsearch URL is http://elasticsearch.example.ingest:9200
E0503 23:44:20.624795       1 caller_handler.go:63] 500 Internal Server Error: error accessing elasticsearch: Get "http://elasticsearch.example.ingest:9200/_cat/snapshots/object-store-repo?v&s=id": context deadline exceeded (Client.Timeout exceeded while awaiting headers)

推荐答案

我会隔离问题以排除可能性,以帮助缩小导致它发生的因素.如果可能,使用一小段代码,以便只处理您想要的内容.

为了测试您的基础架构,httpstat将帮助您模拟远程超时.示例:

func main() {

    client := &http.Client{Timeout: time.Duration(time.Second * 200)}
    req, err := http.NewRequest("GET", "https://httpstat.us/504?sleep=120000", nil)
    if err != nil {
        log.Fatal(err)
        return
    }

    resp, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
        return
    }

    fmt.Println(resp)
}

如果此时出现dial tcp IP:PORT: i/o timeout超时,则需要判断您的操作系统和防火墙.无论你在Go中设置什么超时,都应该覆盖操作系统的默认设置,如果你以这种方式获得超时,可能是防火墙(本地或远程)导致的.

或者,如果您能够从外部连接,那么ES可能会超时,尽管根据文档,您应该预料到直接来自ES的信息性错误.您可以设置ES directly in the URL的超时时间,并对其进行测试.

希望这能帮上忙.

Go相关问答推荐

GoLang:无法发送带有附件的邮箱

错误&对象已被Golang在K8s操作符上修改

如何配置vscode以在Go中显示不必要的(过度指定的)泛型?

格式化 Azure SDK 的 golang 时间

从带有嵌套括号的字符串中提取值

Kusto Go API 从多个表查询

Go Build删除信息

在golang二进制中嵌入SvelteKit

在 Go sync.Map 中,为什么这部分实现不一致或者我误解了什么?

如何从 Asterisk Manager Interface Event 获取活动呼叫数

Golang crypto/rand 线程安全吗?

在 Go 模板中对照片使用随机 Int

fmt.Printf() 标志 '0' 不会被字符串忽略

Golang invopop jsonschema 使用 if/then/else

函数超时和 goroutine 泄漏

同时调用应该只获取一次数据

go 是否对 struct 使用空间填充之类的东西?

Golang Echo Labstack 如何在模板视图中调用函数/方法

如何扩充 ResponseWriter 的 Header() 返回的 map

如何使用 httputil.ReverseProxy 设置 X-Forwarded-For