New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix network binding for ipv4/ipv6 #12942
Conversation
So, an interesting byproduct of this is that if I have an ES node bind to the public interface with I'm not sure if this is desired or not, I guess I would expect the |
Also, this is an OSX-only issue, Linux doesn't have this loopback <-> non-loopback communication weirdness. |
That is not related to this change! That is #12914 and I deferred it because its Mac OS X specific, and because its not related to these changes. |
Okay, I totally agree about the deferring it. Just wanted to make sure it was something we are aware of (which of course there is the other issue open for it). |
bindHost = settings.get(GLOBAL_NETWORK_BINDHOST_SETTING, settings.get(GLOBAL_NETWORK_HOST_SETTING)); | ||
} | ||
if (bindHost == null) { | ||
bindHost = defaultValue2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you prefer the double-if? If not I guess you could do:
if (bindHost == null) {
bindHost = settings.get(GLOBAL_NETWORK_BINDHOST_SETTING, settings.get(GLOBAL_NETWORK_HOST_SETTING, defaultValue2));
}
return resolveInetAddress(bindHost);
Instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have changes coming in a commit. Basically it was too hard for me to see the various fallbacks for the default case (null).
Left a few comments but generally LGTM. I tested this locally on OSX and Linux. Would be great to have someone manually test on Windows as well just for a sanity check. |
@@ -50,16 +50,16 @@ h3. Indexing | |||
Let's try and index some twitter like information. First, let's create a twitter user, and add some tweets (the @twitter@ index will be created automatically): | |||
|
|||
<pre> | |||
curl -XPUT 'http://127.0.0.1:9200/twitter/user/kimchy' -d '{ "name" : "Shay Banon" }' | |||
curl -XPUT 'http://localhost:9200/twitter/user/kimchy' -d '{ "name" : "Shay Banon" }' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
who is this shay banon
guy after all?
|
||
InetSocketAddress boundAddress = (InetSocketAddress) serverChannels.get(0).getLocalAddress(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I first looked at this I wondered if this is prone to concurrent modification exception? I wondered if we should make the serverChannels
final and use a CopyOnWriteArrayList
instead. Reading without sync would be safe. But then looking at the entire file I think we should just make the list final and clear it before we close each channel? the volatile confuses me and I think it's not needd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the concurrency in these methods is super confusing. Its doing really slow stuff like binding to ports, which should not happen all the time. I am happy to fix the concurrency, it will be to make everything synchronized: this is all nuts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree - we can do this in a follow up!
Left mostly minor comments! This looks great to me! I will run tests with node.mode=network quickly as well on that. |
@@ -146,7 +146,7 @@ | |||
// node id to actual channel | |||
protected final ConcurrentMap<DiscoveryNode, NodeChannels> connectedNodes = newConcurrentMap(); | |||
protected final Map<String, ServerBootstrap> serverBootstraps = newConcurrentMap(); | |||
protected final Map<String, Channel> serverChannels = newConcurrentMap(); | |||
protected final Map<String, List<Channel>> serverChannels = newConcurrentMap(); | |||
protected final Map<String, BoundTransportAddress> profileBoundAddresses = newConcurrentMap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this must be a ConcurrentMap you use putIfAbsent
I ran tests with thanks rob! |
In elastic#12942, the NettyTransport and NettyHttpServerTransport were updated to allow for binding to multiple addresses. However, the BoundTransportAddress holder only exposed the first address that the transport was bound to and this object is used to populate the values returned to the user via our APIs. This change exposes all of the bound addresses in the BoundTransportAddress holder, which allows for an accurate representation of all interfaces that elasticsearch is bound to and listening on.
In #12942, the NettyTransport and NettyHttpServerTransport were updated to allow for binding to multiple addresses. However, the BoundTransportAddress holder only exposed the first address that the transport was bound to and this object is used to populate the values returned to the user via our APIs. This change exposes all of the bound addresses in the BoundTransportAddress holder, which allows for an accurate representation of all interfaces that elasticsearch is bound to and listening on.
In #12942, the NettyTransport and NettyHttpServerTransport were updated to allow for binding to multiple addresses. However, the BoundTransportAddress holder only exposed the first address that the transport was bound to and this object is used to populate the values returned to the user via our APIs. This change exposes all of the bound addresses in the BoundTransportAddress holder, which allows for an accurate representation of all interfaces that elasticsearch is bound to and listening on.
Elasticsearch doesn't work well today with modern machines that might support both ipv4 and ipv6. The worst problem here that
curl http://localhost...
does not work e.g. on mac (#12906), because we aren't bound to any v6 address.Equally bad, we only bind to loopback by default for 2.0, so if you want to connect to the network "for real" you might provide an interface name, but that always tends to do the wrong thing too (#12915), e.g. pick link local or some other useless address.
This is a compromise fix that tries to keep things simple:
The default for which address to publish when bound to multiple addresses is pretty simple, we prefer ipv4 by default (java.net.preferIPv4Stack) and I think we should until things like multicast are fixed to work correct over ipv6. Otherwise we prefer "real addresses" > site local > link local and so on.
Some things are still a bit messy, because real cleanups need to not be right before a beta release.
Closes #12906
Closes #12915