From 310d6fe2174636531afa65f70bedf5ade25e9969 Mon Sep 17 00:00:00 2001 From: Redkale Date: Thu, 5 Jan 2023 22:29:45 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9EWeightAddress?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/redkale/net/client/ClientAddress.java | 55 ++++++++++++++++- .../org/redkale/net/client/WeightAddress.java | 59 +++++++++++++++++++ 2 files changed, 111 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/redkale/net/client/WeightAddress.java diff --git a/src/main/java/org/redkale/net/client/ClientAddress.java b/src/main/java/org/redkale/net/client/ClientAddress.java index 5bd41f75e..0cb7f46b5 100644 --- a/src/main/java/org/redkale/net/client/ClientAddress.java +++ b/src/main/java/org/redkale/net/client/ClientAddress.java @@ -3,7 +3,8 @@ package org.redkale.net.client; import java.net.SocketAddress; -import java.util.concurrent.CompletableFuture; +import java.util.*; +import java.util.concurrent.*; import org.redkale.convert.json.JsonConvert; import org.redkale.net.*; @@ -18,7 +19,11 @@ import org.redkale.net.*; */ public class ClientAddress implements java.io.Serializable { - protected SocketAddress address; + private SocketAddress address; + + private List weights; + + private SocketAddress[] addresses; public ClientAddress() { } @@ -27,8 +32,52 @@ public class ClientAddress implements java.io.Serializable { this.address = address; } + public ClientAddress(List addrs) { + this.weights = new ArrayList<>(addrs); + } + + public ClientAddress addWeightAddress(WeightAddress... addrs) { + if (this.weights == null) { + this.weights = new ArrayList<>(); + } + for (WeightAddress addr : addrs) { + this.weights.add(addr); + } + return this; + } + + public void updateWeightAddress(List addrs) { + this.weights = new ArrayList<>(addrs); + this.addresses = null; + } + public CompletableFuture createClient(final boolean tcp, final AsyncGroup group, int readTimeoutSeconds, int writeTimeoutSeconds) { - return group.createClient(tcp, address, readTimeoutSeconds, writeTimeoutSeconds); + SocketAddress addr = address; + if (addr == null) { + if (this.addresses == null) { + synchronized (this) { + if (this.addresses == null) { + int size = 0; + List ws = this.weights; + for (WeightAddress w : ws) { + size += w.getWeight(); + } + SocketAddress[] newAddrs = new SocketAddress[size]; + int index = -1; + for (int i = 0; i < ws.size(); i++) { + WeightAddress w = ws.get(i); + for (int j = 0; j < w.getWeight(); j++) { + newAddrs[++index] = w.getAddress(); + } + } + this.addresses = newAddrs; + } + } + } + SocketAddress[] addrs = addresses; + addr = addrs[ThreadLocalRandom.current().nextInt(addrs.length)]; + } + return group.createClient(tcp, addr, readTimeoutSeconds, writeTimeoutSeconds); } public SocketAddress getAddress() { diff --git a/src/main/java/org/redkale/net/client/WeightAddress.java b/src/main/java/org/redkale/net/client/WeightAddress.java new file mode 100644 index 000000000..aef531418 --- /dev/null +++ b/src/main/java/org/redkale/net/client/WeightAddress.java @@ -0,0 +1,59 @@ +/* + * + */ +package org.redkale.net.client; + +import java.net.SocketAddress; +import java.util.Objects; +import org.redkale.annotation.ConstructorParameters; +import org.redkale.convert.ConvertColumn; +import org.redkale.convert.json.JsonConvert; + +/** + * 带权重的地址 + * + *

+ * 详情见: https://redkale.org + * + * @author zhangjx + * + * @since 2.8.0 + */ +public class WeightAddress implements Comparable, java.io.Serializable { + + @ConvertColumn(index = 1) + private final SocketAddress address; + + //权重值,取值范围[0-100] + @ConvertColumn(index = 2) + private final int weight; + + @ConstructorParameters({"address", "weight"}) + public WeightAddress(SocketAddress address, int weight) { + Objects.requireNonNull(address); + if (weight < 0 || weight > 100) { + throw new IndexOutOfBoundsException("weight must be [0 - 100]"); + } + this.address = address; + this.weight = weight; + } + + @Override + public int compareTo(WeightAddress o) { + return this.weight - (o == null ? 0 : o.weight); + } + + public SocketAddress getAddress() { + return address; + } + + public int getWeight() { + return this.weight; + } + + @Override + public String toString() { + return JsonConvert.root().convertTo(this); + } + +}