rust-http2 icon indicating copy to clipboard operation
rust-http2 copied to clipboard

Connect to multiple addresses

Open stepancheg opened this issue 8 years ago • 7 comments

Currently Client connects to single address, first address name resolved to.

Instead, client should attempt to connect to several addresses: both IPv4 and IPv6, and to multiple addresses resolved by DNS.

stepancheg avatar May 17 '17 04:05 stepancheg

As of today's HEAD, it seems to panic instead, which is much worse:

% cargo run --example client https://fau.xxx/
    Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target/debug/examples/client 'https://fau.xxx/'`
thread 'main' panicked at 'client: Other("addr is resolved to more than one addr")', /checkout/src/libcore/result.rs:860:4
note: Run with `RUST_BACKTRACE=1` for a backtrace.

Seems to have been intentionally broken here: https://github.com/stepancheg/rust-http2/commit/b7e1e4ad77aec26972df0e72f9ea6f4f43f12b29#diff-31bbf71c54bca98a0ae3d40a327af940L70

FauxFaux avatar Sep 13 '17 17:09 FauxFaux

@FauxFaux I believe, it does not panic, it returns Err.

stepancheg avatar Sep 30 '17 20:09 stepancheg

What would be the best way to solve this problem? It seems like the simplest solution would be to choose a random address from the list. Could it also be added as an option to have it just choose the first address that it resolves to?

Currently this is a blocking issue for one of my projects, and I would be interested in contributing a solution.

sphw avatar Jun 09 '18 00:06 sphw

First, as a workaround, you can resolve addr yourself, and call set_addr with the resolved address (IP address instead of hostname).

About proper solution.

As I said, "client should attempt to connect to several addresses".

ClientBuilder.addr field should be changed to Vec<AnySocketAddr>, and this line in client_conn.rs

        let connect = addr.connect(&lh).map_err(Into::into);

should be changed to connect concurrently to multiple addresses instead of one.

Alternatively, a single-connection client (ClientConn) can be exposed as public API so a user could connect to proper address themselves and create a client with an already configured socket.

stepancheg avatar Jun 09 '18 01:06 stepancheg

My worry with that workaround is that I need the Authority header to be set properly. If I manually resolve it will just be set to the ip right?

Is it generally the correct behavior to connect to all of the IPs resolved by the DNS query? RFC8305 seems to indicate that some sort of sorting algorithm should be used then they should connected to in order.

I thought (and might be wrong) that when a DNS record resolved to multiple IPs it was to provide round robin load balancing and graceful failover, wouldn't simultaneously connecting break that down? Or would the goal be to race the connection futures and pick whichever resolves first?

sphw avatar Jun 09 '18 01:06 sphw

My worry with that workaround is that I need the Authority header to be set properly. If I manually resolve it will just be set to the ip right?

Authority is passed explicitly to each client call, e. g.

impl Client { ... 
    pub fn start_get(
        &self,
        path: &str,
        authority: &str)
            -> Response { ... }
}

Is it generally the correct behavior to connect to all of the IPs resolved by the DNS query? RFC8305 seems to indicate that some sort of sorting algorithm should be used then they should connected to in order.

Yep, using the algorithm like that or having a configuration option specifying connect strategy should be the right thing, but for the starters connecting to multiple addresses concurrently is acceptable I think.

I thought (and might be wrong) that when a DNS record resolved to multiple IPs it was to provide round robin load balancing and graceful failover, wouldn't simultaneously connecting break that down? Or would the goal be to race the connection futures and pick whichever resolves first?

I think that multiple IP addresses could be used for failover. So as before I think the proper strategy is to connect to the first address, and after a failure or after small timeout connect to second address etc.

But I'm not an expert, I can be wrong.

stepancheg avatar Jun 09 '18 01:06 stepancheg

Any update on this? Not being able to connect to hosts with multiple addresses (without manually resolving first) is a pain for many services.

qwandor avatar Oct 26 '18 21:10 qwandor