While using a single http client for several goroutines, does editing the transport on one thread affect the other?

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

While using a single http client for several goroutines, does editing the transport on one thread affect the other?

问题

假设我在程序中有一个全局的net/http client。在这个程序中,我有几个goroutine使用相同的全局client进行请求。例如:

Golang伪代码:

package main

func editTransportAndFetch(c *http.Client) {
    c.Transport = &http.Transport{
        // 在这里进行一些独特的更改
    }
    c.Get("https://www.google.com")
}

func main() {
    client := http.Client
    
    // 生成10个进程
    for i := 0; i < 10; i++ {
        go editTransportAndFetch(client)
    }
}

在这个伪代码示例中,我演示了生成10个正在被编辑的http.Transport进程。在这个示例中,进行了完全相同的更改,所以可能不太需要担心干扰。然而,无论如何,如果这些进程是并发进行的,一个进程更新全局client的transport是否会干扰另一个进程可能正在使用的transport呢?

我的最终用例是,我想要一个全局的client,并且能够为特定的请求指定自定义的DialTLSContext,但只针对某些请求。我不希望使用DialTLSContext的请求也可能同时运行。我担心如果我编辑了一个请求的client的http.Transport,它可能会干扰并导致另一个请求也使用DialTLSContext,即使我不希望如此。

英文:

Lets say I have a global net/http client in my program. Within this program, I have several goroutines making requests with the same global client. E.g.

Golang Pseudocode:

package main

func editTransportAndFetch(c *http.Client) {
    c.Transport = &http.Transport{
        // Make some unique change here
    }
    c.Get("https://www.google.com")
}

func main() {
    client := http.Client
    
    // Spawns 10 processes
    for i := 0; i < 10; i++ {
        go editTransportAndFetch(client)
    }
}

In this pseudocode example, I demonstrate spawning 10 processes of the http.Transport being edited. In the case of this example, the same exact change is being made, so maybe interference isn't much of a concern. However, regardless, if these processes are happening concurrently, will one process updating the global client's transport interfere with the transport that a different process may be using?

My ultimate use case is that I would like to have a global client and be able to specify a custom DialTLSContext but only for certain requests. Requests that I don't want using the DialTLSContext may be running concurrently as well. I'm worried that if I edit the http.Transport of the client of one request that it may interfere and cause another request to also use DialTLSContext even though I don't want it to.

答案1

得分: 4

如果您在多个goroutine之间共享相同的客户端实例,并且如果您从其中一个goroutine修改该客户端,则行为是未定义的,因为这是数据竞争。

如果您想要为一些goroutine修改客户端,没有必要使用单个客户端,您可以为每个goroutine创建一个新的客户端。

如果您想要在主函数中配置一个客户端,并将其作为所有goroutine的模板使用,那么请通过值传递客户端,而不是*client,这样每个goroutine都会传递一个该模板的副本,并且每个goroutine都将在自己的副本上工作,共享相同的Transport。如果您将Transport设置为其他内容,那么由于Client是一个副本,仍然是安全的。

然而,如果您修改Transport实例(即RoundTripper),那么又会出现竞争条件。不要这样做。

英文:

If you share the same client instance among multiple goroutines and if you modify that client from one of them, the behavior is undefined because it is a data race.

If you want to modify the client for some of the goroutines, there's no need to use a single client, and you can create a new client for every goroutine.

If you want to configure one client in main, and use that as a template for all goroutines, pass the client by value, not *client, so a copy of that template is passed to each goroutine, and each goroutine would work on its own copy, sharing the common Transport underneath. If you set the Transport to something else, then since the Client is a copy, it is still safe.

If you however modify something in the Transport instance (which is a RoundTripper), that is again a race condition. Don't do that.

答案2

得分: 1

根据文档(https://golang.org/src/net/http/client.go),Http客户端是线程安全的:

客户端可以被多个goroutine并发使用。

英文:

Http clients are thread safe according to the docs (https://golang.org/src/net/http/client.go):

Clients are safe for concurrent use by multiple goroutines.

huangapple
  • 本文由 发表于 2021年8月28日 13:06:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/68961501.html
匿名

发表评论

匿名网友

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

确定