curl / Mailing Lists / curl-library / Single Mail


Re: persistent connections and dns changes

From: Daniel Stenberg <>
Date: Thu, 8 Jun 2017 10:34:30 +0200 (CEST)

On Wed, 7 Jun 2017, Justin Karneges wrote:

> It seems libcurl will reuse a persistent connection to a domain even if the
> IP address of that domain changes (and the DNS record TTL has expired).

And not only by libcurl I'm sure. TTL data is not readily available in
standard POSIX resolver APIs and name resolves can be done using non-DNS.

> This means a host could be moved, but requests may keep going over an old
> connection, possibly forever.

One question then is who's right here and for how long. libcurl resolves a
name to an IP, sets up a connection and starts performing a transfer. At some
point after that initial resolve, the DNS is updated but libcurl doesn't know.
It keeps using the connection it has setup. In an ideal case, and if the
application allows it, it will reuse that connection for any number of
transfers to that same host name.

When libcurl already has a live connection to a host name in its pool, it
skips the name resolve and instead goes directly to reuse.

For HTTP/2 connections, a server is expected to respond with a 421 when this
situation occurs. (Not that libcurl handles that reponse code in any
particular way, but it probably should.)

It should be noted that the fact that a name doesn't resolve to an IP anymore
is not actually a signal that the old connections aren't valid anymore. There
are big sites "out there" that return a set of IPs to each name resolve, and
it will rotate which set it returns over time for load balancing purposes. But
when it returns a new set, the old set still works fine...

> This is mainly a problem if the server at the original IP address isn't shut
> down. Now you might think if a domain is moved then the original server will
> eventually be decommissioned, but as many domains are virtual hosted by
> stable providers this is not always the case. Removing a virtual host
> doesn't necessarily mean clients will be disconnected, especially if there
> are proxy or load balancing layers.

In many cases, if the connection isn't closed, the server can in fact still
serve the contents for the server it used to serve contents for - basically
because it is a race condition that the server really can't be totally sure is
acknowledged and respected by the clients. But sure, there's not a guarantee
so of course there will be servers that go away faster.

> Any suggestions on how to deal with this problem? It doesn't look like the
> API has a way to destroy existing connections when the multi interface is
> used (other than tearing down the entire multi instance, which I suppose I
> could do as a last resort).

If there was an API to tear down a single connection (which has been suggested
before and I would agree to), how would your application know when to call
that for this situation? It seems it would need some other means to figure
that out...

A more "brutal" way would be to have a mode where libcurl would always resolve
names even if it has a live connection in its pool, and instead basically do
connection re-use based on IP address. This will of course slow down repeated
requests to the same host name when the DNS cache entry is flushed.

Possibly a middle way is to introduce a new option that sets a maximum
life-time for a connection to be considered for reuse - as a way to reduce
this impact of this effect. So that if if the connection has been alive for
more than N seconds, it will instead be marked for close and a new one will be
forced to get opened and used for subsequent transfers with that host. Not
sure this actually helps much though.

Actually trying to use the TTL info from DNS would be an option as well, but
that's a rather complicated route as that info is hard to come by in a neat
fashion. Could of course still be done, and maybe relying on for example
c-ares for this functionality could be acceptable.


Received on 2017-06-08