Skip to content
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

RoundRobinLoadBalancer should not sort the addresses #1051

Merged
merged 2 commits into from May 13, 2020

Conversation

NiteshKant
Copy link
Collaborator

Motivation

For quicker lookups on receiving Service discovery events, RoundRobinLoadBalancer keeps a sorted list of addresses. This results in the same order of hosts for all client instances hence potentially creating hot spots. As, the sorting is not required functionally, we should avoid doing that.

Modification

Use unsorted address list and let service discoverer maintain order of addresses.

Result

RoundRobinLoadBalancer does not store sorted addresses.

__Motivation__

For quicker lookups on receiving Service discovery events,  `RoundRobinLoadBalancer` keeps a sorted list of addresses. This results in the same order of hosts for all client instances hence potentially creating hot spots. As, the sorting is not required functionally, we should avoid doing that.

__Modification__

Use unsorted address list and let service discoverer maintain order of addresses.

__Result__

`RoundRobinLoadBalancer` does not store sorted addresses.
Copy link
Member

@idelpivnitskiy idelpivnitskiy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks! One question:

Copy link
Member

@Scottmitch Scottmitch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm with suggestion. I can submit in followup PR for discussion if you prefer.

if (removed != null) {
removed.markInactive();
final List<Host<ResolvedAddress, C>> refreshedAddresses =
new ArrayList<Host<ResolvedAddress, C>>(currentAddresses);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is expected that the ServiceDiscoverer will filter duplicate events, and there is no modification outside of Subscriber#onNext(other than emptying the list). I think we can assume we won't find any duplicates on addition:

This will also avoid ArrayList copy/move of array elements after it has already been copied in the constructor.

                            final ResolvedAddress addr = requireNonNull(event.address());
                            final List<Host<ResolvedAddress, C>> refreshedAddresses;
                            if (event.isAvailable()) {
                                refreshedAddresses = new ArrayList<>(currentAddresses.size() + 1);
                                refreshedAddresses.addAll(currentAddresses);
                                refreshedAddresses.add(new Host<>(addr));
                            } else if (currentAddresses.isEmpty()) {
                                refreshedAddresses = currentAddresses;
                            } else {
                                refreshedAddresses = new ArrayList<>(currentAddresses.size() - 1);
                                for (Host<ResolvedAddress, C> host : (List<Host<ResolvedAddress, C>>) currentAddresses) {
                                    if (host.address.equals(addr)) {
                                        host.markInactive();
                                    } else {
                                        refreshedAddresses.add(host);
                                    }
                                }
                            }
                            return refreshedAddresses;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking about double copying when we add an element. Unfortunately, refreshedAddresses.addAll(currentAddresses) does 2 copies internally. So, it will be the same as using new ArrayList(anotherList) + add with resize.

It is expected that the ServiceDiscoverer will filter duplicate events

DNS SD currently does not filter duplicates. It takes a List from netty's resolver.resolveAll and passes it as-is. I didn't check netty's code but assume it just parses each DnsRecord from the response. If DNS response contains duplicated addresses, we will see them here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can assume we won't find any duplicates on addition

Actually I think we should allow duplicates which enables folks to effectively add weights to certain hosts. I would prefer not to do these two changes (unsorted and allow dups) in the same PR though. So, ya feel free to send a followup

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants