On Fri, Sep 4, 2015 at 2:06 AM, kartik <
ghaya...@gmail.com> wrote:
> Apologies for not explaining the problem in detail. My application is a
> Dynamic Reverse Proxy(lets call it DRP). The clients(lets call them CLIENTS)
> to DRP are servers(not browsers), which send http request with a header
> X-purl which contains the backend URL(e.g:- X-purl: http://<url>) to which
> DRP should forward the request to. Lets call backend servers as BSERVERS.
> DRP provides BSERVER a time of 200 milliseconds to respond to a request that
> DRP forwards it.
>
> When I mentioned that netstat showed 20K connections, most of these
> connections are with the CLIENTS, not with BSERVERS.
>
> The application memory keeps increasing(over a couple of weeks). A lot of
> goroutines ~20K are in IO wait state in the same call trace. Call trace is
> mentioned above. Even when I decrease the traffic on a server, the
> goroutines are not coming down.
>
> Is there a real leak of connections or goroutines which are not being
> garbage collected? Is the IO wait time cumulative?
> Are there 20K goroutines because DRP has 20K keep-alive connections with
> CLIENTS? Please note the CLIENTS also have timeout at their end(say 150ms)
> and if DRP doesn't respond within that time, CLIENT closes the connection.
If you have 20k idle connections with clients, you're going to have
20k goroutines in IO wait.
It sounds like the clients only close their connections if the request
takes too long, otherwise they maintain a keepalive connection to the
server. If there's too many client connections for your server, you
need to prune them yourself, or somehow have the clients use fewer
connections.
>>
>> I don't understand why you have multiple ReverseProxies, each with
>> their own transport. Each one has to maintain it's own idle connection
>> pool, and and will multiply the number of connections that you keep
>> open.
>>
>> A lot of your code seems to be around synchronizing multiple proxy
>> structs. It would be a lot simpler if you just use a single instance,
>> and it would make the use if idle connections a lot more efficient.
>
>
> Thanks for your patience of going through my code. The reason I am using
> multipe reverse-proxies(per URL) is because I observed heavy lock contention
> on the transport, i.e the lock which is taken for "putIdleConn" and
> "getIdleConn"(transport.go)
This is a known issue when using http.Transport under high load.
Multiple transports can help, but you don't need to have all the
orchestration of loaning them out and returning them to the pool for
each request, or having to manage pools of channels (which is probably
more overhead than allocating channels when you need them). The proxy
and Transports are safe to use concurrently, just pick one for each
request.
>> All of your idle connections need to be in IO wait in order to receive
>> data. I'd expect it to be very high maintaining lost of open
>> connections.
>
> So are you saying that IO wait is cumulative?
>
I'm not sure what you mean since by definition it has to be a sum of
the time spent in IO wait, but it doesn't matter if you don't have
anything to compare to.