-
Notifications
You must be signed in to change notification settings - Fork 986
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
Add support for ReadFrom.subnet and ReadFrom.regex #1570
Conversation
Codecov Report
@@ Coverage Diff @@
## main #1570 +/- ##
============================================
+ Coverage 78.64% 78.88% +0.23%
- Complexity 6341 6407 +66
============================================
Files 477 479 +2
Lines 21335 21539 +204
Branches 2334 2360 +26
============================================
+ Hits 16779 16990 +211
+ Misses 3479 3474 -5
+ Partials 1077 1075 -2 Continue to review full report at Codecov.
|
d63d135
to
60c2f9b
Compare
60c2f9b
to
8bd8d01
Compare
Lettuce now supports ReadFrom.subnet which is an option of reading from any node in the given subnets.
8bd8d01
to
1d1827a
Compare
public List<RedisNodeDescription> select(Nodes nodes) { | ||
List<RedisNodeDescription> result = new ArrayList<>(nodes.getNodes().size()); | ||
for (RedisNodeDescription node : nodes) { | ||
if (isInSubnet(node.getUri())) { |
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.
[Question] As far as I tried with debugger, node.getUri()
always returns IP address rather than hostname like not redis://foobar.com
but redis://192.168.0.1
.
Is there any case of returning hostname here?
My concern is, if there is any case that node.getUri()
returns initial endpoint, this code may not work as we intend because the initial endpoint may be associated with multiple IP addresses.
For AWS specific, they issue configuration endpoint (e.g., foobar.cache.amazonaws.com
) and we use it for initial endpoint. The endpoint is associated with (almost all) cluster nodes' ip address.
$ dig foobar.cache.amazonaws.com +short
192.168.0.1
192.168.0.2
192.168.0.3
So there is any case that node.getUri()
returns initial endpoint, its IP address is any one of cluster nodes', thus this class does not work as we intend.
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.
The host part of RedisURI
depends on from where the URI was supplied. In a Redis Cluster or Redis Sentinel arrangement, the topology source is always Redis itself which reports IP addresses only.
When using Master/Replica with provided URL's, then you get hold of the hostname.
ReadFrom
gets always called with the target node. Does that help?
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.
Thank you for the information and review. I will investigate the behaviour in detail!
return false; | ||
} | ||
|
||
InetSocketAddress address = SocketUtils.socketAddress(redisURI.getHost(), redisURI.getPort()); |
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 line can lead to a DNS lookup (blocking call). Would createUnresolved
work as well?
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.
IpSubnetFilterRule
uses InetSocketAddress#getAddress
, so createUnresolved
would not work because getAddress
returns always null
for unresolved socket addresses.
InetAddress#getByName
does not make DNS resolution if IP address is given (see javadoc), so I use it and I add hostname validation to avoid unintended DNS lookup.
7b114cd
to
085f8dc
Compare
I feel DNS resolving in ReadFrom.subnet is bad idea because:
At first I came up with holding remote IP address when connection established in So simply I want to propose as follows:
|
Looking at the rule implementations in netty, I wonder whether we could basically implement IPv4 and IPv6 rules on our own by parsing the IP address into We could approach the case where hostnames are used by a |
You mean, we maintain a subnet as |
Sorry, I think my comment was a bit confusing. I actually made two proposals:
|
Got it, thanks. Those proposals sound reasonable to me. |
29ec55b
to
169bec8
Compare
169bec8
to
c298d90
Compare
/** | ||
* Read from any node that has {@link RedisURI} matching with the given pattern. | ||
* | ||
* @param pattern regex pattern, e.g., {@code Pattern.compile(".*region-1.*")}. Must not be {@code null}. | ||
* @return an instance of {@link ReadFromImpl.ReadFromRegex}. | ||
* @since x.x.x | ||
*/ | ||
public static ReadFrom regex(Pattern pattern) { | ||
return new ReadFromImpl.ReadFromRegex(pattern); | ||
} |
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.
For hostname-based matching, I feel regex-based is more in demand than set-based because it is more simple and extensible, but what do you think? If not I will replace to set-based as originally proposed.
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 think that's fine, too.
} | ||
} | ||
|
||
static class Ipv4SubnetRule implements SubnetRule { |
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.
To avoid license issue (though netty is Apache license), IPv4/IPv6 rules are re-implemented by myself, so some detailed implementations are different from Netty's one.
Lettuce now supports ReadFrom.subnet which is an option of reading from any node in the given subnets. Original pull request: #1570.
Thank you for your contribution. That's merged and polished now. |
Lettuce now supports ReadFrom.subnet which is an option of reading from any node in the given subnets.
Closes: #1569
Make sure that: