1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.resolver;
17
18 import io.netty5.util.concurrent.EventExecutor;
19 import io.netty5.util.concurrent.Future;
20 import io.netty5.util.concurrent.Promise;
21
22 import java.net.InetAddress;
23 import java.net.InetSocketAddress;
24 import java.net.UnknownHostException;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.concurrent.ThreadLocalRandom;
29
30
31
32
33
34
35
36 public class RoundRobinInetAddressResolver extends InetNameResolver {
37 private final NameResolver<InetAddress> nameResolver;
38
39
40
41
42
43
44 public RoundRobinInetAddressResolver(EventExecutor executor, NameResolver<InetAddress> nameResolver) {
45 super(executor);
46 this.nameResolver = nameResolver;
47 }
48
49 @Override
50 protected void doResolve(final String inetHost, final Promise<InetAddress> promise) throws Exception {
51
52
53
54 nameResolver.resolveAll(inetHost).addListener(future -> {
55 if (future.isSuccess()) {
56 List<InetAddress> inetAddresses = future.getNow();
57 int numAddresses = inetAddresses.size();
58 if (numAddresses > 0) {
59
60
61 promise.setSuccess(inetAddresses.get(randomIndex(numAddresses)));
62 } else {
63 promise.setFailure(new UnknownHostException(inetHost));
64 }
65 } else {
66 promise.setFailure(future.cause());
67 }
68 });
69 }
70
71 @Override
72 protected void doResolveAll(String inetHost, final Promise<List<InetAddress>> promise) throws Exception {
73 nameResolver.resolveAll(inetHost).addListener(future -> {
74 if (future.isSuccess()) {
75 List<InetAddress> inetAddresses = future.getNow();
76 if (!inetAddresses.isEmpty()) {
77
78 List<InetAddress> result = new ArrayList<>(inetAddresses);
79
80 Collections.rotate(result, randomIndex(inetAddresses.size()));
81 promise.setSuccess(result);
82 } else {
83 promise.setSuccess(inetAddresses);
84 }
85 } else {
86 promise.setFailure(future.cause());
87 }
88 });
89 }
90
91 private static int randomIndex(int numAddresses) {
92 return numAddresses == 1 ? 0 : ThreadLocalRandom.current().nextInt(numAddresses);
93 }
94
95 @Override
96 public void close() {
97 nameResolver.close();
98 }
99 }