This is an automated email from the ASF dual-hosted git repository.
liuhongyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new 0f2f7acce2 modify loadbalancer (#6251)
0f2f7acce2 is described below
commit 0f2f7acce28824e56472607be3804407c636b357
Author: xiaoyu <[email protected]>
AuthorDate: Mon Dec 8 09:40:18 2025 +0800
modify loadbalancer (#6251)
* modify loadbalancer
* modify loadbalancer
* modify loadbalancer
* modify loadbalancer
* modify loadbalancer
* modify loadbalancer
---
.../shenyu/admin/shiro/config/ShiroRealm.java | 2 +
.../loadbalancer/cache/UpstreamCacheManager.java | 4 +-
.../loadbalancer/entity/LoadBalanceData.java | 204 +++++++++++++++++++++
.../shenyu/loadbalancer/entity/Upstream.java | 130 ++++++++-----
.../loadbalancer/factory/LoadBalancerFactory.java | 10 +-
.../loadbalancer/spi/AbstractLoadBalancer.java | 12 +-
.../shenyu/loadbalancer/spi/HashLoadBalancer.java | 19 +-
.../loadbalancer/spi/LeastActiveLoadBalance.java | 11 +-
.../shenyu/loadbalancer/spi/LoadBalancer.java | 5 +-
.../shenyu/loadbalancer/spi/P2cLoadBalancer.java | 12 +-
.../loadbalancer/spi/RandomLoadBalancer.java | 8 +-
.../loadbalancer/spi/RoundRobinLoadBalancer.java | 3 +-
.../spi/ShortestResponseLoadBalancer.java | 3 +-
.../shenyu/loadbalancer/entity/UpstreamTest.java | 6 +-
.../factory/LoadBalancerFactoryTest.java | 14 +-
.../loadbalancer/spi/HashLoadBalanceTest.java | 87 ++-------
.../loadbalancer/spi/HashLoadBalancerTest.java | 3 +-
.../spi/LeastActiveLoadBalanceTest.java | 10 +-
.../loadbalancer/spi/P2cLoadBalancerTest.java | 9 +-
.../loadbalancer/spi/RandomLoadBalancerTest.java | 11 +-
.../spi/RoundRobinLoadBalanceTest.java | 13 +-
.../spi/ShortestResponseLoadBalancerTest.java | 5 +-
shenyu-plugin/shenyu-plugin-base/pom.xml | 6 +
.../plugin/base/utils/LoadbalancerUtils.java | 100 ++++++++++
.../plugin/httpclient/DefaultRetryStrategy.java | 26 +--
.../apache/shenyu/plugin/divide/DividePlugin.java | 15 +-
.../dubbo/proxy/ApacheDubboGrayLoadBalance.java | 4 +-
.../dubbo/proxy/ApacheDubboProxyService.java | 18 +-
.../grpc/loadbalance/picker/ShenyuPicker.java | 10 +-
.../shenyu/plugin/websocket/WebSocketPlugin.java | 5 +-
.../DefaultConnectionConfigProvider.java | 5 +-
.../sdk/core/client/AbstractShenyuSdkClient.java | 6 +-
.../shenyu/sdk/feign/ShenyuDiscoveryClient.java | 16 +-
33 files changed, 545 insertions(+), 247 deletions(-)
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/shiro/config/ShiroRealm.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/shiro/config/ShiroRealm.java
index 15431cf693..2cd6ac1428 100644
---
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/shiro/config/ShiroRealm.java
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/shiro/config/ShiroRealm.java
@@ -29,6 +29,8 @@ import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.BearerToken;
+
+
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.Permission;
diff --git
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/cache/UpstreamCacheManager.java
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/cache/UpstreamCacheManager.java
index ecb86c019c..30a76ed410 100644
---
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/cache/UpstreamCacheManager.java
+++
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/cache/UpstreamCacheManager.java
@@ -26,10 +26,12 @@ import org.apache.shenyu.common.utils.MapUtils;
import org.apache.shenyu.common.utils.Singleton;
import org.apache.shenyu.loadbalancer.entity.Upstream;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
+import java.util.Set;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
@@ -155,7 +157,7 @@ public final class UpstreamCacheManager {
}
// Use a Set for O(1) lookups instead of nested loops
- java.util.Set<Upstream> existUpstreamSet = new
java.util.HashSet<>(existUpstreamList);
+ Set<Upstream> existUpstreamSet = new HashSet<>(existUpstreamList);
offlineUpstreamList.forEach(offlineUp -> {
if (existUpstreamSet.contains(offlineUp)) {
task.triggerRemoveOne(selectorId, offlineUp);
diff --git
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/entity/LoadBalanceData.java
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/entity/LoadBalanceData.java
new file mode 100644
index 0000000000..b06ba56813
--- /dev/null
+++
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/entity/LoadBalanceData.java
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.loadbalancer.entity;
+
+import java.net.URI;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The type Load balance data.
+ */
+public class LoadBalanceData {
+
+ private String httpMethod = "GET";
+
+ private String ip = "127.0.0.1";
+
+ private URI url;
+
+ private Map<String, Collection<String>> headers = new HashMap<>();
+
+ private Map<String, String> cookies = new HashMap<>();
+
+ private Map<String, Object> attributes = new HashMap<>();
+
+ private Map<String, Collection<String>> queryParams = new HashMap<>();
+
+ /**
+ * Instantiates a new Load balance data.
+ */
+ public LoadBalanceData() {
+ }
+
+ /**
+ * Instantiates a new Load balance data.
+ *
+ * @param httpMethod the http method
+ * @param ip the ip
+ * @param url the url
+ * @param headers the headers
+ * @param cookies the cookies
+ * @param attributes the attributes
+ * @param queryParams the query params
+ */
+ public LoadBalanceData(final String httpMethod,
+ final String ip,
+ final URI url,
+ final Map<String, Collection<String>> headers,
+ final Map<String, String> cookies,
+ final Map<String, Object> attributes,
+ final Map<String, Collection<String>> queryParams) {
+ this.httpMethod = httpMethod;
+ this.ip = ip;
+ this.url = url;
+ this.headers = headers;
+ this.cookies = cookies;
+ this.attributes = attributes;
+ this.queryParams = queryParams;
+ }
+
+
+ /**
+ * Gets http method.
+ *
+ * @return the http method
+ */
+ public String getHttpMethod() {
+ return httpMethod;
+ }
+
+ /**
+ * Gets ip.
+ *
+ * @return the ip
+ */
+ public String getIp() {
+ return ip;
+ }
+
+
+ /**
+ * Gets url.
+ *
+ * @return the url
+ */
+ public URI getUrl() {
+ return url;
+ }
+
+ /**
+ * Gets headers.
+ *
+ * @return the headers
+ */
+ public Map<String, Collection<String>> getHeaders() {
+ return headers;
+ }
+
+ /**
+ * Gets cookies.
+ *
+ * @return the cookies
+ */
+ public Map<String, String> getCookies() {
+ return cookies;
+ }
+
+ /**
+ * Gets attributes.
+ *
+ * @return the attributes
+ */
+ public Map<String, Object> getAttributes() {
+ return attributes;
+ }
+
+ /**
+ * Gets query params.
+ *
+ * @return the query params
+ */
+ public Map<String, Collection<String>> getQueryParams() {
+ return queryParams;
+ }
+
+ /**
+ * Sets http method.
+ *
+ * @param httpMethod the http method
+ */
+ public void setHttpMethod(final String httpMethod) {
+ this.httpMethod = httpMethod;
+ }
+
+ /**
+ * Sets query params.
+ *
+ * @param queryParams the query params
+ */
+ public void setQueryParams(final Map<String, Collection<String>>
queryParams) {
+ this.queryParams = queryParams;
+ }
+
+ /**
+ * Sets attributes.
+ *
+ * @param attributes the attributes
+ */
+ public void setAttributes(final Map<String, Object> attributes) {
+ this.attributes = attributes;
+ }
+
+ /**
+ * Sets cookies.
+ *
+ * @param cookies the cookies
+ */
+ public void setCookies(final Map<String, String> cookies) {
+ this.cookies = cookies;
+ }
+
+ /**
+ * Sets headers.
+ *
+ * @param headers the headers
+ */
+ public void setHeaders(final Map<String, Collection<String>> headers) {
+ this.headers = headers;
+ }
+
+ /**
+ * Sets url.
+ *
+ * @param url the url
+ */
+ public void setUrl(final URI url) {
+ this.url = url;
+ }
+
+ /**
+ * Sets ip.
+ *
+ * @param ip the ip
+ */
+ public void setIp(final String ip) {
+ this.ip = ip;
+ }
+}
diff --git
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/entity/Upstream.java
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/entity/Upstream.java
index 05c962bdc0..c815d67e28 100644
---
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/entity/Upstream.java
+++
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/entity/Upstream.java
@@ -19,8 +19,10 @@ package org.apache.shenyu.loadbalancer.entity;
import org.apache.commons.lang3.StringUtils;
+import java.util.Map;
import java.util.Objects;
import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
/**
@@ -102,7 +104,10 @@ public final class Upstream {
* this is gray.
*/
private boolean gray;
-
+
+ private Map<String, String> metadata = new ConcurrentHashMap<>();
+
+
/**
* Total number of requests being processed.
*/
@@ -123,7 +128,7 @@ public final class Upstream {
this.version = builder.version;
this.gray = builder.gray;
}
-
+
/**
* Gets protocol.
*
@@ -132,7 +137,7 @@ public final class Upstream {
public String getProtocol() {
return protocol;
}
-
+
/**
* Is status boolean.
*
@@ -141,7 +146,7 @@ public final class Upstream {
public boolean isStatus() {
return status;
}
-
+
/**
* Sets status.
*
@@ -150,7 +155,7 @@ public final class Upstream {
public void setStatus(final boolean status) {
this.status = status;
}
-
+
/**
* Gets timestamp.
*
@@ -159,7 +164,7 @@ public final class Upstream {
public long getTimestamp() {
return timestamp;
}
-
+
/**
* Gets warmup.
*
@@ -168,7 +173,7 @@ public final class Upstream {
public int getWarmup() {
return warmup;
}
-
+
/**
* Gets url.
*
@@ -177,7 +182,7 @@ public final class Upstream {
public String getUrl() {
return url;
}
-
+
/**
* Sets url.
*
@@ -186,7 +191,7 @@ public final class Upstream {
public void setUrl(final String url) {
this.url = url;
}
-
+
/**
* get weight.
*
@@ -195,7 +200,7 @@ public final class Upstream {
public int getWeight() {
return weight;
}
-
+
/**
* Sets weight.
*
@@ -204,7 +209,7 @@ public final class Upstream {
public void setWeight(final int weight) {
this.weight = weight;
}
-
+
/**
* Is healthy boolean.
*
@@ -213,7 +218,7 @@ public final class Upstream {
public boolean isHealthy() {
return healthy;
}
-
+
/**
* Sets healthy.
*
@@ -222,7 +227,7 @@ public final class Upstream {
public void setHealthy(final boolean healthy) {
this.healthy = healthy;
}
-
+
/**
* Gets last health timestamp.
*
@@ -231,7 +236,7 @@ public final class Upstream {
public long getLastHealthTimestamp() {
return lastHealthTimestamp;
}
-
+
/**
* Sets last health timestamp.
*
@@ -240,7 +245,7 @@ public final class Upstream {
public void setLastHealthTimestamp(final long lastHealthTimestamp) {
this.lastHealthTimestamp = lastHealthTimestamp;
}
-
+
/**
* Gets last unhealthy timestamp.
*
@@ -249,7 +254,7 @@ public final class Upstream {
public long getLastUnhealthyTimestamp() {
return lastUnhealthyTimestamp;
}
-
+
/**
* Sets last unhealthy timestamp.
*
@@ -258,7 +263,7 @@ public final class Upstream {
public void setLastUnhealthyTimestamp(final long lastUnhealthyTimestamp) {
this.lastUnhealthyTimestamp = lastUnhealthyTimestamp;
}
-
+
/**
* Gets group.
*
@@ -267,7 +272,7 @@ public final class Upstream {
public String getGroup() {
return group;
}
-
+
/**
* Sets group.
*
@@ -276,7 +281,7 @@ public final class Upstream {
public void setGroup(final String group) {
this.group = group;
}
-
+
/**
* Gets version.
*
@@ -285,7 +290,7 @@ public final class Upstream {
public String getVersion() {
return version;
}
-
+
/**
* Sets version.
*
@@ -294,7 +299,7 @@ public final class Upstream {
public void setVersion(final String version) {
this.version = version;
}
-
+
/**
* Gets lag.
*
@@ -303,15 +308,16 @@ public final class Upstream {
public long getLag() {
return lag;
}
-
+
/**
* Sets lag.
+ *
* @param lag the lag
*/
public void setLag(final long lag) {
this.lag = lag;
}
-
+
/**
* Gets responseStamp.
*
@@ -320,15 +326,16 @@ public final class Upstream {
public long getResponseStamp() {
return responseStamp;
}
-
+
/**
* Sets responseStamp.
+ *
* @param responseStamp the responseStamp
*/
public void setResponseStamp(final long responseStamp) {
this.responseStamp = responseStamp;
}
-
+
/**
* Gets lastPickedStamp.
*
@@ -337,15 +344,16 @@ public final class Upstream {
public long getLastPicked() {
return lastPicked;
}
-
+
/**
* Sets lastPickedStamp.
+ *
* @param lastPicked the lastPickedStamp
*/
public void setLastPicked(final long lastPicked) {
this.lastPicked = lastPicked;
}
-
+
/**
* Gets inflight.
*
@@ -354,24 +362,25 @@ public final class Upstream {
public AtomicLong getInflight() {
return inflight;
}
-
+
/**
* Sets inflight.
+ *
* @param inflight the inflight
*/
public void setInflight(final AtomicLong inflight) {
this.inflight = inflight;
}
-
+
/**
* gray.
*
- * @return Gray
+ * @return Gray boolean
*/
public boolean isGray() {
return gray;
}
-
+
/**
* set gray.
*
@@ -380,25 +389,46 @@ public final class Upstream {
public void setGray(final boolean gray) {
this.gray = gray;
}
-
+
+ /**
+ * Gets metadata.
+ *
+ * @return the metadata
+ */
+ public Map<String, String> getMetadata() {
+ return metadata;
+ }
+
+ /**
+ * Sets metadata.
+ *
+ * @param metadata the metadata
+ */
+ public void setMetadata(final Map<String, String> metadata) {
+ this.metadata = metadata;
+ }
+
/**
* Gets succeeded.
+ *
* @return the succeeded
*/
public AtomicLong getSucceeded() {
return succeeded;
}
-
+
/**
* Gets succeededElapsed.
+ *
* @return the succeededElapsed
*/
public AtomicLong getSucceededElapsed() {
return succeededElapsed;
}
-
+
/**
* Gets succeededAverageElapsed.
+ *
* @return the succeededAverageElapsed.
*/
public long getSucceededAverageElapsed() {
@@ -408,11 +438,11 @@ public final class Upstream {
}
return getSucceededElapsed().get() / succeeded;
}
-
+
/**
* build request domain.
*
- * @return domain
+ * @return domain string
*/
public String buildDomain() {
String protocol = this.getProtocol();
@@ -426,12 +456,12 @@ public final class Upstream {
* Build request with protocol.
*
* @param protocol protocol
- * @return domain
+ * @return domain string
*/
public String buildDomain(final String protocol) {
return protocol +
Optional.ofNullable(this.getUrl()).map(String::trim).orElse(null);
}
-
+
/**
* class builder.
*
@@ -471,7 +501,7 @@ public final class Upstream {
+ ", version='" + version
+ '}';
}
-
+
/**
* class builder.
*/
@@ -527,7 +557,7 @@ public final class Upstream {
*/
private Builder() {
}
-
+
/**
* build new Object.
*
@@ -536,7 +566,7 @@ public final class Upstream {
public Upstream build() {
return new Upstream(this);
}
-
+
/**
* build protocol.
*
@@ -547,7 +577,7 @@ public final class Upstream {
this.protocol = protocol;
return this;
}
-
+
/**
* build url.
*
@@ -558,7 +588,7 @@ public final class Upstream {
this.url = url;
return this;
}
-
+
/**
* build weight.
*
@@ -569,7 +599,7 @@ public final class Upstream {
this.weight = weight;
return this;
}
-
+
/**
* build status.
*
@@ -580,7 +610,7 @@ public final class Upstream {
this.status = status;
return this;
}
-
+
/**
* build timestamp.
*
@@ -591,7 +621,7 @@ public final class Upstream {
this.timestamp = timestamp;
return this;
}
-
+
/**
* build warmup.
*
@@ -602,7 +632,7 @@ public final class Upstream {
this.warmup = warmup;
return this;
}
-
+
/**
* build group.
*
@@ -613,7 +643,7 @@ public final class Upstream {
this.group = group;
return this;
}
-
+
/**
* build version.
*
@@ -624,8 +654,8 @@ public final class Upstream {
this.version = version;
return this;
}
-
-
+
+
/**
* build gray.
*
diff --git
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/factory/LoadBalancerFactory.java
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/factory/LoadBalancerFactory.java
index bf1acd88c5..291039da43 100644
---
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/factory/LoadBalancerFactory.java
+++
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/factory/LoadBalancerFactory.java
@@ -17,11 +17,13 @@
package org.apache.shenyu.loadbalancer.factory;
-import java.util.List;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
import org.apache.shenyu.loadbalancer.entity.Upstream;
import org.apache.shenyu.loadbalancer.spi.LoadBalancer;
import org.apache.shenyu.spi.ExtensionLoader;
+import java.util.List;
+
/**
* The type Load balance Factory.
*/
@@ -35,11 +37,11 @@ public final class LoadBalancerFactory {
*
* @param upstreamList the upstream list
* @param algorithm the loadBalance algorithm
- * @param ip the ip
+ * @param data the data
* @return the upstream
*/
- public static Upstream selector(final List<Upstream> upstreamList, final
String algorithm, final String ip) {
+ public static Upstream selector(final List<Upstream> upstreamList, final
String algorithm, final LoadBalanceData data) {
LoadBalancer loadBalance =
ExtensionLoader.getExtensionLoader(LoadBalancer.class).getJoin(algorithm);
- return loadBalance.select(upstreamList, ip);
+ return loadBalance.select(upstreamList, data);
}
}
diff --git
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/AbstractLoadBalancer.java
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/AbstractLoadBalancer.java
index 070960ca96..052194a127 100644
---
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/AbstractLoadBalancer.java
+++
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/AbstractLoadBalancer.java
@@ -17,10 +17,12 @@
package org.apache.shenyu.loadbalancer.spi;
-import java.util.List;
import org.apache.commons.collections4.CollectionUtils;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
import org.apache.shenyu.loadbalancer.entity.Upstream;
+import java.util.List;
+
/**
* The type Abstract load balancer.
*/
@@ -30,20 +32,20 @@ public abstract class AbstractLoadBalancer implements
LoadBalancer {
* Do select upstream.
*
* @param upstreamList the upstream list
- * @param ip the ip
+ * @param data the data
* @return the upstream
*/
- protected abstract Upstream doSelect(List<Upstream> upstreamList, String
ip);
+ protected abstract Upstream doSelect(List<Upstream> upstreamList,
LoadBalanceData data);
@Override
- public Upstream select(final List<Upstream> upstreamList, final String ip)
{
+ public Upstream select(final List<Upstream> upstreamList, final
LoadBalanceData data) {
if (CollectionUtils.isEmpty(upstreamList)) {
return null;
}
if (upstreamList.size() == 1) {
return upstreamList.get(0);
}
- return doSelect(upstreamList, ip);
+ return doSelect(upstreamList, data);
}
protected int getWeight(final Upstream upstream) {
diff --git
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/HashLoadBalancer.java
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/HashLoadBalancer.java
index 4fad9f7e18..8de25c0e2f 100644
---
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/HashLoadBalancer.java
+++
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/HashLoadBalancer.java
@@ -17,6 +17,10 @@
package org.apache.shenyu.loadbalancer.spi;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
+import org.apache.shenyu.loadbalancer.entity.Upstream;
+import org.apache.shenyu.spi.Join;
+
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -24,8 +28,6 @@ import java.util.List;
import java.util.SortedMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.stream.IntStream;
-import org.apache.shenyu.loadbalancer.entity.Upstream;
-import org.apache.shenyu.spi.Join;
/**
* hash algorithm impl.
@@ -37,22 +39,15 @@ public class HashLoadBalancer extends AbstractLoadBalancer {
* virtual node used to solve unbalanced load.
*/
private static final int VIRTUAL_NODE_NUM = 5;
-
- /**
- * consistent hash with virtual node to select upstream.
- *
- * @param upstreamList the upstream list
- * @param ip the ip
- * @return selected upstream
- */
+
@Override
- public Upstream doSelect(final List<Upstream> upstreamList, final String
ip) {
+ public Upstream doSelect(final List<Upstream> upstreamList, final
LoadBalanceData data) {
final ConcurrentSkipListMap<Long, Upstream> treeMap = new
ConcurrentSkipListMap<>();
upstreamList.forEach(upstream -> IntStream.range(0,
VIRTUAL_NODE_NUM).forEach(i -> {
long addressHash = hash("SHENYU-" + upstream.getUrl() + "-HASH-" +
i);
treeMap.put(addressHash, upstream);
}));
- long hash = hash(ip);
+ long hash = hash(data.getIp());
SortedMap<Long, Upstream> lastRing = treeMap.tailMap(hash);
if (!lastRing.isEmpty()) {
return lastRing.get(lastRing.firstKey());
diff --git
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/LeastActiveLoadBalance.java
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/LeastActiveLoadBalance.java
index 5d1b016bb4..5d117a1c08 100644
---
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/LeastActiveLoadBalance.java
+++
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/LeastActiveLoadBalance.java
@@ -17,6 +17,10 @@
package org.apache.shenyu.loadbalancer.spi;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
+import org.apache.shenyu.loadbalancer.entity.Upstream;
+import org.apache.shenyu.spi.Join;
+
import java.util.Comparator;
import java.util.List;
import java.util.Map;
@@ -24,9 +28,6 @@ import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
-import org.apache.shenyu.loadbalancer.entity.Upstream;
-import org.apache.shenyu.spi.Join;
-
/**
* least active algorithm impl.
*/
@@ -36,7 +37,7 @@ public class LeastActiveLoadBalance extends
AbstractLoadBalancer {
private final Map<String, Long> countMap = new ConcurrentHashMap<>();
@Override
- protected Upstream doSelect(final List<Upstream> upstreamList, final
String ip) {
+ protected Upstream doSelect(final List<Upstream> upstreamList, final
LoadBalanceData data) {
Map<String, Upstream> domainMap = upstreamList.stream()
.collect(Collectors.toConcurrentMap(Upstream::buildDomain,
upstream -> upstream));
@@ -51,7 +52,7 @@ public class LeastActiveLoadBalance extends
AbstractLoadBalancer {
.map(Map.Entry::getKey)
.orElse(upstreamList.get(0).buildDomain());
- countMap.computeIfPresent(domain, (key, actived) ->
Optional.of(actived).orElse(Long.MIN_VALUE) + 1);
+ countMap.computeIfPresent(domain, (key, activated) ->
Optional.of(activated).orElse(Long.MIN_VALUE) + 1);
return domainMap.get(domain);
}
diff --git
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/LoadBalancer.java
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/LoadBalancer.java
index 4809aa6212..ad0d0de3e2 100644
---
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/LoadBalancer.java
+++
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/LoadBalancer.java
@@ -17,6 +17,7 @@
package org.apache.shenyu.loadbalancer.spi;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
import org.apache.shenyu.loadbalancer.entity.Upstream;
import org.apache.shenyu.spi.SPI;
@@ -32,8 +33,8 @@ public interface LoadBalancer {
* this is select one for upstream list.
*
* @param upstreamList upstream list
- * @param ip ip
+ * @param data data
* @return upstream
*/
- Upstream select(List<Upstream> upstreamList, String ip);
+ Upstream select(List<Upstream> upstreamList, LoadBalanceData data);
}
diff --git
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/P2cLoadBalancer.java
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/P2cLoadBalancer.java
index 684e4579df..dd0edb7ceb 100644
---
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/P2cLoadBalancer.java
+++
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/P2cLoadBalancer.java
@@ -17,6 +17,7 @@
package org.apache.shenyu.loadbalancer.spi;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
import org.apache.shenyu.loadbalancer.entity.Upstream;
import org.apache.shenyu.spi.Join;
@@ -45,16 +46,9 @@ public class P2cLoadBalancer extends AbstractLoadBalancer {
private static final int PICK_TIMES = 3;
private final Random random = new Random();
-
- /**
- * pick of 2 choices to select upstream.
- *
- * @param upstreamList the upstream list
- * @param ip the ip
- * @return selected upstream
- */
+
@Override
- protected Upstream doSelect(final List<Upstream> upstreamList, final
String ip) {
+ protected Upstream doSelect(final List<Upstream> upstreamList, final
LoadBalanceData data) {
long start = System.currentTimeMillis();
Upstream[] upstreams = pickTwoUpstreams(upstreamList);
Upstream picked;
diff --git
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/RandomLoadBalancer.java
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/RandomLoadBalancer.java
index eabb899940..5f5d7bbe33 100644
---
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/RandomLoadBalancer.java
+++
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/RandomLoadBalancer.java
@@ -17,11 +17,13 @@
package org.apache.shenyu.loadbalancer.spi;
-import java.security.SecureRandom;
-import java.util.List;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
import org.apache.shenyu.loadbalancer.entity.Upstream;
import org.apache.shenyu.spi.Join;
+import java.security.SecureRandom;
+import java.util.List;
+
/**
* random algorithm impl.
*/
@@ -31,7 +33,7 @@ public class RandomLoadBalancer extends AbstractLoadBalancer {
private static final SecureRandom RANDOM = new SecureRandom();
@Override
- public Upstream doSelect(final List<Upstream> upstreamList, final String
ip) {
+ public Upstream doSelect(final List<Upstream> upstreamList, final
LoadBalanceData data) {
int length = upstreamList.size();
// every upstream has the same weight?
boolean sameWeight = true;
diff --git
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/RoundRobinLoadBalancer.java
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/RoundRobinLoadBalancer.java
index da3e62bece..8e3a1c3c0b 100644
---
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/RoundRobinLoadBalancer.java
+++
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/RoundRobinLoadBalancer.java
@@ -18,6 +18,7 @@
package org.apache.shenyu.loadbalancer.spi;
import org.apache.shenyu.common.utils.MapUtils;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
import org.apache.shenyu.loadbalancer.entity.Upstream;
import org.apache.shenyu.spi.Join;
@@ -41,7 +42,7 @@ public class RoundRobinLoadBalancer extends
AbstractLoadBalancer {
private final AtomicBoolean updateLock = new AtomicBoolean();
@Override
- public Upstream doSelect(final List<Upstream> upstreamList, final String
ip) {
+ public Upstream doSelect(final List<Upstream> upstreamList, final
LoadBalanceData data) {
String key = upstreamList.get(0).getUrl();
ConcurrentMap<String, WeightedRoundRobin> map =
MapUtils.computeIfAbsent(methodWeightMap, key, k -> new
ConcurrentHashMap<>(16));
int totalWeight = 0;
diff --git
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/ShortestResponseLoadBalancer.java
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/ShortestResponseLoadBalancer.java
index 615608881b..edf4f15aa6 100644
---
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/ShortestResponseLoadBalancer.java
+++
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/ShortestResponseLoadBalancer.java
@@ -17,6 +17,7 @@
package org.apache.shenyu.loadbalancer.spi;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
import org.apache.shenyu.loadbalancer.entity.Upstream;
import org.apache.shenyu.spi.Join;
@@ -31,7 +32,7 @@ import java.util.concurrent.atomic.AtomicLong;
public class ShortestResponseLoadBalancer extends AbstractLoadBalancer {
@Override
- protected Upstream doSelect(final List<Upstream> upstreamList, final
String ip) {
+ protected Upstream doSelect(final List<Upstream> upstreamList, final
LoadBalanceData data) {
int length = upstreamList.size();
long shortestResponse = Long.MAX_VALUE;
int shortestCount = 0;
diff --git
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/entity/UpstreamTest.java
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/entity/UpstreamTest.java
index 0ce8dc53a7..9a9146f6b0 100644
---
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/entity/UpstreamTest.java
+++
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/entity/UpstreamTest.java
@@ -62,10 +62,10 @@ public class UpstreamTest {
.weight(1)
.status(true)
.build();
- Assertions.assertEquals(upstream2.buildDomain(), "https://url");
+ Assertions.assertEquals("https://url", upstream2.buildDomain());
Assertions.assertNotEquals(upstream, upstream2);
- Assertions.assertNotEquals(upstream, null);
- Assertions.assertNotEquals(upstream, "");
+ Assertions.assertNotEquals(null, upstream);
+ Assertions.assertNotEquals("", upstream);
Assertions.assertEquals(upstream, upstream);
Upstream upstream3 = Upstream.builder()
.protocol("https://")
diff --git
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/factory/LoadBalancerFactoryTest.java
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/factory/LoadBalancerFactoryTest.java
index cabe6c91f6..e7b7f2f280 100644
---
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/factory/LoadBalancerFactoryTest.java
+++
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/factory/LoadBalancerFactoryTest.java
@@ -17,15 +17,17 @@
package org.apache.shenyu.loadbalancer.factory;
+import org.apache.shenyu.common.enums.LoadBalanceEnum;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
+import org.apache.shenyu.loadbalancer.entity.Upstream;
+import org.junit.jupiter.api.Test;
+
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
-import org.apache.shenyu.common.enums.LoadBalanceEnum;
-import org.apache.shenyu.loadbalancer.entity.Upstream;
-import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -48,7 +50,7 @@ public final class LoadBalancerFactoryTest {
.collect(Collectors.toList());
Map<String, Integer> countMap = new HashMap<>();
IntStream.range(0, 120).forEach(i -> {
- Upstream result = LoadBalancerFactory.selector(upstreamList,
LoadBalanceEnum.ROUND_ROBIN.getName(), "");
+ Upstream result = LoadBalancerFactory.selector(upstreamList,
LoadBalanceEnum.ROUND_ROBIN.getName(), new LoadBalanceData());
int count = countMap.getOrDefault(result.getUrl(), 0);
countMap.put(result.getUrl(), ++count);
});
@@ -66,7 +68,7 @@ public final class LoadBalancerFactoryTest {
.collect(Collectors.toList());
Map<String, Integer> countMap = new HashMap<>();
IntStream.range(0, 120).forEach(i -> {
- Upstream result = LoadBalancerFactory.selector(upstreamList,
LoadBalanceEnum.ROUND_ROBIN.getName(), "");
+ Upstream result = LoadBalancerFactory.selector(upstreamList,
LoadBalanceEnum.ROUND_ROBIN.getName(), new LoadBalanceData());
int count = countMap.getOrDefault(result.getUrl(), 0);
countMap.put(result.getUrl(), ++count);
});
@@ -84,7 +86,7 @@ public final class LoadBalancerFactoryTest {
.collect(Collectors.toList());
Map<String, Integer> countMap = new HashMap<>();
IntStream.range(0, 120).forEach(i -> {
- Upstream result = LoadBalancerFactory.selector(upstreamList,
LoadBalanceEnum.ROUND_ROBIN.getName(), "");
+ Upstream result = LoadBalancerFactory.selector(upstreamList,
LoadBalanceEnum.ROUND_ROBIN.getName(), new LoadBalanceData());
int count = countMap.getOrDefault(result.getUrl(), 0);
countMap.put(result.getUrl(), ++count);
});
diff --git
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/HashLoadBalanceTest.java
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/HashLoadBalanceTest.java
index 9f643fa58a..f00057e4d0 100644
---
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/HashLoadBalanceTest.java
+++
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/HashLoadBalanceTest.java
@@ -17,16 +17,13 @@
package org.apache.shenyu.loadbalancer.spi;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
import org.apache.shenyu.loadbalancer.entity.Upstream;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.mockito.MockedStatic;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.SortedMap;
import java.util.concurrent.ConcurrentSkipListMap;
@@ -34,8 +31,6 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.Mockito.mockStatic;
/**
* The type Hash balance test.
@@ -44,8 +39,6 @@ public final class HashLoadBalanceTest {
private Method hash;
- private List<Upstream> onlyOneList;
-
private List<Upstream> hashLoadBalancesOrdered;
private List<Upstream> hashLoadBalancesDisordered;
@@ -62,12 +55,6 @@ public final class HashLoadBalanceTest {
public void setUp() throws Exception {
this.hash = HashLoadBalancer.class.getDeclaredMethod("hash",
String.class);
this.hash.setAccessible(true);
- this.onlyOneList = Stream.of(1)
- .map(weight -> Upstream.builder()
- .url("upstream-" + weight)
- .status(false)
- .build())
- .collect(Collectors.toList());
this.hashLoadBalancesOrdered = Stream.of(1, 2, 3)
.map(weight -> Upstream.builder()
.url("upstream-" + weight)
@@ -109,56 +96,15 @@ public final class HashLoadBalanceTest {
}
}
- /**
- * Hash load balance test.
- */
- @Test
- public void onlyOneListTest() {
- final String ip = "127.0.0.1";
- final HashLoadBalancer hashLoadBalance = new HashLoadBalancer();
- Assertions.assertNotNull(hashLoadBalance.select(onlyOneList, ip));
-
Assertions.assertEquals(hashLoadBalance.getWeight(Upstream.builder().status(false).build()),
0);
- Assertions.assertEquals(hashLoadBalance.getWeight(Upstream.builder()
- .timestamp(System.currentTimeMillis() - 3L)
- .warmup(4)
- .weight(1)
- .build()), 1);
- Assertions.assertEquals(hashLoadBalance.getWeight(Upstream.builder()
- .timestamp(System.currentTimeMillis() + 3L)
- .warmup(4)
- .weight(1)
- .build()), 1);
- Assertions.assertEquals(hashLoadBalance.getWeight(Upstream.builder()
- .timestamp(System.currentTimeMillis() - 3000L)
- .warmup(4000)
- .weight(4)
- .build()), 3);
- Assertions.assertEquals(hashLoadBalance.getWeight(Upstream.builder()
- .timestamp(System.currentTimeMillis() - 3L)
- .warmup(1)
- .weight(1)
- .build()), 1);
- Assertions.assertEquals(hashLoadBalance.getWeight(Upstream.builder()
- .warmup(1)
- .weight(0)
- .build()), 0);
- Assertions.assertEquals(hashLoadBalance.getWeight(Upstream.builder()
- .warmup(0)
- .weight(1)
- .build()), 1);
-
- }
-
/**
* Hash load balance test.
*/
@Test
public void hashLoadBalanceOrderedWeightTest() throws Exception {
- final String ip = "127.0.0.1";
final HashLoadBalancer hashLoadBalance = new HashLoadBalancer();
- Assertions.assertNull(hashLoadBalance.select(null, ip));
- final Upstream upstream =
hashLoadBalance.select(hashLoadBalancesOrdered, ip);
- final Long hashKey = Long.parseLong(hash.invoke(null, ip).toString());
+ Assertions.assertNull(hashLoadBalance.select(null, new
LoadBalanceData()));
+ final Upstream upstream =
hashLoadBalance.select(hashLoadBalancesOrdered, new LoadBalanceData());
+ final Long hashKey = Long.parseLong(hash.invoke(null,
"127.0.0.1").toString());
final SortedMap<Long, Upstream> lastRing =
treeMapOrdered.tailMap(hashKey);
final Upstream assertUp = lastRing.get(lastRing.firstKey());
assertEquals(assertUp.getUrl(), upstream.getUrl());
@@ -167,27 +113,19 @@ public final class HashLoadBalanceTest {
@Test
public void selectTest() {
final String ip = "SHENYU-upstream-2-HASH-100";
+ LoadBalanceData data = new LoadBalanceData();
+ data.setIp(ip);
final HashLoadBalancer hashLoadBalance = new HashLoadBalancer();
- Assertions.assertNull(hashLoadBalance.select(null, ip));
- final Upstream upstream =
hashLoadBalance.select(hashLoadBalancesOrdered, ip);
+ Assertions.assertNull(hashLoadBalance.select(null, new
LoadBalanceData()));
+ final Upstream upstream =
hashLoadBalance.select(hashLoadBalancesOrdered, data);
assertEquals(treeMapOrdered.firstEntry().getValue().getUrl(),
upstream.getUrl());
}
- @Test
- public void hashErrorTest() throws NoSuchAlgorithmException {
- final String ip = "127.0.0.1";
- MockedStatic<MessageDigest> messageDigestMockedStatic =
mockStatic(MessageDigest.class);
- messageDigestMockedStatic.when((MockedStatic.Verification)
MessageDigest.getInstance("MD5")).thenThrow(NoSuchAlgorithmException.class);
- assertThrows(InvocationTargetException.class, () -> hash.invoke(null,
ip));
- messageDigestMockedStatic.close();
- }
-
@Test
public void hashLoadBalanceDisorderedWeightTest() throws Exception {
- final String ip = "127.0.0.1";
final HashLoadBalancer hashLoadBalance = new HashLoadBalancer();
- final Upstream upstream =
hashLoadBalance.select(hashLoadBalancesDisordered, ip);
- final Long hashKey = Long.parseLong(hash.invoke(null, ip).toString());
+ final Upstream upstream =
hashLoadBalance.select(hashLoadBalancesDisordered, new LoadBalanceData());
+ final Long hashKey = Long.parseLong(hash.invoke(null,
"127.0.0.1").toString());
final SortedMap<Long, Upstream> lastRing =
treeMapDisordered.tailMap(hashKey);
final Upstream assertUp = lastRing.get(lastRing.firstKey());
assertEquals(assertUp.getUrl(), upstream.getUrl());
@@ -196,10 +134,9 @@ public final class HashLoadBalanceTest {
@Test
public void hashLoadBalanceReversedWeightTest() throws Exception {
- final String ip = "127.0.0.1";
final HashLoadBalancer hashLoadBalance = new HashLoadBalancer();
- final Upstream divideUpstream =
hashLoadBalance.select(hashLoadBalancesReversed, ip);
- final Long hashKey = Long.parseLong(hash.invoke(null, ip).toString());
+ final Upstream divideUpstream =
hashLoadBalance.select(hashLoadBalancesReversed, new LoadBalanceData());
+ final Long hashKey = Long.parseLong(hash.invoke(null,
"127.0.0.1").toString());
final SortedMap<Long, Upstream> lastRing =
treeMapReversed.tailMap(hashKey);
final Upstream assertUp = lastRing.get(lastRing.firstKey());
assertEquals(assertUp.getUrl(), divideUpstream.getUrl());
diff --git
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/HashLoadBalancerTest.java
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/HashLoadBalancerTest.java
index e7c9d1fca4..a58beff641 100644
---
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/HashLoadBalancerTest.java
+++
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/HashLoadBalancerTest.java
@@ -17,6 +17,7 @@
package org.apache.shenyu.loadbalancer.spi;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
import org.apache.shenyu.loadbalancer.entity.Upstream;
import org.junit.jupiter.api.Test;
@@ -38,7 +39,7 @@ class HashLoadBalancerTest {
upstreamList.add(Upstream.builder().url("http://2.2.2.2/api").build());
upstreamList.add(Upstream.builder().url("http://3.3.3.3/api").build());
- final Upstream upstream = hashLoadBalancer.doSelect(upstreamList,
"127.0.0.1");
+ Upstream upstream = hashLoadBalancer.doSelect(upstreamList, new
LoadBalanceData());
assertEquals(upstreamList.get(2).getUrl(), upstream.getUrl());
}
diff --git
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/LeastActiveLoadBalanceTest.java
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/LeastActiveLoadBalanceTest.java
index 49c1e70ab9..44a6851dc2 100644
---
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/LeastActiveLoadBalanceTest.java
+++
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/LeastActiveLoadBalanceTest.java
@@ -17,12 +17,14 @@
package org.apache.shenyu.loadbalancer.spi;
-import java.util.ArrayList;
-import java.util.List;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
import org.apache.shenyu.loadbalancer.entity.Upstream;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* The type least activity load balance test.
*/
@@ -49,8 +51,8 @@ public class LeastActiveLoadBalanceTest {
public void testResponseTimeBalancer() throws Exception {
buildUpstreamList();
final LeastActiveLoadBalance leastActiveLoadBalance = new
LeastActiveLoadBalance();
- Upstream upstream = leastActiveLoadBalance.doSelect(onlyOneList,
"localhost");
- Upstream upstream1 = leastActiveLoadBalance.doSelect(onlyOneList,
"localhost");
+ Upstream upstream = leastActiveLoadBalance.doSelect(onlyOneList, new
LoadBalanceData());
+ Upstream upstream1 = leastActiveLoadBalance.doSelect(onlyOneList, new
LoadBalanceData());
Assertions.assertTrue(upstream.getUrl().equals("baidu.com") &&
upstream1.getUrl().equals("pro.jd.com")
|| upstream1.getUrl().equals("baidu.com") &&
upstream.getUrl().equals("pro.jd.com"));
}
diff --git
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/P2cLoadBalancerTest.java
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/P2cLoadBalancerTest.java
index 493418656b..5b760949fc 100644
---
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/P2cLoadBalancerTest.java
+++
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/P2cLoadBalancerTest.java
@@ -17,6 +17,7 @@
package org.apache.shenyu.loadbalancer.spi;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
import org.apache.shenyu.loadbalancer.entity.Upstream;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -47,8 +48,8 @@ public class P2cLoadBalancerTest {
public void testResponseTimeBalancerSameLag() {
buildUpstreamList();
final P2cLoadBalancer p2cLoadBalancer = new P2cLoadBalancer();
- Upstream upstream = p2cLoadBalancer.doSelect(upstreamList,
"localhost");
- Upstream upstream1 = p2cLoadBalancer.doSelect(upstreamList,
"localhost");
+ Upstream upstream = p2cLoadBalancer.doSelect(upstreamList, new
LoadBalanceData());
+ Upstream upstream1 = p2cLoadBalancer.doSelect(upstreamList, new
LoadBalanceData());
Assertions.assertTrue(upstream.getUrl().equals("baidu.com") &&
upstream1.getUrl().equals("pro.jd.com")
|| upstream1.getUrl().equals("baidu.com") &&
upstream.getUrl().equals("pro.jd.com"));
}
@@ -58,8 +59,8 @@ public class P2cLoadBalancerTest {
buildUpstreamList();
final P2cLoadBalancer p2cLoadBalancer = new P2cLoadBalancer();
upstreamList.get(0).setLag(1);
- Upstream upstream = p2cLoadBalancer.doSelect(upstreamList,
"localhost");
- Upstream upstream1 = p2cLoadBalancer.doSelect(upstreamList,
"localhost");
+ Upstream upstream = p2cLoadBalancer.doSelect(upstreamList, new
LoadBalanceData());
+ Upstream upstream1 = p2cLoadBalancer.doSelect(upstreamList, new
LoadBalanceData());
Assertions.assertTrue(upstream.getUrl().equals("baidu.com") &&
upstream1.getUrl().equals("pro.jd.com"));
}
}
diff --git
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/RandomLoadBalancerTest.java
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/RandomLoadBalancerTest.java
index b6c8ad979f..f733a82b3b 100644
---
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/RandomLoadBalancerTest.java
+++
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/RandomLoadBalancerTest.java
@@ -17,6 +17,7 @@
package org.apache.shenyu.loadbalancer.spi;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
import org.apache.shenyu.loadbalancer.entity.Upstream;
import org.junit.jupiter.api.Test;
@@ -37,7 +38,7 @@ public class RandomLoadBalancerTest {
.url("upstream-" + weight)
.weight(weight)
.build())
- .collect(Collectors.toList()), "");
+ .collect(Collectors.toList()), new LoadBalanceData());
assertNotNull(upstreamOrdered);
}
@@ -48,7 +49,7 @@ public class RandomLoadBalancerTest {
.url("upstream-" + weight)
.weight(weight)
.build())
- .collect(Collectors.toList()), "");
+ .collect(Collectors.toList()), new LoadBalanceData());
assertNotNull(upstreamOrdered);
}
@@ -62,7 +63,7 @@ public class RandomLoadBalancerTest {
.url("upstream-" + weight)
.weight(weight)
.build())
- .collect(Collectors.toList()), "");
+ .collect(Collectors.toList()), new LoadBalanceData());
assertNotNull(upstreamOrdered);
}
@@ -73,7 +74,7 @@ public class RandomLoadBalancerTest {
.url("upstream-" + weight)
.weight(weight)
.build())
- .collect(Collectors.toList()), "");
+ .collect(Collectors.toList()), new LoadBalanceData());
assertNotNull(upstreamDisordered);
}
@@ -84,7 +85,7 @@ public class RandomLoadBalancerTest {
.url("upstream-" + weight)
.weight(weight)
.build())
- .collect(Collectors.toList()), "");
+ .collect(Collectors.toList()), new LoadBalanceData());
assertNotNull(upstreamReversed);
}
}
diff --git
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/RoundRobinLoadBalanceTest.java
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/RoundRobinLoadBalanceTest.java
index c21daab40d..dde5d3d0f8 100644
---
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/RoundRobinLoadBalanceTest.java
+++
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/RoundRobinLoadBalanceTest.java
@@ -17,6 +17,7 @@
package org.apache.shenyu.loadbalancer.spi;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
import org.apache.shenyu.loadbalancer.entity.Upstream;
import org.junit.jupiter.api.Test;
@@ -54,7 +55,7 @@ public final class RoundRobinLoadBalanceTest {
RoundRobinLoadBalancer roundRobinLoadBalancer = new
RoundRobinLoadBalancer();
Map<String, Integer> countMap = new HashMap<>();
IntStream.range(0, 120).forEach(i -> {
- Upstream result = roundRobinLoadBalancer.select(upstreamList, "");
+ Upstream result = roundRobinLoadBalancer.select(upstreamList, new
LoadBalanceData());
int count = countMap.getOrDefault(result.getUrl(), 0);
countMap.put(result.getUrl(), ++count);
});
@@ -74,7 +75,7 @@ public final class RoundRobinLoadBalanceTest {
RoundRobinLoadBalancer roundRobinLoadBalancer = new
RoundRobinLoadBalancer();
Map<String, Integer> countMap = new HashMap<>();
IntStream.range(0, 120).forEach(i -> {
- Upstream result = roundRobinLoadBalancer.select(upstreamList, "");
+ Upstream result = roundRobinLoadBalancer.select(upstreamList, new
LoadBalanceData());
int count = countMap.getOrDefault(result.getUrl(), 0);
countMap.put(result.getUrl(), ++count);
});
@@ -94,7 +95,7 @@ public final class RoundRobinLoadBalanceTest {
RoundRobinLoadBalancer roundRobinLoadBalancer = new
RoundRobinLoadBalancer();
Map<String, Integer> countMap = new HashMap<>();
IntStream.range(0, 120).forEach(i -> {
- Upstream result = roundRobinLoadBalancer.select(upstreamList, "");
+ Upstream result = roundRobinLoadBalancer.select(upstreamList, new
LoadBalanceData());
int count = countMap.getOrDefault(result.getUrl(), 0);
countMap.put(result.getUrl(), ++count);
});
@@ -121,19 +122,19 @@ public final class RoundRobinLoadBalanceTest {
RoundRobinLoadBalancer roundRobinLoadBalancer = new
RoundRobinLoadBalancer();
// Test with weighted upstream list
- Upstream result1 = roundRobinLoadBalancer.select(upstreamList, "");
+ Upstream result1 = roundRobinLoadBalancer.select(upstreamList, new
LoadBalanceData());
assertNotNull(result1, "Selected upstream should not be null");
assertTrue(upstreamList.contains(result1), "Selected upstream should
be from the provided list");
// Test with equal weight upstream list
- Upstream result2 = roundRobinLoadBalancer.select(upstreamList2, "");
+ Upstream result2 = roundRobinLoadBalancer.select(upstreamList2, new
LoadBalanceData());
assertNotNull(result2, "Selected upstream should not be null");
assertTrue(upstreamList2.contains(result2), "Selected upstream should
be from the provided list");
// Test multiple selections to verify round-robin behavior
Map<String, Integer> countMap = new HashMap<>();
IntStream.range(0, SELECTION_ITERATIONS).forEach(i -> {
- Upstream result = roundRobinLoadBalancer.select(upstreamList2, "");
+ Upstream result = roundRobinLoadBalancer.select(upstreamList2, new
LoadBalanceData());
int count = countMap.getOrDefault(result.getUrl(), 0);
countMap.put(result.getUrl(), ++count);
});
diff --git
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/ShortestResponseLoadBalancerTest.java
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/ShortestResponseLoadBalancerTest.java
index abd579e029..b6bb359d20 100644
---
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/ShortestResponseLoadBalancerTest.java
+++
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/ShortestResponseLoadBalancerTest.java
@@ -17,6 +17,7 @@
package org.apache.shenyu.loadbalancer.spi;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
import org.apache.shenyu.loadbalancer.entity.Upstream;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -45,7 +46,7 @@ public class ShortestResponseLoadBalancerTest {
int loop = 10000;
ShortestResponseLoadBalancer lb = new ShortestResponseLoadBalancer();
for (int i = 0; i < loop; i++) {
- Upstream upstream = lb.select(upstreamList, "");
+ Upstream upstream = lb.select(upstreamList, new LoadBalanceData());
if (upstream.getUrl().equals("upstream-1")) {
select1++;
}
@@ -71,7 +72,7 @@ public class ShortestResponseLoadBalancerTest {
upstreamList.get(0).getSucceeded().addAndGet(1);
upstreamList.get(0).getSucceededElapsed().addAndGet(50000);
for (int i = 0; i < loop; i++) {
- Upstream upstream = lb.select(upstreamList, "");
+ Upstream upstream = lb.select(upstreamList, new LoadBalanceData());
if (upstream.getUrl().equals("upstream-1")) {
select1++;
}
diff --git a/shenyu-plugin/shenyu-plugin-base/pom.xml
b/shenyu-plugin/shenyu-plugin-base/pom.xml
index 2cea6d65bc..ec9f557b66 100644
--- a/shenyu-plugin/shenyu-plugin-base/pom.xml
+++ b/shenyu-plugin/shenyu-plugin-base/pom.xml
@@ -40,6 +40,12 @@
<artifactId>shenyu-spi</artifactId>
<version>${project.version}</version>
</dependency>
+
+ <dependency>
+ <groupId>org.apache.shenyu</groupId>
+ <artifactId>shenyu-loadbalancer</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
diff --git
a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/utils/LoadbalancerUtils.java
b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/utils/LoadbalancerUtils.java
new file mode 100644
index 0000000000..91e8e850ab
--- /dev/null
+++
b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/utils/LoadbalancerUtils.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.plugin.base.utils;
+
+import org.apache.commons.collections4.MapUtils;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
+import org.apache.shenyu.loadbalancer.entity.Upstream;
+import org.apache.shenyu.loadbalancer.factory.LoadBalancerFactory;
+import org.springframework.http.HttpCookie;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.server.ServerWebExchange;
+
+import java.net.URI;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * The type Loadbalancer utils.
+ */
+public final class LoadbalancerUtils {
+
+ private LoadbalancerUtils() {
+ }
+
+ /**
+ * Gets for exchange.
+ *
+ * @param upstreamList the upstream list
+ * @param algorithm the algorithm
+ * @param exchange the exchange
+ * @return the for exchange
+ */
+ public static Upstream getForExchange(final List<Upstream> upstreamList,
final String algorithm, final ServerWebExchange exchange) {
+ LoadBalanceData loadBalanceData = buildLoadBalanceData(exchange);
+ return LoadBalancerFactory.selector(upstreamList, algorithm,
loadBalanceData);
+ }
+
+ /**
+ * Gets for no exchange.
+ *
+ * @param upstreamList the upstream list
+ * @param algorithm the algorithm
+ * @return the for no exchange
+ */
+ public static Upstream getForNoExchange(final List<Upstream> upstreamList,
final String algorithm) {
+ return LoadBalancerFactory.selector(upstreamList, algorithm, new
LoadBalanceData());
+ }
+
+ private static LoadBalanceData buildLoadBalanceData(final
ServerWebExchange exchange) {
+ ServerHttpRequest request = exchange.getRequest();
+ String ip =
Objects.requireNonNull(request.getRemoteAddress()).getAddress().getHostAddress();
+ String httpMethod = request.getMethod().name();
+ URI uri = exchange.getRequest().getURI();
+ HttpHeaders headers = request.getHeaders();
+ MultiValueMap<String, HttpCookie> cookies = request.getCookies();
+ Map<String, Object> attributes = exchange.getAttributes();
+ MultiValueMap<String, String> queryParams = request.getQueryParams();
+ return new LoadBalanceData(httpMethod, ip, uri,
+ buildMultiValueMap(headers),
+ buildCookies(cookies),
+ attributes,
+ buildMultiValueMap(queryParams));
+ }
+
+ private static Map<String, Collection<String>> buildMultiValueMap(final
MultiValueMap<String, String> queryParams) {
+ Map<String, Collection<String>> resultMap = new HashMap<>();
+ if (MapUtils.isNotEmpty(queryParams)) {
+ resultMap.putAll(queryParams);
+ }
+ return resultMap;
+ }
+
+ private static Map<String, String> buildCookies(final
MultiValueMap<String, HttpCookie> cookies) {
+ Map<String, String> resultMap = new HashMap<>();
+ if (MapUtils.isNotEmpty(cookies)) {
+ cookies.forEach((key, value) -> value.forEach((cookie) ->
resultMap.put(cookie.getName(), cookie.getValue())));
+ }
+ return resultMap;
+ }
+}
diff --git
a/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/DefaultRetryStrategy.java
b/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/DefaultRetryStrategy.java
index c7a259c951..6339ddbee6 100644
---
a/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/DefaultRetryStrategy.java
+++
b/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/DefaultRetryStrategy.java
@@ -17,23 +17,13 @@
package org.apache.shenyu.plugin.httpclient;
-import java.net.URI;
-import java.time.Duration;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.TimeoutException;
-import java.util.stream.Collectors;
import org.apache.shenyu.common.constant.Constants;
import org.apache.shenyu.common.enums.RetryEnum;
import org.apache.shenyu.common.exception.ShenyuException;
import org.apache.shenyu.loadbalancer.cache.UpstreamCacheManager;
import org.apache.shenyu.loadbalancer.entity.Upstream;
-import org.apache.shenyu.loadbalancer.factory.LoadBalancerFactory;
import org.apache.shenyu.plugin.api.utils.RequestUrlUtils;
+import org.apache.shenyu.plugin.base.utils.LoadbalancerUtils;
import org.apache.shenyu.plugin.httpclient.exception.ShenyuTimeoutException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,6 +34,17 @@ import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;
import reactor.util.retry.RetryBackoffSpec;
+import java.net.URI;
+import java.time.Duration;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.TimeoutException;
+import java.util.stream.Collectors;
+
/**
* Default Retry Policy Class
@@ -119,8 +120,7 @@ public class DefaultRetryStrategy<R> implements
RetryStrategy<R> {
// no need to retry anymore
return Mono.error(new
ShenyuException("CANNOT_FIND_HEALTHY_UPSTREAM_URL_AFTER_FAILOVER"));
}
- final String ip =
Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getAddress().getHostAddress();
- final Upstream upstream =
LoadBalancerFactory.selector(upstreamList, loadBalance, ip);
+ final Upstream upstream =
LoadbalancerUtils.getForExchange(upstreamList, loadBalance, exchange);
if (Objects.isNull(upstream)) {
// no need to retry anymore
return Mono.error(new
ShenyuException("CANNOT_FIND_HEALTHY_UPSTREAM_URL_AFTER_FAILOVER"));
diff --git
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-divide/src/main/java/org/apache/shenyu/plugin/divide/DividePlugin.java
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-divide/src/main/java/org/apache/shenyu/plugin/divide/DividePlugin.java
index 39a514b2ee..d1d1cd7342 100644
---
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-divide/src/main/java/org/apache/shenyu/plugin/divide/DividePlugin.java
+++
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-divide/src/main/java/org/apache/shenyu/plugin/divide/DividePlugin.java
@@ -29,7 +29,6 @@ import org.apache.shenyu.common.enums.RetryEnum;
import org.apache.shenyu.common.enums.RpcTypeEnum;
import org.apache.shenyu.loadbalancer.cache.UpstreamCacheManager;
import org.apache.shenyu.loadbalancer.entity.Upstream;
-import org.apache.shenyu.loadbalancer.factory.LoadBalancerFactory;
import org.apache.shenyu.plugin.api.ShenyuPluginChain;
import org.apache.shenyu.plugin.api.context.ShenyuContext;
import org.apache.shenyu.plugin.api.result.ShenyuResultEnum;
@@ -38,6 +37,7 @@ import org.apache.shenyu.plugin.api.utils.RequestUrlUtils;
import org.apache.shenyu.plugin.api.utils.WebFluxResultUtils;
import org.apache.shenyu.plugin.base.AbstractShenyuPlugin;
import org.apache.shenyu.plugin.base.utils.CacheKeyUtils;
+import org.apache.shenyu.plugin.base.utils.LoadbalancerUtils;
import org.apache.shenyu.plugin.divide.handler.DividePluginDataHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -97,16 +97,16 @@ public class DividePlugin extends AbstractShenyuPlugin {
Object error = ShenyuResultWrap.error(exchange,
ShenyuResultEnum.CANNOT_FIND_HEALTHY_UPSTREAM_URL);
return WebFluxResultUtils.result(exchange, error);
}
- String ip =
Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getAddress().getHostAddress();
- Upstream upstream = LoadBalancerFactory.selector(upstreamList,
ruleHandle.getLoadBalance(), ip);
+ Upstream upstream = LoadbalancerUtils.getForExchange(upstreamList,
ruleHandle.getLoadBalance(), exchange);
if (Objects.isNull(upstream)) {
LOG.error("divide has no upstream");
Object error = ShenyuResultWrap.error(exchange,
ShenyuResultEnum.CANNOT_FIND_HEALTHY_UPSTREAM_URL);
return WebFluxResultUtils.result(exchange, error);
}
// set the http url
- if
(CollectionUtils.isNotEmpty(exchange.getRequest().getHeaders().get(Constants.SPECIFY_DOMAIN)))
{
-
upstream.setUrl(exchange.getRequest().getHeaders().get(Constants.SPECIFY_DOMAIN).get(0));
+ List<String> specifyDomains =
exchange.getRequest().getHeaders().get(Constants.SPECIFY_DOMAIN);
+ if (CollectionUtils.isNotEmpty(specifyDomains)) {
+ upstream.setUrl(specifyDomains.get(0));
}
// set domain
String domain = upstream.buildDomain();
@@ -115,8 +115,8 @@ public class DividePlugin extends AbstractShenyuPlugin {
exchange.getAttributes().put(Constants.HTTP_TIME_OUT,
ruleHandle.getTimeout());
exchange.getAttributes().put(Constants.HTTP_RETRY,
ruleHandle.getRetry());
// set retry strategy stuff
- exchange.getAttributes().put(Constants.RETRY_STRATEGY,
StringUtils.defaultString(ruleHandle.getRetryStrategy(),
RetryEnum.CURRENT.getName()));
- exchange.getAttributes().put(Constants.LOAD_BALANCE,
StringUtils.defaultString(ruleHandle.getLoadBalance(),
LoadBalanceEnum.RANDOM.getName()));
+ exchange.getAttributes().put(Constants.RETRY_STRATEGY,
StringUtils.defaultIfEmpty(ruleHandle.getRetryStrategy(),
RetryEnum.CURRENT.getName()));
+ exchange.getAttributes().put(Constants.LOAD_BALANCE,
StringUtils.defaultIfEmpty(ruleHandle.getLoadBalance(),
LoadBalanceEnum.RANDOM.getName()));
exchange.getAttributes().put(Constants.DIVIDE_SELECTOR_ID,
selector.getId());
if (ruleHandle.getLoadBalance().equals(P2C)) {
return chain.execute(exchange).doOnSuccess(e ->
responseTrigger(upstream
@@ -185,4 +185,5 @@ public class DividePlugin extends AbstractShenyuPlugin {
upstream.getSucceededElapsed().addAndGet(System.currentTimeMillis() -
beginTime);
upstream.getSucceeded().incrementAndGet();
}
+
}
diff --git
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-dubbo/shenyu-plugin-apache-dubbo/src/main/java/org/apache/shenyu/plugin/apache/dubbo/proxy/ApacheDubboGrayLoadBalance.java
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-dubbo/shenyu-plugin-apache-dubbo/src/main/java/org/apache/shenyu/plugin/apache/dubbo/proxy/ApacheDubboGrayLoadBalance.java
index bacbf901b2..9551ff2f18 100644
---
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-dubbo/shenyu-plugin-apache-dubbo/src/main/java/org/apache/shenyu/plugin/apache/dubbo/proxy/ApacheDubboGrayLoadBalance.java
+++
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-dubbo/shenyu-plugin-apache-dubbo/src/main/java/org/apache/shenyu/plugin/apache/dubbo/proxy/ApacheDubboGrayLoadBalance.java
@@ -32,8 +32,8 @@ import
org.apache.shenyu.common.dto.convert.rule.impl.DubboRuleHandle;
import org.apache.shenyu.common.dto.convert.selector.DubboUpstream;
import org.apache.shenyu.loadbalancer.cache.UpstreamCacheManager;
import org.apache.shenyu.loadbalancer.entity.Upstream;
-import org.apache.shenyu.loadbalancer.factory.LoadBalancerFactory;
import
org.apache.shenyu.plugin.apache.dubbo.handler.ApacheDubboPluginDataHandler;
+import org.apache.shenyu.plugin.base.utils.LoadbalancerUtils;
import java.util.List;
import java.util.Objects;
@@ -54,7 +54,7 @@ public class ApacheDubboGrayLoadBalance implements
LoadBalance {
DubboRuleHandle dubboRuleHandle =
ApacheDubboPluginDataHandler.RULE_CACHED_HANDLE.get().obtainHandle(shenyuRuleId);
// if gray list is not empty,just use load balance to choose one.
if (CollectionUtils.isNotEmpty(dubboUpstreams)) {
- Upstream upstream =
LoadBalancerFactory.selector(UpstreamCacheManager.getInstance().findUpstreamListBySelectorId(shenyuSelectorId),
dubboRuleHandle.getLoadBalance(), remoteAddressIp);
+ Upstream upstream =
LoadbalancerUtils.getForNoExchange(UpstreamCacheManager.getInstance().findUpstreamListBySelectorId(shenyuSelectorId),
dubboRuleHandle.getLoadBalance());
if (Objects.isNull(upstream)) {
return dubboSelect(invokers, url, invocation);
}
diff --git
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-dubbo/shenyu-plugin-apache-dubbo/src/main/java/org/apache/shenyu/plugin/apache/dubbo/proxy/ApacheDubboProxyService.java
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-dubbo/shenyu-plugin-apache-dubbo/src/main/java/org/apache/shenyu/plugin/apache/dubbo/proxy/ApacheDubboProxyService.java
index 8bfcaf45ad..cdbe6375c2 100644
---
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-dubbo/shenyu-plugin-apache-dubbo/src/main/java/org/apache/shenyu/plugin/apache/dubbo/proxy/ApacheDubboProxyService.java
+++
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-dubbo/shenyu-plugin-apache-dubbo/src/main/java/org/apache/shenyu/plugin/apache/dubbo/proxy/ApacheDubboProxyService.java
@@ -17,12 +17,6 @@
package org.apache.shenyu.plugin.apache.dubbo.proxy;
-import java.util.Objects;
-import java.util.concurrent.CompletableFuture;
-import java.util.stream.Collectors;
-import java.util.List;
-import java.util.Collections;
-import java.util.Optional;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
@@ -44,13 +38,20 @@ import org.apache.shenyu.common.utils.GsonUtils;
import org.apache.shenyu.common.utils.JsonUtils;
import org.apache.shenyu.common.utils.ParamCheckUtils;
import org.apache.shenyu.loadbalancer.entity.Upstream;
-import org.apache.shenyu.loadbalancer.factory.LoadBalancerFactory;
import org.apache.shenyu.plugin.apache.dubbo.cache.ApacheDubboConfigCache;
+import org.apache.shenyu.plugin.base.utils.LoadbalancerUtils;
import org.apache.shenyu.plugin.dubbo.common.param.DubboParamResolveService;
import org.springframework.util.ObjectUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
+
/**
* dubbo proxy service is use GenericService.
*/
@@ -140,8 +141,7 @@ public class ApacheDubboProxyService {
}
List<Upstream> upstreams = this.convertUpstreamList(dubboUpstreams);
- String ip =
Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getAddress().getHostAddress();
- Upstream upstream = LoadBalancerFactory.selector(upstreams,
LoadBalanceEnum.RANDOM.getName(), ip);
+ Upstream upstream = LoadbalancerUtils.getForExchange(upstreams,
LoadBalanceEnum.RANDOM.getName(), exchange);
DubboUpstream dubboUpstream = dubboUpstreams.get(0);
for (DubboUpstream upstreamItem : dubboUpstreams) {
if (Objects.equals(upstreamItem.getRegistry(), upstream.getUrl())
diff --git
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/picker/ShenyuPicker.java
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/picker/ShenyuPicker.java
index ef71b3ef98..616ab9f3e6 100644
---
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/picker/ShenyuPicker.java
+++
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/picker/ShenyuPicker.java
@@ -22,6 +22,7 @@ import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shenyu.common.dto.convert.rule.impl.GrpcRuleHandle;
import org.apache.shenyu.common.dto.convert.selector.GrpcUpstream;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
import org.apache.shenyu.loadbalancer.entity.Upstream;
import org.apache.shenyu.loadbalancer.factory.LoadBalancerFactory;
import org.apache.shenyu.plugin.grpc.cache.ApplicationConfigCache;
@@ -45,19 +46,19 @@ public class ShenyuPicker extends AbstractReadyPicker {
@Override
protected SubChannelCopy pick(final List<SubChannelCopy> list) {
-
String grpcRuleId = GrpcConstants.GRPC_RULE_ID.get();
String selectorId = GrpcConstants.GRPC_SELECTOR_ID.get();
String remoteAddressIp = GrpcConstants.GRPC_REMOTE_ADDRESS.get();
final GrpcRuleHandle cacheRuleHandle =
ApplicationConfigCache.getInstance().getCacheRuleHandle(grpcRuleId);
List<GrpcUpstream> grpcUpstreams =
ApplicationConfigCache.getInstance().getGrpcUpstreamListCache(selectorId);
if (CollectionUtils.isNotEmpty(grpcUpstreams)) {
- Upstream upstream =
LoadBalancerFactory.selector(convertUpstreamList(grpcUpstreams),
cacheRuleHandle.getLoadBalance(), remoteAddressIp);
+ LoadBalanceData data = new LoadBalanceData();
+ data.setIp(remoteAddressIp);
+ Upstream upstream =
LoadBalancerFactory.selector(convertUpstreamList(grpcUpstreams),
cacheRuleHandle.getLoadBalance(), data);
if (StringUtils.isBlank(upstream.getUrl()) &&
StringUtils.isBlank(upstream.getGroup()) &&
StringUtils.isBlank(upstream.getVersion())) {
return randomPicker.pick(list);
}
-
- final List<SubChannelCopy> invokerGrays =
list.stream().filter(each ->
each.getUrl().equals(upstream.getUrl())).collect(Collectors.toList());
+ final List<SubChannelCopy> invokerGrays =
list.stream().filter(each -> each.getUrl().equals(upstream.getUrl())).toList();
return invokerGrays.stream().findFirst().orElse(null);
}
return randomPicker.pick(list);
@@ -72,5 +73,4 @@ public class ShenyuPicker extends AbstractReadyPicker {
.timestamp(u.getTimestamp())
.build()).collect(Collectors.toList());
}
-
}
diff --git
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-websocket/src/main/java/org/apache/shenyu/plugin/websocket/WebSocketPlugin.java
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-websocket/src/main/java/org/apache/shenyu/plugin/websocket/WebSocketPlugin.java
index 11e5f3cfd9..697238e15e 100644
---
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-websocket/src/main/java/org/apache/shenyu/plugin/websocket/WebSocketPlugin.java
+++
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-websocket/src/main/java/org/apache/shenyu/plugin/websocket/WebSocketPlugin.java
@@ -27,7 +27,6 @@ import org.apache.shenyu.common.enums.PluginEnum;
import org.apache.shenyu.common.enums.RpcTypeEnum;
import org.apache.shenyu.loadbalancer.cache.UpstreamCacheManager;
import org.apache.shenyu.loadbalancer.entity.Upstream;
-import org.apache.shenyu.loadbalancer.factory.LoadBalancerFactory;
import org.apache.shenyu.plugin.api.ShenyuPluginChain;
import org.apache.shenyu.plugin.api.context.ShenyuContext;
import org.apache.shenyu.plugin.api.result.ShenyuResultEnum;
@@ -36,6 +35,7 @@ import org.apache.shenyu.plugin.api.utils.RequestUrlUtils;
import org.apache.shenyu.plugin.api.utils.WebFluxResultUtils;
import org.apache.shenyu.plugin.base.AbstractShenyuPlugin;
import org.apache.shenyu.plugin.base.utils.CacheKeyUtils;
+import org.apache.shenyu.plugin.base.utils.LoadbalancerUtils;
import org.apache.shenyu.plugin.websocket.handler.WebSocketPluginDataHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -96,8 +96,7 @@ public class WebSocketPlugin extends AbstractShenyuPlugin {
return chain.execute(exchange);
}
final WebSocketRuleHandle ruleHandle = buildRuleHandle(rule);
- final String ip =
Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getAddress().getHostAddress();
- Upstream upstream = LoadBalancerFactory.selector(upstreamList,
ruleHandle.getLoadBalance(), ip);
+ Upstream upstream = LoadbalancerUtils.getForExchange(upstreamList,
ruleHandle.getLoadBalance(), exchange);
if (Objects.isNull(upstream)) {
LOG.error("websocket has no upstream, error:{}", rule);
Object error = ShenyuResultWrap.error(exchange,
ShenyuResultEnum.CANNOT_FIND_HEALTHY_UPSTREAM_URL);
diff --git
a/shenyu-protocol/shenyu-protocol-tcp/src/main/java/org/apache/shenyu/protocol/tcp/connection/DefaultConnectionConfigProvider.java
b/shenyu-protocol/shenyu-protocol-tcp/src/main/java/org/apache/shenyu/protocol/tcp/connection/DefaultConnectionConfigProvider.java
index d126ac086e..2e597276f5 100644
---
a/shenyu-protocol/shenyu-protocol-tcp/src/main/java/org/apache/shenyu/protocol/tcp/connection/DefaultConnectionConfigProvider.java
+++
b/shenyu-protocol/shenyu-protocol-tcp/src/main/java/org/apache/shenyu/protocol/tcp/connection/DefaultConnectionConfigProvider.java
@@ -20,6 +20,7 @@ package org.apache.shenyu.protocol.tcp.connection;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.shenyu.common.exception.ShenyuException;
import org.apache.shenyu.common.utils.JsonUtils;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
import org.apache.shenyu.loadbalancer.entity.Upstream;
import org.apache.shenyu.loadbalancer.factory.LoadBalancerFactory;
import org.apache.shenyu.protocol.tcp.UpstreamProvider;
@@ -62,7 +63,9 @@ public class DefaultConnectionConfigProvider implements
ClientConnectionConfigPr
if (CollectionUtils.isEmpty(upstreamList)) {
throw new ShenyuException("shenyu TcpProxy don't have any
upstream");
}
- Upstream upstream = LoadBalancerFactory.selector(upstreamList,
loadBalanceAlgorithm, ip);
+ LoadBalanceData data = new LoadBalanceData();
+ data.setIp(ip);
+ Upstream upstream = LoadBalancerFactory.selector(upstreamList,
loadBalanceAlgorithm, data);
return cover(upstream);
}
diff --git
a/shenyu-sdk/shenyu-sdk-core/src/main/java/org/apache/shenyu/sdk/core/client/AbstractShenyuSdkClient.java
b/shenyu-sdk/shenyu-sdk-core/src/main/java/org/apache/shenyu/sdk/core/client/AbstractShenyuSdkClient.java
index f044d28f60..102eeefdfb 100644
---
a/shenyu-sdk/shenyu-sdk-core/src/main/java/org/apache/shenyu/sdk/core/client/AbstractShenyuSdkClient.java
+++
b/shenyu-sdk/shenyu-sdk-core/src/main/java/org/apache/shenyu/sdk/core/client/AbstractShenyuSdkClient.java
@@ -22,6 +22,7 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.shenyu.common.constant.Constants;
import org.apache.shenyu.common.exception.ShenyuException;
import org.apache.shenyu.common.utils.UriUtils;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
import org.apache.shenyu.loadbalancer.entity.Upstream;
import org.apache.shenyu.loadbalancer.factory.LoadBalancerFactory;
import org.apache.shenyu.registry.api.ShenyuInstanceRegisterRepository;
@@ -169,7 +170,10 @@ public abstract class AbstractShenyuSdkClient implements
ShenyuSdkClient {
.collect(Collectors.toList());
}
// loadBalancer upstreams
- final Upstream upstream = LoadBalancerFactory.selector(upstreams,
algorithm, "");
+ LoadBalanceData data = new LoadBalanceData();
+ data.setHeaders(request.getHeaders());
+ data.setHttpMethod(request.getHttpMethod().name());
+ final Upstream upstream = LoadBalancerFactory.selector(upstreams,
algorithm, data);
return replaceUrl(upstream.getUrl(), request.getUrl());
}
diff --git
a/shenyu-sdk/shenyu-sdk-feign/src/main/java/org/apache/shenyu/sdk/feign/ShenyuDiscoveryClient.java
b/shenyu-sdk/shenyu-sdk-feign/src/main/java/org/apache/shenyu/sdk/feign/ShenyuDiscoveryClient.java
index af4b79fafb..894888e3eb 100644
---
a/shenyu-sdk/shenyu-sdk-feign/src/main/java/org/apache/shenyu/sdk/feign/ShenyuDiscoveryClient.java
+++
b/shenyu-sdk/shenyu-sdk-feign/src/main/java/org/apache/shenyu/sdk/feign/ShenyuDiscoveryClient.java
@@ -17,18 +17,13 @@
package org.apache.shenyu.sdk.feign;
-import java.net.URI;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Objects;
-import java.util.Properties;
-import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.shenyu.common.constant.Constants;
import org.apache.shenyu.common.enums.HttpSchemeEnum;
import org.apache.shenyu.common.exception.ShenyuException;
import org.apache.shenyu.common.utils.UriUtils;
+import org.apache.shenyu.loadbalancer.entity.LoadBalanceData;
import org.apache.shenyu.loadbalancer.entity.Upstream;
import org.apache.shenyu.loadbalancer.factory.LoadBalancerFactory;
import org.apache.shenyu.registry.api.ShenyuInstanceRegisterRepository;
@@ -39,6 +34,13 @@ import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.stream.Collectors;
+
public class ShenyuDiscoveryClient {
private static final Logger LOG =
LoggerFactory.getLogger(ShenyuDiscoveryClient.class);
@@ -92,7 +94,7 @@ public class ShenyuDiscoveryClient {
}
Upstream upstream = upstreams.get(0);
if (CollectionUtils.isNotEmpty(upstreams) && upstreams.size() > 1) {
- upstream = LoadBalancerFactory.selector(upstreams, algorithm, "");
+ upstream = LoadBalancerFactory.selector(upstreams, algorithm, new
LoadBalanceData());
}
final URI uri = UriUtils.createUri(upstream.getUrl());