英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论