I have an usecase where there are two services S1 and S2 and 1000 different Hosts. S1 and S2 are running in same machine and can talk to each other over local host and port. It works like this:
- S1 makes call to S2 over localhost to get data from host. The connection between S1 and S2 is TCP on top of UDS.
- S2 makes call to Host, collect data and send back to S1
So, S1 to S2 call is on localhost but S2 to Hosts calls are over network.
Now, I need to maintain http connection pool in such a way that for each Host there is a separate connection spawned between S1 and S2 i.e. same connection should not be used for all the Hosts.
As S2 is residing on localhost to S1 so for every request if connection is free, the same connection is being used. The default connection pooling logic of net/http transport works on host:port which will always be same between S1 and S2. So, I want the connection pooling based on target URL path where I specify the id of each Host in the path e.g. http://localhost/api/v1/host-1
To achieve this, I set the Proxy on net/http Transport a custom function which returns the request URL. By this, the transport connection pool uses complete URL to pool connections.
So, with this I am setting target URL as the http transport Proxy. Can this cause any problem? Or is it okay to use Proxy in such manner. What is other alternative approach to achieve the requirement?
I thought of using separate http clients for each Host id but then it might result in memory and performance impacts.
Sample code:
func getHttpClient() *http.Client {
transport := &http.Transport{
DialContext: func(ctx context.Context, network string, addr string) (net.Conn, error) {
dialer := net.Dialer{Timeout: 1 * time.Second}
return dialer.DialContext(ctx, "unix", "/var/run/envoy/svc")
},
ResponseHeaderTimeout: 20 * time.Second,
}
transport.Proxy = proxyFromRequest
transport.MaxIdleConns = 1000
transport.MaxIdleConnsPerHost = 1000
transport.MaxConnsPerHost = 1000
transport.IdleConnTimeout = 10 * time.Minute
client := http.Client{
Transport: transport,
}
client.Timeout = 5 * time.Minute
return &client
}
func proxyFromRequest(req *http.Request) (*url.URL, error) {
return req.URL, nil
}