[3.3]Use spotless to format the code (#13322)

* Use spotless to format the code

Signed-off-by: crazyhzm <crazyhzm@gmail.com>

* Use spotless to format the code

Signed-off-by: crazyhzm <crazyhzm@gmail.com>

* Use spotless to format the code

Signed-off-by: crazyhzm <crazyhzm@gmail.com>

* degrade dubbo version

Signed-off-by: crazyhzm <crazyhzm@gmail.com>

* degrade dubbo version

Signed-off-by: crazyhzm <crazyhzm@gmail.com>

* revert degrade dubbo version

Signed-off-by: crazyhzm <crazyhzm@gmail.com>

* Fix ut

Signed-off-by: crazyhzm <crazyhzm@gmail.com>

---------

Signed-off-by: crazyhzm <crazyhzm@gmail.com>
This commit is contained in:
huazhongming 2023-11-07 15:41:45 +08:00 committed by GitHub
parent 88deb9be3d
commit d979b211ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3497 changed files with 57977 additions and 54188 deletions

View File

@ -1,3 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@ -14,110 +15,109 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-parent</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>dubbo-cluster</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>The cluster module of dubbo project</description>
<properties>
<skip_maven_deploy>false</skip_maven_deploy>
<nashorn-core.version>15.4</nashorn-core.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-api</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-injvm</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-serialization-hessian2</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-serialization-fastjson2</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-test-check</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metrics-registry</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metrics-default</artifactId>
<version>${project.parent.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-integration-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-parent</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>dubbo-cluster</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>The cluster module of dubbo project</description>
<properties>
<skip_maven_deploy>false</skip_maven_deploy>
<nashorn-core.version>15.4</nashorn-core.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-api</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-injvm</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-serialization-hessian2</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-serialization-fastjson2</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-test-check</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metrics-registry</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metrics-default</artifactId>
<version>${project.parent.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-integration-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<!--
<profiles>
<!--
https://github.com/openjdk/nashorn
Nashorn used to be part of the JDK until Java 14.
This project provides a standalone version of Nashorn suitable for use with Java 11 and later.
-->
<profile>
<id>nashorn-jdk11</id>
<activation>
<jdk>[11,)</jdk>
</activation>
<dependencies>
<dependency>
<groupId>org.openjdk.nashorn</groupId>
<artifactId>nashorn-core</artifactId>
<version>${nashorn-core.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</profile>
</profiles>
<profile>
<id>nashorn-jdk11</id>
<activation>
<jdk>[11,)</jdk>
</activation>
<dependencies>
<dependency>
<groupId>org.openjdk.nashorn</groupId>
<artifactId>nashorn-core</artifactId>
<version>${nashorn-core.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</profile>
</profiles>
</project>

View File

@ -35,8 +35,5 @@ public interface AddressListener {
*/
List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
default void destroy(URL consumerUrl, Directory registryDirectory) {
}
default void destroy(URL consumerUrl, Directory registryDirectory) {}
}

View File

@ -55,6 +55,8 @@ public interface Cluster {
if (StringUtils.isEmpty(name)) {
name = Cluster.DEFAULT;
}
return ScopeModelUtil.getApplicationModel(scopeModel).getExtensionLoader(Cluster.class).getExtension(name, wrap);
return ScopeModelUtil.getApplicationModel(scopeModel)
.getExtensionLoader(Cluster.class)
.getExtension(name, wrap);
}
}

View File

@ -38,6 +38,5 @@ public class ClusterScopeModelInitializer implements ScopeModelInitializer {
}
@Override
public void initializeModuleModel(ModuleModel moduleModel) {
}
public void initializeModuleModel(ModuleModel moduleModel) {}
}

View File

@ -51,7 +51,6 @@ public interface Configurator extends Comparable<Configurator> {
*/
URL configure(URL url);
/**
* Convert override urls to map for use when re-refer. Send all rules every time, the urls will be reassembled and
* calculated
@ -73,7 +72,9 @@ public interface Configurator extends Comparable<Configurator> {
return Optional.empty();
}
ConfiguratorFactory configuratorFactory = urls.get(0).getOrDefaultApplicationModel().getExtensionLoader(ConfiguratorFactory.class)
ConfiguratorFactory configuratorFactory = urls.get(0)
.getOrDefaultApplicationModel()
.getExtensionLoader(ConfiguratorFactory.class)
.getAdaptiveExtension();
List<Configurator> configurators = new ArrayList<>(urls.size());
@ -83,7 +84,8 @@ public interface Configurator extends Comparable<Configurator> {
break;
}
Map<String, String> override = new HashMap<>(url.getParameters());
//The anyhost parameter of override may be added automatically, it can't change the judgement of changing url
// The anyhost parameter of override may be added automatically, it can't change the judgement of changing
// url
override.remove(ANYHOST_KEY);
if (CollectionUtils.isEmptyMap(override)) {
continue;

View File

@ -36,5 +36,4 @@ public interface ConfiguratorFactory {
*/
@Adaptive(CommonConstants.PROTOCOL_KEY)
Configurator getConfigurator(URL url);
}

View File

@ -100,7 +100,6 @@ public interface Constants {
String OVERRIDE_PROVIDERS_KEY = "providerAddresses";
/**
* key for router type, for e.g., "script"/"file", corresponding to ScriptRouterFactory.NAME, FileRouterFactory.NAME
*/

View File

@ -46,5 +46,4 @@ public interface LoadBalance {
*/
@Adaptive("loadbalance")
<T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException;
}

View File

@ -22,5 +22,4 @@ import org.apache.dubbo.common.extension.SPI;
public interface Merger<T> {
T merge(T... items);
}

View File

@ -33,7 +33,9 @@ public interface ProviderURLMergeProcessor {
*/
URL mergeUrl(URL remoteUrl, Map<String, String> localParametersMap);
default Map<String, String> mergeLocalParams(Map<String, String> localMap) { return localMap; }
default Map<String, String> mergeLocalParams(Map<String, String> localMap) {
return localMap;
}
default boolean accept(URL providerUrl, Map<String, String> localParametersMap) {
return true;

View File

@ -68,8 +68,8 @@ public interface Router extends Comparable<Router> {
* @return state with route result
* @throws RpcException
*/
default <T> RouterResult<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation,
boolean needToPrintMessage) throws RpcException {
default <T> RouterResult<Invoker<T>> route(
List<Invoker<T>> invokers, URL url, Invocation invocation, boolean needToPrintMessage) throws RpcException {
return new RouterResult<>(route(invokers, url, invocation));
}
@ -80,9 +80,7 @@ public interface Router extends Comparable<Router> {
* @param invokers invoker list
* @param <T> invoker's type
*/
default <T> void notify(List<Invoker<T>> invokers) {
}
default <T> void notify(List<Invoker<T>> invokers) {}
/**
* To decide whether this router need to execute every time an RPC comes or should only execute when addresses or
@ -109,7 +107,7 @@ public interface Router extends Comparable<Router> {
int getPriority();
default void stop() {
//do nothing by default
// do nothing by default
}
@Override

View File

@ -16,12 +16,6 @@
*/
package org.apache.dubbo.rpc.cluster;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.ConfigurationUtils;
import org.apache.dubbo.common.constants.LoggerCodeConstants;
@ -36,6 +30,12 @@ import org.apache.dubbo.rpc.cluster.router.state.StateRouterFactory;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.apache.dubbo.rpc.model.ScopeModelUtil;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;
import static org.apache.dubbo.rpc.cluster.Constants.ROUTER_KEY;
/**
@ -52,31 +52,30 @@ public class RouterChain<T> {
public static <T> RouterChain<T> buildChain(Class<T> interfaceClass, URL url) {
SingleRouterChain<T> chain1 = buildSingleChain(interfaceClass, url);
SingleRouterChain<T> chain2 = buildSingleChain(interfaceClass, url);
return new RouterChain<>(new SingleRouterChain[]{chain1, chain2});
return new RouterChain<>(new SingleRouterChain[] {chain1, chain2});
}
public static <T> SingleRouterChain<T> buildSingleChain(Class<T> interfaceClass, URL url) {
ModuleModel moduleModel = url.getOrDefaultModuleModel();
List<RouterFactory> extensionFactories = moduleModel.getExtensionLoader(RouterFactory.class)
.getActivateExtension(url, ROUTER_KEY);
List<RouterFactory> extensionFactories =
moduleModel.getExtensionLoader(RouterFactory.class).getActivateExtension(url, ROUTER_KEY);
List<Router> routers = extensionFactories.stream()
.map(factory -> factory.getRouter(url))
.sorted(Router::compareTo)
.collect(Collectors.toList());
.map(factory -> factory.getRouter(url))
.sorted(Router::compareTo)
.collect(Collectors.toList());
List<StateRouter<T>> stateRouters = moduleModel
.getExtensionLoader(StateRouterFactory.class)
.getActivateExtension(url, ROUTER_KEY)
.stream()
.map(factory -> factory.getRouter(interfaceClass, url))
.collect(Collectors.toList());
List<StateRouter<T>> stateRouters =
moduleModel.getExtensionLoader(StateRouterFactory.class).getActivateExtension(url, ROUTER_KEY).stream()
.map(factory -> factory.getRouter(interfaceClass, url))
.collect(Collectors.toList());
boolean shouldFailFast = Boolean.parseBoolean(
ConfigurationUtils.getProperty(moduleModel, Constants.SHOULD_FAIL_FAST_KEY, "true"));
boolean shouldFailFast = Boolean.parseBoolean(ConfigurationUtils.getProperty(moduleModel, Constants.SHOULD_FAIL_FAST_KEY, "true"));
RouterSnapshotSwitcher routerSnapshotSwitcher = ScopeModelUtil.getFrameworkModel(moduleModel).getBeanFactory().getBean(RouterSnapshotSwitcher.class);
RouterSnapshotSwitcher routerSnapshotSwitcher =
ScopeModelUtil.getFrameworkModel(moduleModel).getBeanFactory().getBean(RouterSnapshotSwitcher.class);
return new SingleRouterChain<>(routers, stateRouters, shouldFailFast, routerSnapshotSwitcher);
}
@ -106,9 +105,9 @@ public class RouterChain<T> {
// If `availableInvokers` is created from origin invokers => use backup chain
// If `availableInvokers` is created from newly invokers => use main chain
BitList<Invoker<T>> notifying = notifyingInvokers.get();
if (notifying != null &&
currentChain == backupChain &&
availableInvokers.getOriginList() == notifying.getOriginList()) {
if (notifying != null
&& currentChain == backupChain
&& availableInvokers.getOriginList() == notifying.getOriginList()) {
return mainChain;
}
return currentChain;
@ -140,7 +139,8 @@ public class RouterChain<T> {
}
// Refresh main chain.
// No one can request to use main chain. `currentChain` is backup chain. `route` method cannot access main chain.
// No one can request to use main chain. `currentChain` is backup chain. `route` method cannot access main
// chain.
try {
// Lock main chain to wait all invocation end
// To wait until no one is using main chain.
@ -157,26 +157,32 @@ public class RouterChain<T> {
}
// Set the reference of newly invokers to temp variable.
// Reason: The next step will switch the invokers reference in directory, so we should check the `availableInvokers`
// argument when `route`. If the current invocation use newly invokers, we should use main chain to route, and
// Reason: The next step will switch the invokers reference in directory, so we should check the
// `availableInvokers`
// argument when `route`. If the current invocation use newly invokers, we should use main chain to
// route, and
// this can prevent use newly invokers to route backup chain, which can only route origin invokers now.
notifyingInvokers.set(invokers);
// Switch the invokers reference in directory.
// Cannot switch before update main chain or after backup chain update success. Or that will cause state inconsistent.
// Cannot switch before update main chain or after backup chain update success. Or that will cause state
// inconsistent.
switchAction.run();
try {
// Lock to prevent directory continue list
// The invokers reference in directory now should be the newly one and should always use the newly one once lock released.
// The invokers reference in directory now should be the newly one and should always use the newly one once
// lock released.
lock.writeLock().lock();
// Switch to main chain. Will update backup chain later.
currentChain = mainChain;
// Clean up temp variable.
// `availableInvokers` check is useless now, because `route` method will no longer receive any `availableInvokers` related
// with the origin invokers. The getter of invokers reference in directory is locked now, and will return newly invokers
// `availableInvokers` check is useless now, because `route` method will no longer receive any
// `availableInvokers` related
// with the origin invokers. The getter of invokers reference in directory is locked now, and will return
// newly invokers
// once lock released.
notifyingInvokers.set(null);
} finally {
@ -186,7 +192,8 @@ public class RouterChain<T> {
}
// Refresh main chain.
// No one can request to use main chain. `currentChain` is main chain. `route` method cannot access backup chain.
// No one can request to use main chain. `currentChain` is main chain. `route` method cannot access backup
// chain.
try {
// Lock main chain to wait all invocation end
backupChain.getLock().writeLock().lock();

View File

@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.cluster;
import org.apache.dubbo.common.URL;
@ -26,5 +25,4 @@ import java.util.List;
public interface RuleConverter {
List<URL> convert(URL subscribeUrl, Object source);
}

View File

@ -16,13 +16,6 @@
*/
package org.apache.dubbo.rpc.cluster;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.Version;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
@ -40,6 +33,13 @@ import org.apache.dubbo.rpc.cluster.router.state.BitList;
import org.apache.dubbo.rpc.cluster.router.state.StateRouter;
import org.apache.dubbo.rpc.cluster.router.state.TailStateRouter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_FAILED_STOP;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_NO_VALID_PROVIDER;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_ERROR;
@ -79,7 +79,11 @@ public class SingleRouterChain<T> {
private final ReadWriteLock lock = new ReentrantReadWriteLock();
public SingleRouterChain(List<Router> routers, List<StateRouter<T>> stateRouters, boolean shouldFailFast, RouterSnapshotSwitcher routerSnapshotSwitcher) {
public SingleRouterChain(
List<Router> routers,
List<StateRouter<T>> stateRouters,
boolean shouldFailFast,
RouterSnapshotSwitcher routerSnapshotSwitcher) {
initWithRouters(routers);
initWithStateRouters(stateRouters);
@ -134,9 +138,12 @@ public class SingleRouterChain<T> {
public List<Invoker<T>> route(URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
if (invokers.getOriginList() != availableInvokers.getOriginList()) {
logger.error(INTERNAL_ERROR, "", "Router's invoker size: " + invokers.getOriginList().size() +
" Invocation's invoker size: " + availableInvokers.getOriginList().size(),
"Reject to route, because the invokers has changed.");
logger.error(
INTERNAL_ERROR,
"",
"Router's invoker size: " + invokers.getOriginList().size() + " Invocation's invoker size: "
+ availableInvokers.getOriginList().size(),
"Reject to route, because the invokers has changed.");
throw new IllegalStateException("reject to route, because the invokers has changed.");
}
if (RpcContext.getServiceContext().isNeedPrintRouterSnapshot()) {
@ -202,7 +209,8 @@ public class SingleRouterChain<T> {
/**
* Build each router's result
*/
public RouterSnapshotNode<T> buildRouterSnapshot(URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
public RouterSnapshotNode<T> buildRouterSnapshot(
URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
BitList<Invoker<T>> resultInvokers = availableInvokers.clone();
RouterSnapshotNode<T> parentNode = new RouterSnapshotNode<T>("Parent", resultInvokers.clone());
parentNode.setNodeOutputInvokers(resultInvokers.clone());
@ -228,7 +236,8 @@ public class SingleRouterChain<T> {
// Copy resultInvokers to a arrayList. BitList not support
List<Invoker<T>> inputInvokers = new ArrayList<>(commonRouterResult);
RouterSnapshotNode<T> currentNode = new RouterSnapshotNode<T>(router.getClass().getSimpleName(), inputInvokers);
RouterSnapshotNode<T> currentNode =
new RouterSnapshotNode<T>(router.getClass().getSimpleName(), inputInvokers);
// append to router node chain
commonRouterNode.appendNode(currentNode);
@ -268,24 +277,27 @@ public class SingleRouterChain<T> {
}
private void logRouterSnapshot(URL url, Invocation invocation, RouterSnapshotNode<T> snapshotNode) {
if (snapshotNode.getChainOutputInvokers() == null ||
snapshotNode.getChainOutputInvokers().isEmpty()) {
if (snapshotNode.getChainOutputInvokers() == null
|| snapshotNode.getChainOutputInvokers().isEmpty()) {
if (logger.isWarnEnabled()) {
String message = "No provider available after route for the service " + url.getServiceKey()
+ " from registry " + url.getAddress()
+ " on the consumer " + NetUtils.getLocalHost()
+ " using the dubbo version " + Version.getVersion() + ". Router snapshot is below: \n" + snapshotNode.toString();
+ " from registry " + url.getAddress()
+ " on the consumer " + NetUtils.getLocalHost()
+ " using the dubbo version " + Version.getVersion() + ". Router snapshot is below: \n"
+ snapshotNode.toString();
if (routerSnapshotSwitcher.isEnable()) {
routerSnapshotSwitcher.setSnapshot(message);
}
logger.warn(CLUSTER_NO_VALID_PROVIDER, "No provider available after route for the service", "", message);
logger.warn(
CLUSTER_NO_VALID_PROVIDER, "No provider available after route for the service", "", message);
}
} else {
if (logger.isInfoEnabled()) {
String message = "Router snapshot service " + url.getServiceKey()
+ " from registry " + url.getAddress()
+ " on the consumer " + NetUtils.getLocalHost()
+ " using the dubbo version " + Version.getVersion() + " is below: \n" + snapshotNode.toString();
+ " from registry " + url.getAddress()
+ " on the consumer " + NetUtils.getLocalHost()
+ " using the dubbo version " + Version.getVersion() + " is below: \n"
+ snapshotNode.toString();
if (routerSnapshotSwitcher.isEnable()) {
routerSnapshotSwitcher.setSnapshot(message);
}
@ -330,7 +342,12 @@ public class SingleRouterChain<T> {
try {
router.stop();
} catch (Exception e) {
logger.error(CLUSTER_FAILED_STOP, "route stop failed", "", "Error trying to stop router " + router.getClass(), e);
logger.error(
CLUSTER_FAILED_STOP,
"route stop failed",
"",
"Error trying to stop router " + router.getClass(),
e);
}
}
routers = Collections.emptyList();
@ -340,7 +357,12 @@ public class SingleRouterChain<T> {
try {
router.stop();
} catch (Exception e) {
logger.error(CLUSTER_FAILED_STOP, "StateRouter stop failed", "", "Error trying to stop StateRouter " + router.getClass(), e);
logger.error(
CLUSTER_FAILED_STOP,
"StateRouter stop failed",
"",
"Error trying to stop StateRouter " + router.getClass(),
e);
}
}
stateRouters = Collections.emptyList();

View File

@ -72,7 +72,10 @@ public abstract class AbstractConfigurator implements Configurator {
@Override
public URL configure(URL url) {
// If override url is not enabled or is invalid, just return.
if (!configuratorUrl.getParameter(ENABLED_KEY, true) || configuratorUrl.getHost() == null || url == null || url.getHost() == null) {
if (!configuratorUrl.getParameter(ENABLED_KEY, true)
|| configuratorUrl.getHost() == null
|| url == null
|| url.getHost() == null) {
logger.info("Cannot apply configurator rule, the rule is disabled or is invalid: \n" + configuratorUrl);
return url;
}
@ -98,7 +101,9 @@ public abstract class AbstractConfigurator implements Configurator {
@Deprecated
private URL configureDeprecated(URL url) {
// If override url has port, means it is a provider address. We want to control a specific provider with this override url, it may take effect on the specific provider instance or on consumers holding this provider instance.
// If override url has port, means it is a provider address. We want to control a specific provider with this
// override url, it may take effect on the specific provider instance or on consumers holding this provider
// instance.
if (configuratorUrl.getPort() != 0) {
if (url.getPort() == configuratorUrl.getPort()) {
return configureIfMatch(url.getHost(), url);
@ -131,7 +136,8 @@ public abstract class AbstractConfigurator implements Configurator {
if (matcher.isMatch(host, url)) {
return doConfigure(url, configuratorUrl.removeParameters(conditionKeys));
} else {
logger.debug("Cannot apply configurator rule, param mismatch, current params are " + url + ", params in rule is " + matcher);
logger.debug("Cannot apply configurator rule, param mismatch, current params are " + url
+ ", params in rule is " + matcher);
}
} else {
return doConfigure(url, configuratorUrl.removeParameters(conditionKeys));
@ -141,7 +147,8 @@ public abstract class AbstractConfigurator implements Configurator {
}
}
} else {
logger.debug("Cannot apply configurator rule, host mismatch, current host is " + host + ", host in rule is " + configuratorUrl.getHost());
logger.debug("Cannot apply configurator rule, host mismatch, current host is " + host + ", host in rule is "
+ configuratorUrl.getHost());
}
return url;
}
@ -159,15 +166,16 @@ public abstract class AbstractConfigurator implements Configurator {
String[] providerAddresses = providers.split(CommonConstants.COMMA_SEPARATOR);
for (String address : providerAddresses) {
if (address.equals(url.getAddress())
|| address.equals(ANYHOST_VALUE)
|| address.equals(ANYHOST_VALUE + CommonConstants.GROUP_CHAR_SEPARATOR + ANY_VALUE)
|| address.equals(ANYHOST_VALUE + CommonConstants.GROUP_CHAR_SEPARATOR + url.getPort())
|| address.equals(url.getHost())) {
|| address.equals(ANYHOST_VALUE)
|| address.equals(ANYHOST_VALUE + CommonConstants.GROUP_CHAR_SEPARATOR + ANY_VALUE)
|| address.equals(ANYHOST_VALUE + CommonConstants.GROUP_CHAR_SEPARATOR + url.getPort())
|| address.equals(url.getHost())) {
match = true;
}
}
if (!match) {
logger.debug("Cannot apply configurator rule, provider address mismatch, current address " + url.getAddress() + ", address in rule is " + providers);
logger.debug("Cannot apply configurator rule, provider address mismatch, current address "
+ url.getAddress() + ", address in rule is " + providers);
return false;
}
}
@ -175,17 +183,18 @@ public abstract class AbstractConfigurator implements Configurator {
String configApplication = configuratorUrl.getApplication(configuratorUrl.getUsername());
String currentApplication = url.getApplication(url.getUsername());
if (configApplication != null
&& !ANY_VALUE.equals(configApplication)
&& !configApplication.equals(currentApplication)) {
logger.debug("Cannot apply configurator rule, application name mismatch, current application is " + currentApplication + ", application in rule is " + configApplication);
&& !ANY_VALUE.equals(configApplication)
&& !configApplication.equals(currentApplication)) {
logger.debug("Cannot apply configurator rule, application name mismatch, current application is "
+ currentApplication + ", application in rule is " + configApplication);
return false;
}
String configServiceKey = configuratorUrl.getServiceKey();
String currentServiceKey = url.getServiceKey();
if (!ANY_VALUE.equals(configServiceKey)
&& !configServiceKey.equals(currentServiceKey)) {
logger.debug("Cannot apply configurator rule, service mismatch, current service is " + currentServiceKey + ", service in rule is " + configServiceKey);
if (!ANY_VALUE.equals(configServiceKey) && !configServiceKey.equals(currentServiceKey)) {
logger.debug("Cannot apply configurator rule, service mismatch, current service is " + currentServiceKey
+ ", service in rule is " + configServiceKey);
return false;
}
@ -202,8 +211,9 @@ public abstract class AbstractConfigurator implements Configurator {
if (startWithTilde) {
conditionKeys.add(key);
}
if (value != null && !ANY_VALUE.equals(value)
&& !value.equals(url.getParameter(startWithTilde ? key.substring(1) : key))) {
if (value != null
&& !ANY_VALUE.equals(value)
&& !value.equals(url.getParameter(startWithTilde ? key.substring(1) : key))) {
result = false;
break;
}
@ -233,5 +243,4 @@ public abstract class AbstractConfigurator implements Configurator {
}
protected abstract URL doConfigure(URL currentUrl, URL configUrl);
}

View File

@ -32,5 +32,4 @@ public class AbsentConfigurator extends AbstractConfigurator {
public URL doConfigure(URL currentUrl, URL configUrl) {
return currentUrl.addParametersIfAbsent(configUrl.getParameters());
}
}

View File

@ -30,5 +30,4 @@ public class AbsentConfiguratorFactory implements ConfiguratorFactory {
public Configurator getConfigurator(URL url) {
return new AbsentConfigurator(url);
}
}

View File

@ -36,5 +36,4 @@ public class OverrideConfigurator extends AbstractConfigurator {
logger.info("Start overriding url " + currentUrl + " with override url " + configUrl);
return currentUrl.addParameters(configUrl.getParameters());
}
}

View File

@ -30,5 +30,4 @@ public class OverrideConfiguratorFactory implements ConfiguratorFactory {
public Configurator getConfigurator(URL url) {
return new OverrideConfigurator(url);
}
}

View File

@ -23,14 +23,14 @@ import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.rpc.cluster.configurator.parser.model.ConfigItem;
import org.apache.dubbo.rpc.cluster.configurator.parser.model.ConfiguratorConfig;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER;
import static org.apache.dubbo.common.constants.RegistryConstants.APP_DYNAMIC_CONFIGURATORS_CATEGORY;
@ -104,7 +104,12 @@ public class ConfigParser {
if (CollectionUtils.isNotEmpty(apps)) {
apps.forEach(app -> {
StringBuilder tmpUrlBuilder = new StringBuilder(urlBuilder);
urls.add(appendMatchCondition(URL.valueOf(tmpUrlBuilder.append("&application=").append(app).toString()), item));
urls.add(appendMatchCondition(
URL.valueOf(tmpUrlBuilder
.append("&application=")
.append(app)
.toString()),
item));
});
} else {
urls.add(appendMatchCondition(URL.valueOf(urlBuilder.toString()), item));
@ -155,8 +160,8 @@ public class ConfigParser {
}
Map<String, String> parameters = item.getParameters();
if (CollectionUtils.isEmptyMap(parameters)) {
throw new IllegalStateException("Invalid configurator rule, please specify at least one parameter " +
"you want to change in the rule.");
throw new IllegalStateException("Invalid configurator rule, please specify at least one parameter "
+ "you want to change in the rule.");
}
parameters.forEach((k, v) -> {

View File

@ -101,12 +101,11 @@ public class ConditionMatch {
@Override
public String toString() {
return "ConditionMatch{" +
"address='" + address + '\'' +
"providerAddress='" + providerAddress + '\'' +
", service='" + service + '\'' +
", app='" + app + '\'' +
", param='" + param + '\'' +
'}';
return "ConditionMatch{" + "address='"
+ address + '\'' + "providerAddress='"
+ providerAddress + '\'' + ", service='"
+ service + '\'' + ", app='"
+ app + '\'' + ", param='"
+ param + '\'' + '}';
}
}

View File

@ -68,32 +68,33 @@ public class ConfigItem {
Object addresses = map.get(ADDRESSES_KEY);
if (addresses != null && List.class.isAssignableFrom(addresses.getClass())) {
configItem.setAddresses(((List<Object>) addresses).stream()
.map(String::valueOf).collect(Collectors.toList()));
configItem.setAddresses(
((List<Object>) addresses).stream().map(String::valueOf).collect(Collectors.toList()));
}
Object providerAddresses = map.get(PROVIDER_ADDRESSES_KEY);
if (providerAddresses != null && List.class.isAssignableFrom(providerAddresses.getClass())) {
configItem.setProviderAddresses(((List<Object>) providerAddresses).stream()
.map(String::valueOf).collect(Collectors.toList()));
configItem.setProviderAddresses(((List<Object>) providerAddresses)
.stream().map(String::valueOf).collect(Collectors.toList()));
}
Object services = map.get(SERVICES_KEY);
if (services != null && List.class.isAssignableFrom(services.getClass())) {
configItem.setServices(((List<Object>) services).stream()
.map(String::valueOf).collect(Collectors.toList()));
configItem.setServices(
((List<Object>) services).stream().map(String::valueOf).collect(Collectors.toList()));
}
Object applications = map.get(APPLICATIONS_KEY);
if (applications != null && List.class.isAssignableFrom(applications.getClass())) {
configItem.setApplications(((List<Object>) applications).stream()
.map(String::valueOf).collect(Collectors.toList()));
configItem.setApplications(
((List<Object>) applications).stream().map(String::valueOf).collect(Collectors.toList()));
}
Object parameters = map.get(PARAMETERS_KEY);
if (parameters != null && Map.class.isAssignableFrom(parameters.getClass())) {
configItem.setParameters(((Map<String, Object>) parameters).entrySet()
.stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().toString())));
configItem.setParameters(((Map<String, Object>) parameters)
.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue()
.toString())));
}
try {
@ -102,7 +103,12 @@ public class ConfigItem {
configItem.setMatch(PojoUtils.mapToPojo((Map<String, Object>) match, ConditionMatch.class));
}
} catch (Throwable t) {
logger.error(CLUSTER_FAILED_RECEIVE_RULE, " Failed to parse dynamic configuration rule", String.valueOf(map.get(MATCH_KEY)), "Error occurred when parsing rule component.", t);
logger.error(
CLUSTER_FAILED_RECEIVE_RULE,
" Failed to parse dynamic configuration rule",
String.valueOf(map.get(MATCH_KEY)),
"Error occurred when parsing rule component.",
t);
}
configItem.setSide((String) map.get(SIDE_KEY));

View File

@ -52,8 +52,8 @@ public class ConfiguratorConfig {
Object configs = map.get(CONFIGS_KEY);
if (configs != null && List.class.isAssignableFrom(configs.getClass())) {
configuratorConfig.setConfigs(((List<Map<String, Object>>) configs).stream()
.map(ConfigItem::parseFromMap).collect(Collectors.toList()));
configuratorConfig.setConfigs(((List<Map<String, Object>>) configs)
.stream().map(ConfigItem::parseFromMap).collect(Collectors.toList()));
}
return configuratorConfig;

View File

@ -50,9 +50,6 @@ public class ParamMatch {
@Override
public String toString() {
return "ParamMatch{" +
"key='" + key + '\'' +
", value='" + value + '\'' +
'}';
return "ParamMatch{" + "key='" + key + '\'' + ", value='" + value + '\'' + '}';
}
}

View File

@ -160,18 +160,20 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
// remove some local only parameters
applicationModel = url.getOrDefaultApplicationModel();
this.queryMap = applicationModel.getBeanFactory().getBean(ClusterUtils.class).mergeLocalParams(queryMap);
this.queryMap =
applicationModel.getBeanFactory().getBean(ClusterUtils.class).mergeLocalParams(queryMap);
if (consumerUrl == null) {
String host = isNotEmpty(queryMap.get(REGISTER_IP_KEY)) ? queryMap.get(REGISTER_IP_KEY) : this.url.getHost();
String host =
isNotEmpty(queryMap.get(REGISTER_IP_KEY)) ? queryMap.get(REGISTER_IP_KEY) : this.url.getHost();
String path = isNotEmpty(queryMap.get(PATH_KEY)) ? queryMap.get(PATH_KEY) : queryMap.get(INTERFACE_KEY);
String consumedProtocol = isNotEmpty(queryMap.get(PROTOCOL_KEY)) ? queryMap.get(PROTOCOL_KEY) : CONSUMER;
URL consumerUrlFrom = this.url
.setHost(host)
.setPort(0)
.setProtocol(consumedProtocol)
.setPath(path);
.setHost(host)
.setPort(0)
.setProtocol(consumedProtocol)
.setPath(path);
if (isUrlFromRegistry) {
// reserve parameters if url is already a consumer url
consumerUrlFrom = consumerUrlFrom.clearParameters();
@ -179,19 +181,23 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
this.consumerUrl = consumerUrlFrom.addParameters(queryMap);
}
this.connectivityExecutor = applicationModel.getFrameworkModel().getBeanFactory()
.getBean(FrameworkExecutorRepository.class).getConnectivityScheduledExecutor();
this.connectivityExecutor = applicationModel
.getFrameworkModel()
.getBeanFactory()
.getBean(FrameworkExecutorRepository.class)
.getConnectivityScheduledExecutor();
Configuration configuration = ConfigurationUtils.getGlobalConfiguration(url.getOrDefaultModuleModel());
this.reconnectTaskTryCount = configuration.getInt(RECONNECT_TASK_TRY_COUNT, DEFAULT_RECONNECT_TASK_TRY_COUNT);
this.reconnectTaskPeriod = configuration.getInt(RECONNECT_TASK_PERIOD, DEFAULT_RECONNECT_TASK_PERIOD);
setRouterChain(routerChain);
}
@Override
public List<Invoker<T>> list(Invocation invocation) throws RpcException {
if (destroyed) {
throw new RpcException("Directory of type " + this.getClass().getSimpleName() + " already destroyed for service " + getConsumerUrl().getServiceKey() + " from registry " + getUrl());
throw new RpcException(
"Directory of type " + this.getClass().getSimpleName() + " already destroyed for service "
+ getConsumerUrl().getServiceKey() + " from registry " + getUrl());
}
BitList<Invoker<T>> availableInvokers;
@ -222,12 +228,16 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
if (routedResult.isEmpty()) {
// 2-2 - No provider available.
logger.warn(CLUSTER_NO_VALID_PROVIDER, "provider server or registry center crashed", "",
"No provider available after connectivity filter for the service " + getConsumerUrl().getServiceKey()
+ " All routed invokers' size: " + routedResult.size()
+ " from registry " + this
+ " on the consumer " + NetUtils.getLocalHost()
+ " using the dubbo version " + Version.getVersion() + ".");
logger.warn(
CLUSTER_NO_VALID_PROVIDER,
"provider server or registry center crashed",
"",
"No provider available after connectivity filter for the service "
+ getConsumerUrl().getServiceKey()
+ " All routed invokers' size: " + routedResult.size()
+ " from registry " + this
+ " on the consumer " + NetUtils.getLocalHost()
+ " using the dubbo version " + Version.getVersion() + ".");
}
return Collections.unmodifiableList(routedResult);
} finally {
@ -290,68 +300,78 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
// 3. try start check connectivity task
checkConnectivity();
logger.info("The invoker " + invoker.getUrl() + " has been added to invalidate list due to connectivity problem. " +
"Will trying to reconnect to it in the background.");
logger.info("The invoker " + invoker.getUrl()
+ " has been added to invalidate list due to connectivity problem. "
+ "Will trying to reconnect to it in the background.");
}
}
public void checkConnectivity() {
// try to submit task, to ensure there is only one task at most for each directory
if (checkConnectivityPermit.tryAcquire()) {
this.connectivityCheckFuture = connectivityExecutor.schedule(() -> {
try {
if (isDestroyed()) {
return;
}
RpcContext.getServiceContext().setConsumerUrl(getConsumerUrl());
List<Invoker<T>> needDeleteList = new ArrayList<>();
List<Invoker<T>> invokersToTry = new ArrayList<>();
// 1. pick invokers from invokersToReconnect
// limit max reconnectTaskTryCount, prevent this task hang up all the connectivityExecutor for long time
if (invokersToReconnect.size() < reconnectTaskTryCount) {
invokersToTry.addAll(invokersToReconnect);
} else {
for (int i = 0; i < reconnectTaskTryCount; i++) {
Invoker<T> tInvoker = invokersToReconnect.get(ThreadLocalRandom.current().nextInt(invokersToReconnect.size()));
if (!invokersToTry.contains(tInvoker)) {
// ignore if is selected, invokersToTry's size is always smaller than reconnectTaskTryCount + 1
invokersToTry.add(tInvoker);
this.connectivityCheckFuture = connectivityExecutor.schedule(
() -> {
try {
if (isDestroyed()) {
return;
}
}
}
RpcContext.getServiceContext().setConsumerUrl(getConsumerUrl());
List<Invoker<T>> needDeleteList = new ArrayList<>();
List<Invoker<T>> invokersToTry = new ArrayList<>();
// 2. try to check the invoker's status
for (Invoker<T> invoker : invokersToTry) {
if (invokers.contains(invoker)) {
if (invoker.isAvailable()) {
needDeleteList.add(invoker);
// 1. pick invokers from invokersToReconnect
// limit max reconnectTaskTryCount, prevent this task hang up all the connectivityExecutor
// for long time
if (invokersToReconnect.size() < reconnectTaskTryCount) {
invokersToTry.addAll(invokersToReconnect);
} else {
for (int i = 0; i < reconnectTaskTryCount; i++) {
Invoker<T> tInvoker = invokersToReconnect.get(
ThreadLocalRandom.current().nextInt(invokersToReconnect.size()));
if (!invokersToTry.contains(tInvoker)) {
// ignore if is selected, invokersToTry's size is always smaller than
// reconnectTaskTryCount + 1
invokersToTry.add(tInvoker);
}
}
}
} else {
needDeleteList.add(invoker);
}
}
// 3. recover valid invoker
for (Invoker<T> tInvoker : needDeleteList) {
if (invokers.contains(tInvoker)) {
addValidInvoker(tInvoker);
logger.info("Recover service address: " + tInvoker.getUrl() + " from invalid list.");
}
invokersToReconnect.remove(tInvoker);
}
} finally {
checkConnectivityPermit.release();
}
// 2. try to check the invoker's status
for (Invoker<T> invoker : invokersToTry) {
if (invokers.contains(invoker)) {
if (invoker.isAvailable()) {
needDeleteList.add(invoker);
}
} else {
needDeleteList.add(invoker);
}
}
// 4. submit new task if it has more to recover
if (!invokersToReconnect.isEmpty()) {
checkConnectivity();
}
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
}, reconnectTaskPeriod, TimeUnit.MILLISECONDS);
// 3. recover valid invoker
for (Invoker<T> tInvoker : needDeleteList) {
if (invokers.contains(tInvoker)) {
addValidInvoker(tInvoker);
logger.info(
"Recover service address: " + tInvoker.getUrl() + " from invalid list.");
}
invokersToReconnect.remove(tInvoker);
}
} finally {
checkConnectivityPermit.release();
}
// 4. submit new task if it has more to recover
if (!invokersToReconnect.isEmpty()) {
checkConnectivity();
}
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(
applicationModel, getSummary(), getDirectoryMeta()));
},
reconnectTaskPeriod,
TimeUnit.MILLISECONDS);
}
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
MetricsEventBus.publish(
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
}
/**
@ -365,7 +385,8 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
if (invokersInitialized) {
refreshInvokerInternal();
}
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
MetricsEventBus.publish(
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
}
protected Map<String, String> getDirectoryMeta() {
@ -398,7 +419,8 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
removeValidInvoker(invoker);
logger.info("Disable service address: " + invoker.getUrl() + ".");
}
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
MetricsEventBus.publish(
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
}
@Override
@ -411,19 +433,24 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
}
}
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
MetricsEventBus.publish(
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
}
protected final void refreshRouter(BitList<Invoker<T>> newlyInvokers, Runnable switchAction) {
try {
routerChain.setInvokers(newlyInvokers.clone(), switchAction);
} catch (Throwable t) {
logger.error(LoggerCodeConstants.INTERNAL_ERROR, "", "", "Error occurred when refreshing router chain. " +
"The addresses from notification: " +
newlyInvokers.stream()
.map(Invoker::getUrl)
.map(URL::getAddress)
.collect(Collectors.joining(", ")), t);
logger.error(
LoggerCodeConstants.INTERNAL_ERROR,
"",
"",
"Error occurred when refreshing router chain. " + "The addresses from notification: "
+ newlyInvokers.stream()
.map(Invoker::getUrl)
.map(URL::getAddress)
.collect(Collectors.joining(", ")),
t);
throw t;
}
@ -468,7 +495,8 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
refreshInvokerInternal();
this.invokersInitialized = true;
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
MetricsEventBus.publish(
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
}
protected void destroyInvokers() {
@ -483,7 +511,8 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
synchronized (this.validInvokers) {
result = this.validInvokers.add(invoker);
}
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
MetricsEventBus.publish(
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
return result;
}
@ -492,12 +521,14 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
synchronized (this.validInvokers) {
result = this.validInvokers.remove(invoker);
}
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
MetricsEventBus.publish(
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
return result;
}
protected abstract List<Invoker<T>> doList(SingleRouterChain<T> singleRouterChain,
BitList<Invoker<T>> invokers, Invocation invocation) throws RpcException;
protected abstract List<Invoker<T>> doList(
SingleRouterChain<T> singleRouterChain, BitList<Invoker<T>> invokers, Invocation invocation)
throws RpcException;
protected String joinValidInvokerAddresses() {
BitList<Invoker<T>> validInvokers = getValidInvokers().clone();
@ -505,10 +536,10 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
return "empty";
}
return validInvokers.stream()
.limit(5)
.map(Invoker::getUrl)
.map(URL::getAddress)
.collect(Collectors.joining(","));
.limit(5)
.map(Invoker::getUrl)
.map(URL::getAddress)
.collect(Collectors.joining(","));
}
private Map<MetricsKey, Map<String, Integer>> getSummary() {
@ -527,25 +558,27 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
@Override
public String toString() {
return "Directory(" +
"invokers: " + invokers.size() + "[" +
invokers.stream()
.map(Invoker::getUrl)
.map(URL::getAddress)
.limit(3)
.collect(Collectors.joining(", ")) + "]" +
", validInvokers: " + validInvokers.size() + "[" +
validInvokers.stream()
.map(Invoker::getUrl)
.map(URL::getAddress)
.limit(3)
.collect(Collectors.joining(", ")) + "]" +
", invokersToReconnect: " + invokersToReconnect.size() + "[" +
invokersToReconnect.stream()
.map(Invoker::getUrl)
.map(URL::getAddress)
.limit(3)
.collect(Collectors.joining(", ")) + "]" +
')';
return "Directory(" + "invokers: "
+ invokers.size() + "["
+ invokers.stream()
.map(Invoker::getUrl)
.map(URL::getAddress)
.limit(3)
.collect(Collectors.joining(", "))
+ "]" + ", validInvokers: "
+ validInvokers.size() + "["
+ validInvokers.stream()
.map(Invoker::getUrl)
.map(URL::getAddress)
.limit(3)
.collect(Collectors.joining(", "))
+ "]" + ", invokersToReconnect: "
+ invokersToReconnect.size() + "["
+ invokersToReconnect.stream()
.map(Invoker::getUrl)
.map(URL::getAddress)
.limit(3)
.collect(Collectors.joining(", "))
+ "]" + ')';
}
}

View File

@ -55,7 +55,12 @@ public class StaticDirectory<T> extends AbstractDirectory<T> {
}
public StaticDirectory(URL url, List<Invoker<T>> invokers, RouterChain<T> routerChain) {
super(url == null && CollectionUtils.isNotEmpty(invokers) ? invokers.get(0).getUrl() : url, routerChain, false);
super(
url == null && CollectionUtils.isNotEmpty(invokers)
? invokers.get(0).getUrl()
: url,
routerChain,
false);
if (CollectionUtils.isEmpty(invokers)) {
throw new IllegalArgumentException("invokers == null");
}
@ -101,28 +106,34 @@ public class StaticDirectory<T> extends AbstractDirectory<T> {
public void buildRouterChain() {
RouterChain<T> routerChain = RouterChain.buildChain(getInterface(), getUrl());
routerChain.setInvokers(getInvokers(), () -> {
});
routerChain.setInvokers(getInvokers(), () -> {});
this.setRouterChain(routerChain);
}
public void notify(List<Invoker<T>> invokers) {
BitList<Invoker<T>> bitList = new BitList<>(invokers);
if (routerChain != null) {
refreshRouter(bitList.clone(), () -> this.setInvokers(bitList));
refreshRouter(bitList.clone(), () -> this.setInvokers(bitList));
} else {
this.setInvokers(bitList);
}
}
@Override
protected List<Invoker<T>> doList(SingleRouterChain<T> singleRouterChain, BitList<Invoker<T>> invokers, Invocation invocation) throws RpcException {
protected List<Invoker<T>> doList(
SingleRouterChain<T> singleRouterChain, BitList<Invoker<T>> invokers, Invocation invocation)
throws RpcException {
if (singleRouterChain != null) {
try {
List<Invoker<T>> finalInvokers = singleRouterChain.route(getConsumerUrl(), invokers, invocation);
return finalInvokers == null ? BitList.emptyList() : finalInvokers;
} catch (Throwable t) {
logger.error(CLUSTER_FAILED_SITE_SELECTION, "Failed to execute router", "", "Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t);
logger.error(
CLUSTER_FAILED_SITE_SELECTION,
"Failed to execute router",
"",
"Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(),
t);
return BitList.emptyList();
}
}

View File

@ -47,12 +47,14 @@ public class DefaultFilterChainBuilder implements FilterChainBuilder {
List<ModuleModel> moduleModels = getModuleModelsFromUrl(url);
List<Filter> filters;
if (moduleModels != null && moduleModels.size() == 1) {
filters = ScopeModelUtil.getExtensionLoader(Filter.class, moduleModels.get(0)).getActivateExtension(url, key, group);
filters = ScopeModelUtil.getExtensionLoader(Filter.class, moduleModels.get(0))
.getActivateExtension(url, key, group);
} else if (moduleModels != null && moduleModels.size() > 1) {
filters = new ArrayList<>();
List<ExtensionDirector> directors = new ArrayList<>();
for (ModuleModel moduleModel : moduleModels) {
List<Filter> tempFilters = ScopeModelUtil.getExtensionLoader(Filter.class, moduleModel).getActivateExtension(url, key, group);
List<Filter> tempFilters = ScopeModelUtil.getExtensionLoader(Filter.class, moduleModel)
.getActivateExtension(url, key, group);
filters.addAll(tempFilters);
directors.add(moduleModel.getExtensionDirector());
}
@ -62,7 +64,6 @@ public class DefaultFilterChainBuilder implements FilterChainBuilder {
filters = ScopeModelUtil.getExtensionLoader(Filter.class, null).getActivateExtension(url, key, group);
}
if (!CollectionUtils.isEmpty(filters)) {
for (int i = filters.size() - 1; i >= 0; i--) {
final Filter filter = filters.get(i);
@ -79,25 +80,29 @@ public class DefaultFilterChainBuilder implements FilterChainBuilder {
* build consumer cluster filter chain
*/
@Override
public <T> ClusterInvoker<T> buildClusterInvokerChain(final ClusterInvoker<T> originalInvoker, String key, String group) {
public <T> ClusterInvoker<T> buildClusterInvokerChain(
final ClusterInvoker<T> originalInvoker, String key, String group) {
ClusterInvoker<T> last = originalInvoker;
URL url = originalInvoker.getUrl();
List<ModuleModel> moduleModels = getModuleModelsFromUrl(url);
List<ClusterFilter> filters;
if (moduleModels != null && moduleModels.size() == 1) {
filters = ScopeModelUtil.getExtensionLoader(ClusterFilter.class, moduleModels.get(0)).getActivateExtension(url, key, group);
filters = ScopeModelUtil.getExtensionLoader(ClusterFilter.class, moduleModels.get(0))
.getActivateExtension(url, key, group);
} else if (moduleModels != null && moduleModels.size() > 1) {
filters = new ArrayList<>();
List<ExtensionDirector> directors = new ArrayList<>();
for (ModuleModel moduleModel : moduleModels) {
List<ClusterFilter> tempFilters = ScopeModelUtil.getExtensionLoader(ClusterFilter.class, moduleModel).getActivateExtension(url, key, group);
List<ClusterFilter> tempFilters = ScopeModelUtil.getExtensionLoader(ClusterFilter.class, moduleModel)
.getActivateExtension(url, key, group);
filters.addAll(tempFilters);
directors.add(moduleModel.getExtensionDirector());
}
filters = sortingAndDeduplication(filters, directors);
} else {
filters = ScopeModelUtil.getExtensionLoader(ClusterFilter.class, null).getActivateExtension(url, key, group);
filters =
ScopeModelUtil.getExtensionLoader(ClusterFilter.class, null).getActivateExtension(url, key, group);
}
if (!CollectionUtils.isEmpty(filters)) {
@ -141,5 +146,4 @@ public class DefaultFilterChainBuilder implements FilterChainBuilder {
}
return moduleModels;
}
}

View File

@ -92,7 +92,8 @@ public interface FilterChainBuilder {
public Result invoke(Invocation invocation) throws RpcException {
Result asyncResult;
try {
InvocationProfilerUtils.enterDetailProfiler(invocation, () -> "Filter " + filter.getClass().getName() + " invoke.");
InvocationProfilerUtils.enterDetailProfiler(
invocation, () -> "Filter " + filter.getClass().getName() + " invoke.");
asyncResult = filter.invoke(nextNode, invocation);
} catch (Exception e) {
InvocationProfilerUtils.releaseDetailProfiler(invocation);
@ -159,12 +160,11 @@ public interface FilterChainBuilder {
* @param <TYPE>
*/
class ClusterFilterChainNode<T, TYPE extends ClusterInvoker<T>, FILTER extends BaseFilter>
extends FilterChainNode<T, TYPE, FILTER> implements ClusterInvoker<T> {
extends FilterChainNode<T, TYPE, FILTER> implements ClusterInvoker<T> {
public ClusterFilterChainNode(TYPE originalInvoker, Invoker<T> nextNode, FILTER filter) {
super(originalInvoker, nextNode, filter);
}
@Override
public URL getRegistryUrl() {
return getOriginalInvoker().getRegistryUrl();
@ -182,7 +182,8 @@ public interface FilterChainBuilder {
}
class CallbackRegistrationInvoker<T, FILTER extends BaseFilter> implements Invoker<T> {
private static final ErrorTypeAwareLogger LOGGER = LoggerFactory.getErrorTypeAwareLogger(CallbackRegistrationInvoker.class);
private static final ErrorTypeAwareLogger LOGGER =
LoggerFactory.getErrorTypeAwareLogger(CallbackRegistrationInvoker.class);
final Invoker<T> filterInvoker;
final List<FILTER> filters;
@ -223,9 +224,20 @@ public interface FilterChainBuilder {
}
}
} catch (RuntimeException runtimeException) {
LOGGER.error(CLUSTER_EXECUTE_FILTER_EXCEPTION, "the custom filter is abnormal", "", String.format("Exception occurred while executing the %s filter named %s.", i, filter.getClass().getSimpleName()));
LOGGER.error(
CLUSTER_EXECUTE_FILTER_EXCEPTION,
"the custom filter is abnormal",
"",
String.format(
"Exception occurred while executing the %s filter named %s.",
i, filter.getClass().getSimpleName()));
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("Whole filter list is: %s", filters.stream().map(tmpFilter -> tmpFilter.getClass().getSimpleName()).collect(Collectors.toList())));
LOGGER.debug(String.format(
"Whole filter list is: %s",
filters.stream()
.map(tmpFilter ->
tmpFilter.getClass().getSimpleName())
.collect(Collectors.toList())));
}
filterRuntimeException = runtimeException;
t = runtimeException;
@ -264,11 +276,12 @@ public interface FilterChainBuilder {
}
}
class ClusterCallbackRegistrationInvoker<T, FILTER extends BaseFilter> extends CallbackRegistrationInvoker<T, FILTER>
implements ClusterInvoker<T> {
class ClusterCallbackRegistrationInvoker<T, FILTER extends BaseFilter>
extends CallbackRegistrationInvoker<T, FILTER> implements ClusterInvoker<T> {
private ClusterInvoker<T> originalInvoker;
public ClusterCallbackRegistrationInvoker(ClusterInvoker<T> originalInvoker, Invoker<T> filterInvoker, List<FILTER> filters) {
public ClusterCallbackRegistrationInvoker(
ClusterInvoker<T> originalInvoker, Invoker<T> filterInvoker, List<FILTER> filters) {
super(filterInvoker, filters);
this.originalInvoker = originalInvoker;
}
@ -293,10 +306,11 @@ public interface FilterChainBuilder {
}
}
@Experimental("Works for the same purpose as FilterChainNode, replace FilterChainNode with this one when proved stable enough")
@Experimental(
"Works for the same purpose as FilterChainNode, replace FilterChainNode with this one when proved stable enough")
class CopyOfFilterChainNode<T, TYPE extends Invoker<T>, FILTER extends BaseFilter> implements Invoker<T> {
private static final ErrorTypeAwareLogger LOGGER = LoggerFactory.getErrorTypeAwareLogger(CopyOfFilterChainNode.class);
private static final ErrorTypeAwareLogger LOGGER =
LoggerFactory.getErrorTypeAwareLogger(CopyOfFilterChainNode.class);
TYPE originalInvoker;
Invoker<T> nextNode;
FILTER filter;
@ -330,11 +344,14 @@ public interface FilterChainBuilder {
public Result invoke(Invocation invocation) throws RpcException {
Result asyncResult;
try {
InvocationProfilerUtils.enterDetailProfiler(invocation, () -> "Filter " + filter.getClass().getName() + " invoke.");
InvocationProfilerUtils.enterDetailProfiler(
invocation, () -> "Filter " + filter.getClass().getName() + " invoke.");
asyncResult = filter.invoke(nextNode, invocation);
if (!(asyncResult instanceof AsyncRpcResult)) {
String msg = "The result of filter invocation must be AsyncRpcResult. (If you want to recreate a result, please use AsyncRpcResult.newDefaultAsyncResult.) " +
"Filter class: " + filter.getClass().getName() + ". Result class: " + asyncResult.getClass().getName() + ".";
String msg =
"The result of filter invocation must be AsyncRpcResult. (If you want to recreate a result, please use AsyncRpcResult.newDefaultAsyncResult.) "
+ "Filter class: " + filter.getClass().getName() + ". Result class: "
+ asyncResult.getClass().getName() + ".";
LOGGER.error(INTERNAL_ERROR, "", "", msg);
throw new RpcException(msg);
}
@ -372,14 +389,14 @@ public interface FilterChainBuilder {
}
}
@Experimental("Works for the same purpose as ClusterFilterChainNode, replace ClusterFilterChainNode with this one when proved stable enough")
@Experimental(
"Works for the same purpose as ClusterFilterChainNode, replace ClusterFilterChainNode with this one when proved stable enough")
class CopyOfClusterFilterChainNode<T, TYPE extends ClusterInvoker<T>, FILTER extends BaseFilter>
extends CopyOfFilterChainNode<T, TYPE, FILTER> implements ClusterInvoker<T> {
extends CopyOfFilterChainNode<T, TYPE, FILTER> implements ClusterInvoker<T> {
public CopyOfClusterFilterChainNode(TYPE originalInvoker, Invoker<T> nextNode, FILTER filter) {
super(originalInvoker, nextNode, filter);
}
@Override
public URL getRegistryUrl() {
return getOriginalInvoker().getRegistryUrl();

View File

@ -62,7 +62,8 @@ public class ProtocolFilterWrapper implements Protocol {
}
private <T> FilterChainBuilder getFilterChainBuilder(URL url) {
return ScopeModelUtil.getExtensionLoader(FilterChainBuilder.class, url.getScopeModel()).getDefaultExtension();
return ScopeModelUtil.getExtensionLoader(FilterChainBuilder.class, url.getScopeModel())
.getDefaultExtension();
}
@Override
@ -83,5 +84,4 @@ public class ProtocolFilterWrapper implements Protocol {
public List<ProtocolServer> getServers() {
return protocol.getServers();
}
}

View File

@ -27,10 +27,11 @@ import org.apache.dubbo.rpc.cluster.filter.ClusterFilter;
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
@Activate(group = {CONSUMER}, order = Integer.MIN_VALUE + 100)
@Activate(
group = {CONSUMER},
order = Integer.MIN_VALUE + 100)
public class MetricsConsumerFilter extends MetricsFilter implements ClusterFilter, BaseFilter.Listener {
public MetricsConsumerFilter() {
}
public MetricsConsumerFilter() {}
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {

View File

@ -56,5 +56,4 @@ public class DefaultGovernanceRuleRepositoryImpl implements GovernanceRuleReposi
private DynamicConfiguration getDynamicConfiguration() {
return moduleModel.modelEnvironment().getDynamicConfiguration().orElse(null);
}
}

View File

@ -36,7 +36,6 @@ public interface GovernanceRuleRepository {
addListener(key, DEFAULT_GROUP, listener);
}
/**
* {@link #removeListener(String, String, ConfigurationListener)}
*

View File

@ -47,7 +47,7 @@ public abstract class AbstractLoadBalance implements LoadBalance {
* @return weight which takes warmup into account
*/
static int calculateWarmupWeight(int uptime, int warmup, int weight) {
int ww = (int) ( uptime / ((float) warmup / weight));
int ww = (int) (uptime / ((float) warmup / weight));
return ww < 1 ? 1 : (Math.min(ww, weight));
}
@ -64,7 +64,6 @@ public abstract class AbstractLoadBalance implements LoadBalance {
protected abstract <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation);
/**
* Get the weight of the invoker's invocation which takes warmup time into account
* if the uptime is within the warmup time, the weight will be reduce proportionally
@ -94,7 +93,7 @@ public abstract class AbstractLoadBalance implements LoadBalance {
}
int warmup = invoker.getUrl().getParameter(WARMUP_KEY, DEFAULT_WARMUP);
if (uptime > 0 && uptime < warmup) {
weight = calculateWarmupWeight((int)uptime, warmup, weight);
weight = calculateWarmupWeight((int) uptime, warmup, weight);
}
}
}

View File

@ -46,7 +46,8 @@ public class ConsistentHashLoadBalance extends AbstractLoadBalance {
*/
public static final String HASH_ARGUMENTS = "hash.arguments";
private final ConcurrentMap<String, ConsistentHashSelector<?>> selectors = new ConcurrentHashMap<String, ConsistentHashSelector<?>>();
private final ConcurrentMap<String, ConsistentHashSelector<?>> selectors =
new ConcurrentHashMap<String, ConsistentHashSelector<?>>();
@SuppressWarnings("unchecked")
@Override
@ -124,11 +125,10 @@ public class ConsistentHashLoadBalance extends AbstractLoadBalance {
private long hash(byte[] digest, int number) {
return (((long) (digest[3 + number * 4] & 0xFF) << 24)
| ((long) (digest[2 + number * 4] & 0xFF) << 16)
| ((long) (digest[1 + number * 4] & 0xFF) << 8)
| (digest[number * 4] & 0xFF))
| ((long) (digest[2 + number * 4] & 0xFF) << 16)
| ((long) (digest[1 + number * 4] & 0xFF) << 8)
| (digest[number * 4] & 0xFF))
& 0xFFFFFFFFL;
}
}
}

View File

@ -56,17 +56,18 @@ public class LeastActiveLoadBalance extends AbstractLoadBalance {
// Every least active invoker has the same weight value?
boolean sameWeight = true;
// Filter out all the least active invokers
for (int i = 0; i < length; i++) {
Invoker<T> invoker = invokers.get(i);
// Get the active number of the invoker
int active = RpcStatus.getStatus(invoker.getUrl(), RpcUtils.getMethodName(invocation)).getActive();
int active = RpcStatus.getStatus(invoker.getUrl(), RpcUtils.getMethodName(invocation))
.getActive();
// Get the weight of the invoker's configuration. The default value is 100.
int afterWarmup = getWeight(invoker, invocation);
// save for later use
weights[i] = afterWarmup;
// If it is the first invoker or the active number of the invoker is less than the current least active number
// If it is the first invoker or the active number of the invoker is less than the current least active
// number
if (leastActive == -1 || active < leastActive) {
// Reset the active number of the current invoker to the least active number
leastActive = active;

View File

@ -78,7 +78,8 @@ public class RandomLoadBalance extends AbstractLoadBalance {
}
}
if (totalWeight > 0 && !sameWeight) {
// If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on totalWeight.
// If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on
// totalWeight.
int offset = ThreadLocalRandom.current().nextInt(totalWeight);
// Return an invoker based on the random value.
if (length <= 4) {
@ -92,7 +93,7 @@ public class RandomLoadBalance extends AbstractLoadBalance {
if (i < 0) {
i = -i - 1;
} else {
while (weights[i+1] == offset) {
while (weights[i + 1] == offset) {
i++;
}
i++;

View File

@ -37,7 +37,8 @@ public class RoundRobinLoadBalance extends AbstractLoadBalance {
private static final int RECYCLE_PERIOD = 60000;
private final ConcurrentMap<String, ConcurrentMap<String, WeightedRoundRobin>> methodWeightMap = new ConcurrentHashMap<>();
private final ConcurrentMap<String, ConcurrentMap<String, WeightedRoundRobin>> methodWeightMap =
new ConcurrentHashMap<>();
protected static class WeightedRoundRobin {
private int weight;
@ -91,7 +92,8 @@ public class RoundRobinLoadBalance extends AbstractLoadBalance {
@Override
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
String key = invokers.get(0).getUrl().getServiceKey() + "." + RpcUtils.getMethodName(invocation);
ConcurrentMap<String, WeightedRoundRobin> map = ConcurrentHashMapUtils.computeIfAbsent(methodWeightMap, key, k -> new ConcurrentHashMap<>());
ConcurrentMap<String, WeightedRoundRobin> map =
ConcurrentHashMapUtils.computeIfAbsent(methodWeightMap, key, k -> new ConcurrentHashMap<>());
int totalWeight = 0;
long maxCurrent = Long.MIN_VALUE;
long now = System.currentTimeMillis();
@ -107,7 +109,7 @@ public class RoundRobinLoadBalance extends AbstractLoadBalance {
});
if (weight != weightedRoundRobin.getWeight()) {
//weight changed
// weight changed
weightedRoundRobin.setWeight(weight);
}
long cur = weightedRoundRobin.increaseCurrent();
@ -129,5 +131,4 @@ public class RoundRobinLoadBalance extends AbstractLoadBalance {
// should not happen here
return invokers.get(0);
}
}

View File

@ -59,9 +59,15 @@ public class ShortestResponseLoadBalance extends AbstractLoadBalance implements
@Override
public void setApplicationModel(ApplicationModel applicationModel) {
slidePeriod = applicationModel.modelEnvironment().getConfiguration().getInt(Constants.SHORTEST_RESPONSE_SLIDE_PERIOD, 30_000);
executorService = applicationModel.getFrameworkModel().getBeanFactory()
.getBean(FrameworkExecutorRepository.class).getSharedExecutor();
slidePeriod = applicationModel
.modelEnvironment()
.getConfiguration()
.getInt(Constants.SHORTEST_RESPONSE_SLIDE_PERIOD, 30_000);
executorService = applicationModel
.getFrameworkModel()
.getBeanFactory()
.getBean(FrameworkExecutorRepository.class)
.getSharedExecutor();
}
protected static class SlideWindowData {
@ -118,9 +124,11 @@ public class ShortestResponseLoadBalance extends AbstractLoadBalance implements
for (int i = 0; i < length; i++) {
Invoker<T> invoker = invokers.get(i);
RpcStatus rpcStatus = RpcStatus.getStatus(invoker.getUrl(), RpcUtils.getMethodName(invocation));
SlideWindowData slideWindowData = ConcurrentHashMapUtils.computeIfAbsent(methodMap, rpcStatus, SlideWindowData::new);
SlideWindowData slideWindowData =
ConcurrentHashMapUtils.computeIfAbsent(methodMap, rpcStatus, SlideWindowData::new);
// Calculate the estimated response time from the product of active connections and succeeded average elapsed time.
// Calculate the estimated response time from the product of active connections and succeeded average
// elapsed time.
long estimateResponse = slideWindowData.getEstimateResponse();
int afterWarmup = getWeight(invoker, invocation);
weights[i] = afterWarmup;
@ -135,16 +143,15 @@ public class ShortestResponseLoadBalance extends AbstractLoadBalance implements
} else if (estimateResponse == shortestResponse) {
shortestIndexes[shortestCount++] = i;
totalWeight += afterWarmup;
if (sameWeight && i > 0
&& afterWarmup != firstWeight) {
if (sameWeight && i > 0 && afterWarmup != firstWeight) {
sameWeight = false;
}
}
}
if (System.currentTimeMillis() - lastUpdateTime > slidePeriod
&& onResetSlideWindow.compareAndSet(false, true)) {
//reset slideWindowData in async way
&& onResetSlideWindow.compareAndSet(false, true)) {
// reset slideWindowData in async way
executorService.execute(() -> {
methodMap.values().forEach(SlideWindowData::reset);
lastUpdateTime = System.currentTimeMillis();

View File

@ -28,12 +28,13 @@ public abstract class AbstractRouter implements Router {
private GovernanceRuleRepository ruleRepository;
public AbstractRouter(URL url) {
this.ruleRepository = url.getOrDefaultModuleModel().getExtensionLoader(GovernanceRuleRepository.class).getDefaultExtension();
this.ruleRepository = url.getOrDefaultModuleModel()
.getExtensionLoader(GovernanceRuleRepository.class)
.getDefaultExtension();
this.url = url;
}
public AbstractRouter() {
}
public AbstractRouter() {}
@Override
public URL getUrl() {
@ -67,8 +68,7 @@ public abstract class AbstractRouter implements Router {
this.priority = priority;
}
public GovernanceRuleRepository getRuleRepository(){
public GovernanceRuleRepository getRuleRepository() {
return this.ruleRepository;
}
}

View File

@ -34,7 +34,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
public class RouterSnapshotFilter implements ClusterFilter, BaseFilter.Listener {
private final RouterSnapshotSwitcher switcher;
private final static Logger logger = LoggerFactory.getLogger(RouterSnapshotFilter.class);
private static final Logger logger = LoggerFactory.getLogger(RouterSnapshotFilter.class);
public RouterSnapshotFilter(FrameworkModel frameworkModel) {
this.switcher = frameworkModel.getBeanFactory().getBean(RouterSnapshotSwitcher.class);

View File

@ -114,43 +114,55 @@ public class RouterSnapshotNode<T> {
public String toString(int level) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("[ ")
.append(name)
.append(' ')
.append("(Input: ").append(beforeSize).append(") ")
.append("(Current Node Output: ").append(nodeOutputSize).append(") ")
.append("(Chain Node Output: ").append(chainOutputSize).append(')')
.append(routerMessage == null ? "" : " Router message: ")
.append(routerMessage == null ? "" : routerMessage)
.append(" ] ");
stringBuilder
.append("[ ")
.append(name)
.append(' ')
.append("(Input: ")
.append(beforeSize)
.append(") ")
.append("(Current Node Output: ")
.append(nodeOutputSize)
.append(") ")
.append("(Chain Node Output: ")
.append(chainOutputSize)
.append(')')
.append(routerMessage == null ? "" : " Router message: ")
.append(routerMessage == null ? "" : routerMessage)
.append(" ] ");
if (level == 1) {
stringBuilder.append("Input: ")
.append(CollectionUtils.isEmpty(inputInvokers) ? "Empty" :
inputInvokers.subList(0, Math.min(5, inputInvokers.size()))
.stream()
.map(Invoker::getUrl)
.map(URL::getAddress)
.collect(Collectors.joining(",")))
.append(" -> ");
stringBuilder
.append("Input: ")
.append(
CollectionUtils.isEmpty(inputInvokers)
? "Empty"
: inputInvokers.subList(0, Math.min(5, inputInvokers.size())).stream()
.map(Invoker::getUrl)
.map(URL::getAddress)
.collect(Collectors.joining(",")))
.append(" -> ");
stringBuilder.append("Chain Node Output: ")
.append(CollectionUtils.isEmpty(chainOutputInvokers) ? "Empty" :
chainOutputInvokers.subList(0, Math.min(5, chainOutputInvokers.size()))
.stream()
.map(Invoker::getUrl)
.map(URL::getAddress)
.collect(Collectors.joining(",")));
stringBuilder
.append("Chain Node Output: ")
.append(
CollectionUtils.isEmpty(chainOutputInvokers)
? "Empty"
: chainOutputInvokers.subList(0, Math.min(5, chainOutputInvokers.size())).stream()
.map(Invoker::getUrl)
.map(URL::getAddress)
.collect(Collectors.joining(",")));
} else {
stringBuilder.append("Current Node Output: ")
.append(CollectionUtils.isEmpty(nodeOutputInvokers) ? "Empty" :
nodeOutputInvokers.subList(0, Math.min(5, nodeOutputInvokers.size()))
.stream()
.map(Invoker::getUrl)
.map(URL::getAddress)
.collect(Collectors.joining(",")));
stringBuilder
.append("Current Node Output: ")
.append(
CollectionUtils.isEmpty(nodeOutputInvokers)
? "Empty"
: nodeOutputInvokers.subList(0, Math.min(5, nodeOutputInvokers.size())).stream()
.map(Invoker::getUrl)
.map(URL::getAddress)
.collect(Collectors.joining(",")));
}
if (nodeOutputInvokers != null && nodeOutputInvokers.size() > 5) {
stringBuilder.append("...");
}

View File

@ -26,7 +26,7 @@ public class RouterSnapshotSwitcher {
private volatile boolean enable;
private final Set<String> enabledService = new ConcurrentHashSet<>();
private final static int MAX_LENGTH = 1 << 5; // 2 ^ 5 = 31
private static final int MAX_LENGTH = 1 << 5; // 2 ^ 5 = 31
private final AtomicInteger offset = new AtomicInteger(0);
private volatile String[] recentSnapshot = new String[MAX_LENGTH];

View File

@ -62,7 +62,14 @@ public class AddressMatch {
try {
return input.equals(getCird()) || matchIpExpression(getCird(), input);
} catch (UnknownHostException e) {
logger.error(CLUSTER_FAILED_EXEC_CONDITION_ROUTER, "Executing routing rule match expression error.", "", String.format("Error trying to match cird formatted address %s with input %s in AddressMatch.", getCird(), input), e);
logger.error(
CLUSTER_FAILED_EXEC_CONDITION_ROUTER,
"Executing routing rule match expression error.",
"",
String.format(
"Error trying to match cird formatted address %s with input %s in AddressMatch.",
getCird(), input),
e);
}
}
if (getWildcard() != null && input != null) {

View File

@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
public class BoolMatch {
private Boolean exact;
@ -29,8 +27,8 @@ public class BoolMatch {
this.exact = exact;
}
public boolean isMatch(boolean input){
if (exact != null){
public boolean isMatch(boolean input) {
if (exact != null) {
return input == exact;
}
return false;

View File

@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
public class DoubleMatch {
private Double exact;
private DoubleRangeMatch range;
@ -47,7 +45,6 @@ public class DoubleMatch {
this.mod = mod;
}
public boolean isMatch(Double input) {
if (exact != null && mod == null) {
return input.equals(exact);

View File

@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
public class DoubleRangeMatch {
private Double start;
private Double end;
@ -38,7 +36,6 @@ public class DoubleRangeMatch {
this.end = end;
}
public boolean isMatch(Double input) {
if (start != null && end != null) {
return input.compareTo(start) >= 0 && input.compareTo(end) < 0;

View File

@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
public class DubboMethodArg {
private int index;
private String type;
@ -79,12 +77,11 @@ public class DubboMethodArg {
@Override
public String toString() {
return "DubboMethodArg{" +
"index=" + index +
", type='" + type + '\'' +
", str_value=" + str_value +
", num_value=" + num_value +
", bool_value=" + bool_value +
'}';
return "DubboMethodArg{" + "index="
+ index + ", type='"
+ type + '\'' + ", str_value="
+ str_value + ", num_value="
+ num_value + ", bool_value="
+ bool_value + '}';
}
}

View File

@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
import org.apache.dubbo.rpc.Invocation;
@ -23,7 +22,6 @@ import org.apache.dubbo.rpc.support.RpcUtils;
import java.util.List;
import java.util.Map;
public class DubboMethodMatch {
private StringMatch name_match;
private Integer argc;
@ -73,13 +71,12 @@ public class DubboMethodMatch {
@Override
public String toString() {
return "DubboMethodMatch{" +
"name_match=" + name_match +
", argc=" + argc +
", args=" + args +
", argp=" + argp +
", headers=" + headers +
'}';
return "DubboMethodMatch{" + "name_match="
+ name_match + ", argc="
+ argc + ", args="
+ args + ", argp="
+ argp + ", headers="
+ headers + '}';
}
public boolean isMatch(Invocation invocation) {
@ -90,8 +87,8 @@ public class DubboMethodMatch {
Integer argc = getArgc();
Object[] arguments = invocation.getArguments();
if (argc != null &&
((argc != 0 && (arguments == null || arguments.length == 0)) || (argc != arguments.length))) {
if (argc != null
&& ((argc != 0 && (arguments == null || arguments.length == 0)) || (argc != arguments.length))) {
return false;
}
@ -107,7 +104,7 @@ public class DubboMethodMatch {
for (int index = 0; index < argp.size(); index++) {
boolean match = argp.get(index).isMatch(parameterTypes[index].getName())
|| argp.get(index).isMatch(parameterTypes[index].getSimpleName());
|| argp.get(index).isMatch(parameterTypes[index].getSimpleName());
if (!match) {
return false;
}
@ -134,4 +131,3 @@ public class DubboMethodMatch {
return true;
}
}

View File

@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
import java.util.List;
public class ListBoolMatch {
@ -41,4 +39,3 @@ public class ListBoolMatch {
return false;
}
}

View File

@ -14,12 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
import java.util.List;
public class ListDoubleMatch {
private List<DoubleMatch> oneof;

View File

@ -14,12 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
import java.util.List;
public class ListStringMatch {
private List<StringMatch> oneof;
@ -31,7 +29,6 @@ public class ListStringMatch {
this.oneof = oneof;
}
public boolean isMatch(String input) {
for (StringMatch stringMatch : oneof) {

View File

@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match;
import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE;
public class StringMatch {
@ -28,7 +26,6 @@ public class StringMatch {
private String empty;
private String wildcard;
public String getExact() {
return exact;
}
@ -98,12 +95,11 @@ public class StringMatch {
@Override
public String toString() {
return "StringMatch{" +
"exact='" + exact + '\'' +
", prefix='" + prefix + '\'' +
", regex='" + regex + '\'' +
", noempty='" + noempty + '\'' +
", empty='" + empty + '\'' +
'}';
return "StringMatch{" + "exact='"
+ exact + '\'' + ", prefix='"
+ prefix + '\'' + ", regex='"
+ regex + '\'' + ", noempty='"
+ noempty + '\'' + ", empty='"
+ empty + '\'' + '}';
}
}

View File

@ -47,9 +47,11 @@ public abstract class AbstractStateRouter<T> implements StateRouter<T> {
public AbstractStateRouter(URL url) {
moduleModel = url.getOrDefaultModuleModel();
this.ruleRepository = moduleModel.getExtensionLoader(GovernanceRuleRepository.class).getDefaultExtension();
this.ruleRepository =
moduleModel.getExtensionLoader(GovernanceRuleRepository.class).getDefaultExtension();
this.url = url;
this.shouldFailFast = Boolean.parseBoolean(ConfigurationUtils.getProperty(moduleModel, Constants.SHOULD_FAIL_FAST_KEY, "true"));
this.shouldFailFast = Boolean.parseBoolean(
ConfigurationUtils.getProperty(moduleModel, Constants.SHOULD_FAIL_FAST_KEY, "true"));
}
@Override
@ -89,7 +91,13 @@ public abstract class AbstractStateRouter<T> implements StateRouter<T> {
}
@Override
public final BitList<Invoker<T>> route(BitList<Invoker<T>> invokers, URL url, Invocation invocation, boolean needToPrintMessage, Holder<RouterSnapshotNode<T>> nodeHolder) throws RpcException {
public final BitList<Invoker<T>> route(
BitList<Invoker<T>> invokers,
URL url,
Invocation invocation,
boolean needToPrintMessage,
Holder<RouterSnapshotNode<T>> nodeHolder)
throws RpcException {
if (needToPrintMessage && (nodeHolder == null || nodeHolder.get() == null)) {
needToPrintMessage = false;
}
@ -151,17 +159,26 @@ public abstract class AbstractStateRouter<T> implements StateRouter<T> {
* @param messageHolder message holder when router should current router print message
* @return routed result
*/
protected abstract BitList<Invoker<T>> doRoute(BitList<Invoker<T>> invokers, URL url, Invocation invocation,
boolean needToPrintMessage, Holder<RouterSnapshotNode<T>> nodeHolder,
Holder<String> messageHolder) throws RpcException;
protected abstract BitList<Invoker<T>> doRoute(
BitList<Invoker<T>> invokers,
URL url,
Invocation invocation,
boolean needToPrintMessage,
Holder<RouterSnapshotNode<T>> nodeHolder,
Holder<String> messageHolder)
throws RpcException;
/**
* Call next router to get result
*
* @param invokers current router filtered invokers
*/
protected final BitList<Invoker<T>> continueRoute(BitList<Invoker<T>> invokers, URL url, Invocation invocation,
boolean needToPrintMessage, Holder<RouterSnapshotNode<T>> nodeHolder) {
protected final BitList<Invoker<T>> continueRoute(
BitList<Invoker<T>> invokers,
URL url,
Invocation invocation,
boolean needToPrintMessage,
Holder<RouterSnapshotNode<T>> nodeHolder) {
if (nextRouter != null) {
return nextRouter.route(invokers, url, invocation, needToPrintMessage, nodeHolder);
} else {
@ -192,9 +209,7 @@ public abstract class AbstractStateRouter<T> implements StateRouter<T> {
@Override
public final String buildSnapshot() {
return doBuildSnapshot() +
" v \n" +
nextRouter.buildSnapshot();
return doBuildSnapshot() + " v \n" + nextRouter.buildSnapshot();
}
protected String doBuildSnapshot() {

View File

@ -55,7 +55,7 @@ import java.util.concurrent.ThreadLocalRandom;
public class BitList<E> extends AbstractList<E> implements Cloneable {
private final BitSet rootSet;
private volatile List<E> originList;
private final static BitList emptyList = new BitList(Collections.emptyList());
private static final BitList emptyList = new BitList(Collections.emptyList());
private volatile List<E> tailList = null;
public BitList(List<E> originList) {
@ -367,7 +367,8 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
copiedTailList = null;
resultSet.set(toIndex, resultSet.length(), false);
} else {
copiedTailList = copiedTailList == null ? null : copiedTailList.subList(0, toIndex - rootSet.cardinality());
copiedTailList =
copiedTailList == null ? null : copiedTailList.subList(0, toIndex - rootSet.cardinality());
}
}
if (fromIndex > 0) {
@ -375,7 +376,9 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
resultSet.set(0, fromIndex, false);
} else {
resultSet.clear();
copiedTailList = copiedTailList == null ? null : copiedTailList.subList(fromIndex - rootSet.cardinality(), copiedTailList.size());
copiedTailList = copiedTailList == null
? null
: copiedTailList.subList(fromIndex - rootSet.cardinality(), copiedTailList.size());
}
}
return new BitList<>(originList, resultSet, copiedTailList);
@ -551,6 +554,7 @@ public class BitList<E> extends AbstractList<E> implements Cloneable {
@Override
public BitList<E> clone() {
return new BitList<>(originList, (BitSet) rootSet.clone(), tailList == null ? null : new LinkedList<>(tailList));
return new BitList<>(
originList, (BitSet) rootSet.clone(), tailList == null ? null : new LinkedList<>(tailList));
}
}

View File

@ -32,7 +32,8 @@ public abstract class CacheableStateRouterFactory implements StateRouterFactory
@Override
public <T> StateRouter<T> getRouter(Class<T> interfaceClass, URL url) {
return ConcurrentHashMapUtils.computeIfAbsent(routerMap, url.getServiceKey(), k -> createRouter(interfaceClass, url));
return ConcurrentHashMapUtils.computeIfAbsent(
routerMap, url.getServiceKey(), k -> createRouter(interfaceClass, url));
}
protected abstract <T> StateRouter<T> createRouter(Class<T> interfaceClass, URL url);

View File

@ -48,29 +48,32 @@ public class RouterGroupingState<T> {
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(routerName)
.append(' ')
.append(" Total: ")
.append(total)
.append("\n");
stringBuilder
.append(routerName)
.append(' ')
.append(" Total: ")
.append(total)
.append("\n");
for (Map.Entry<String, BitList<Invoker<T>>> entry : grouping.entrySet()) {
BitList<Invoker<T>> invokers = entry.getValue();
stringBuilder.append("[ ")
.append(entry.getKey())
.append(" -> ")
.append(invokers.isEmpty() ?
"Empty" :
invokers.stream()
.limit(5)
.map(Invoker::getUrl)
.map(URL::getAddress)
.collect(Collectors.joining(",")))
.append(invokers.size() > 5 ? "..." : "")
.append(" (Total: ")
.append(invokers.size())
.append(") ]")
.append("\n");
stringBuilder
.append("[ ")
.append(entry.getKey())
.append(" -> ")
.append(
invokers.isEmpty()
? "Empty"
: invokers.stream()
.limit(5)
.map(Invoker::getUrl)
.map(URL::getAddress)
.collect(Collectors.joining(",")))
.append(invokers.size() > 5 ? "..." : "")
.append(" (Total: ")
.append(invokers.size())
.append(") ]")
.append("\n");
}
return stringBuilder.toString();
}

View File

@ -55,8 +55,13 @@ public interface StateRouter<T> {
* @return state with route result
* @since 3.0
*/
BitList<Invoker<T>> route(BitList<Invoker<T>> invokers, URL url, Invocation invocation,
boolean needToPrintMessage, Holder<RouterSnapshotNode<T>> nodeHolder) throws RpcException;
BitList<Invoker<T>> route(
BitList<Invoker<T>> invokers,
URL url,
Invocation invocation,
boolean needToPrintMessage,
Holder<RouterSnapshotNode<T>> nodeHolder)
throws RpcException;
/**
* To decide whether this router need to execute every time an RPC comes or should only execute when addresses or
@ -92,7 +97,7 @@ public interface StateRouter<T> {
String buildSnapshot();
default void stop() {
//do nothing by default
// do nothing by default
}
/**

View File

@ -31,14 +31,10 @@ public class TailStateRouter<T> implements StateRouter<T> {
return INSTANCE;
}
private TailStateRouter() {
}
private TailStateRouter() {}
@Override
public void setNextRouter(StateRouter<T> nextRouter) {
}
public void setNextRouter(StateRouter<T> nextRouter) {}
@Override
public URL getUrl() {
@ -46,7 +42,13 @@ public class TailStateRouter<T> implements StateRouter<T> {
}
@Override
public BitList<Invoker<T>> route(BitList<Invoker<T>> invokers, URL url, Invocation invocation, boolean needToPrintMessage, Holder<RouterSnapshotNode<T>> nodeHolder) throws RpcException {
public BitList<Invoker<T>> route(
BitList<Invoker<T>> invokers,
URL url,
Invocation invocation,
boolean needToPrintMessage,
Holder<RouterSnapshotNode<T>> nodeHolder)
throws RpcException {
return invokers;
}
@ -61,9 +63,7 @@ public class TailStateRouter<T> implements StateRouter<T> {
}
@Override
public void notify(BitList<Invoker<T>> invokers) {
}
public void notify(BitList<Invoker<T>> invokers) {}
@Override
public String buildSnapshot() {

View File

@ -61,7 +61,8 @@ import static org.apache.dubbo.rpc.cluster.Constants.DEFAULT_CLUSTER_STICKY;
*/
public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(AbstractClusterInvoker.class);
private static final ErrorTypeAwareLogger logger =
LoggerFactory.getErrorTypeAwareLogger(AbstractClusterInvoker.class);
protected Directory<T> directory;
@ -75,8 +76,7 @@ public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
private volatile Invoker<T> stickyInvoker = null;
public AbstractClusterInvoker() {
}
public AbstractClusterInvoker() {}
public AbstractClusterInvoker(Directory<T> directory) {
this(directory, directory.getUrl());
@ -88,7 +88,7 @@ public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
}
this.directory = directory;
//sticky: invoker.isAvailable() should always be checked before using when availablecheck is true.
// sticky: invoker.isAvailable() should always be checked before using when availablecheck is true.
this.availableCheck = url.getParameter(CLUSTER_AVAILABLE_CHECK_KEY, DEFAULT_CLUSTER_AVAILABLE_CHECK);
Configuration configuration = ConfigurationUtils.getGlobalConfiguration(url.getOrDefaultModuleModel());
this.reselectCount = configuration.getInt(RESELECT_COUNT, DEFAULT_RESELECT_COUNT);
@ -152,22 +152,23 @@ public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
* @return the invoker which will final to do invoke.
* @throws RpcException exception
*/
protected Invoker<T> select(LoadBalance loadbalance, Invocation invocation,
List<Invoker<T>> invokers, List<Invoker<T>> selected) throws RpcException {
protected Invoker<T> select(
LoadBalance loadbalance, Invocation invocation, List<Invoker<T>> invokers, List<Invoker<T>> selected)
throws RpcException {
if (CollectionUtils.isEmpty(invokers)) {
return null;
}
String methodName = invocation == null ? StringUtils.EMPTY_STRING : RpcUtils.getMethodName(invocation);
boolean sticky = invokers.get(0).getUrl()
.getMethodParameter(methodName, CLUSTER_STICKY_KEY, DEFAULT_CLUSTER_STICKY);
boolean sticky =
invokers.get(0).getUrl().getMethodParameter(methodName, CLUSTER_STICKY_KEY, DEFAULT_CLUSTER_STICKY);
//ignore overloaded method
// ignore overloaded method
if (stickyInvoker != null && !invokers.contains(stickyInvoker)) {
stickyInvoker = null;
}
//ignore concurrency problem
// ignore concurrency problem
if (sticky && stickyInvoker != null && (selected == null || !selected.contains(stickyInvoker))) {
if (availableCheck && stickyInvoker.isAvailable()) {
return stickyInvoker;
@ -183,8 +184,9 @@ public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
return invoker;
}
private Invoker<T> doSelect(LoadBalance loadbalance, Invocation invocation,
List<Invoker<T>> invokers, List<Invoker<T>> selected) throws RpcException {
private Invoker<T> doSelect(
LoadBalance loadbalance, Invocation invocation, List<Invoker<T>> invokers, List<Invoker<T>> selected)
throws RpcException {
if (CollectionUtils.isEmpty(invokers)) {
return null;
@ -196,7 +198,7 @@ public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
}
Invoker<T> invoker = loadbalance.select(invokers, getUrl(), invocation);
//If the `invoker` is in the `selected` or invoker is unavailable && availablecheck is true, reselect.
// If the `invoker` is in the `selected` or invoker is unavailable && availablecheck is true, reselect.
boolean isSelected = selected != null && selected.contains(invoker);
boolean isUnavailable = availableCheck && !invoker.isAvailable() && getUrl() != null;
@ -209,17 +211,28 @@ public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
if (rInvoker != null) {
invoker = rInvoker;
} else {
//Check the index of current selected invoker, if it's not the last one, choose the one at index+1.
// Check the index of current selected invoker, if it's not the last one, choose the one at index+1.
int index = invokers.indexOf(invoker);
try {
//Avoid collision
// Avoid collision
invoker = invokers.get((index + 1) % invokers.size());
} catch (Exception e) {
logger.warn(CLUSTER_FAILED_RESELECT_INVOKERS,"select invokers exception","",e.getMessage() + " may because invokers list dynamic change, ignore.",e);
logger.warn(
CLUSTER_FAILED_RESELECT_INVOKERS,
"select invokers exception",
"",
e.getMessage() + " may because invokers list dynamic change, ignore.",
e);
}
}
} catch (Throwable t) {
logger.error(CLUSTER_FAILED_RESELECT_INVOKERS,"failed to reselect invokers","","cluster reselect fail reason is :" + t.getMessage() + " if can not solve, you can set cluster.availablecheck=false in url",t);
logger.error(
CLUSTER_FAILED_RESELECT_INVOKERS,
"failed to reselect invokers",
"",
"cluster reselect fail reason is :" + t.getMessage()
+ " if can not solve, you can set cluster.availablecheck=false in url",
t);
}
}
@ -238,8 +251,13 @@ public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
* @return the reselect result to do invoke
* @throws RpcException exception
*/
private Invoker<T> reselect(LoadBalance loadbalance, Invocation invocation,
List<Invoker<T>> invokers, List<Invoker<T>> selected, boolean availableCheck) throws RpcException {
private Invoker<T> reselect(
LoadBalance loadbalance,
Invocation invocation,
List<Invoker<T>> invokers,
List<Invoker<T>> selected,
boolean availableCheck)
throws RpcException {
// Allocating one in advance, this list is certain to be used.
List<Invoker<T>> reselectInvokers = new ArrayList<>(Math.min(invokers.size(), reselectCount));
@ -247,9 +265,12 @@ public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
// 1. Try picking some invokers not in `selected`.
// 1.1. If all selectable invokers' size is smaller than reselectCount, just add all
// 1.2. If all selectable invokers' size is greater than reselectCount, randomly select reselectCount.
// The result size of invokers might smaller than reselectCount due to disAvailable or de-duplication (might be zero).
// This means there is probable that reselectInvokers is empty however all invoker list may contain available invokers.
// Use reselectCount can reduce retry times if invokers' size is huge, which may lead to long time hang up.
// The result size of invokers might smaller than reselectCount due to disAvailable or de-duplication
// (might be zero).
// This means there is probable that reselectInvokers is empty however all invoker list may contain
// available invokers.
// Use reselectCount can reduce retry times if invokers' size is huge, which may lead to long time
// hang up.
if (reselectCount >= invokers.size()) {
for (Invoker<T> invoker : invokers) {
// check if available
@ -290,7 +311,7 @@ public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
if (selected != null) {
for (Invoker<T> invoker : selected) {
if ((invoker.isAvailable()) // available first
&& !reselectInvokers.contains(invoker)) {
&& !reselectInvokers.contains(invoker)) {
reselectInvokers.add(invoker);
}
}
@ -325,10 +346,10 @@ public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
checkWhetherDestroyed();
// binding attachments into invocation.
// Map<String, Object> contextAttachments = RpcContext.getClientAttachment().getObjectAttachments();
// if (contextAttachments != null && contextAttachments.size() != 0) {
// ((RpcInvocation) invocation).addObjectAttachmentsIfAbsent(contextAttachments);
// }
// Map<String, Object> contextAttachments = RpcContext.getClientAttachment().getObjectAttachments();
// if (contextAttachments != null && contextAttachments.size() != 0) {
// ((RpcInvocation) invocation).addObjectAttachmentsIfAbsent(contextAttachments);
// }
InvocationProfilerUtils.enterDetailProfiler(invocation, () -> "Router route.");
List<Invoker<T>> invokers = list(invocation);
@ -339,7 +360,8 @@ public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
LoadBalance loadbalance = initLoadBalance(invokers, invocation);
RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
InvocationProfilerUtils.enterDetailProfiler(invocation, () -> "Cluster " + this.getClass().getName() + " invoke.");
InvocationProfilerUtils.enterDetailProfiler(
invocation, () -> "Cluster " + this.getClass().getName() + " invoke.");
try {
return doInvoke(invocation, invokers, loadbalance);
} finally {
@ -349,9 +371,10 @@ public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
protected void checkWhetherDestroyed() {
if (destroyed.get()) {
throw new RpcException("Rpc cluster invoker for " + getInterface() + " on consumer " + NetUtils.getLocalHost()
+ " use dubbo version " + Version.getVersion()
+ " is now destroyed! Can not invoke any more.");
throw new RpcException(
"Rpc cluster invoker for " + getInterface() + " on consumer " + NetUtils.getLocalHost()
+ " use dubbo version " + Version.getVersion()
+ " is now destroyed! Can not invoke any more.");
}
}
@ -362,13 +385,17 @@ public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
protected void checkInvokers(List<Invoker<T>> invokers, Invocation invocation) {
if (CollectionUtils.isEmpty(invokers)) {
throw new RpcException(RpcException.NO_INVOKER_AVAILABLE_AFTER_FILTER, "Failed to invoke the method "
+ RpcUtils.getMethodName(invocation) + " in the service " + getInterface().getName()
+ ". No provider available for the service " + getDirectory().getConsumerUrl().getServiceKey()
+ " from registry " + getDirectory()
+ " on the consumer " + NetUtils.getLocalHost()
+ " using the dubbo version " + Version.getVersion()
+ ". Please check if the providers have been started and registered.");
throw new RpcException(
RpcException.NO_INVOKER_AVAILABLE_AFTER_FILTER,
"Failed to invoke the method "
+ RpcUtils.getMethodName(invocation) + " in the service "
+ getInterface().getName()
+ ". No provider available for the service "
+ getDirectory().getConsumerUrl().getServiceKey()
+ " from registry " + getDirectory()
+ " on the consumer " + NetUtils.getLocalHost()
+ " using the dubbo version " + Version.getVersion()
+ ". Please check if the providers have been started and registered.");
}
}
@ -377,7 +404,9 @@ public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
Result result;
try {
if (ProfilerSwitch.isEnableSimpleProfiler()) {
InvocationProfilerUtils.enterProfiler(invocation, "Invoker invoke. Target Address: " + invoker.getUrl().getAddress());
InvocationProfilerUtils.enterProfiler(
invocation,
"Invoker invoke. Target Address: " + invoker.getUrl().getAddress());
}
setRemote(invoker, invocation);
result = invoker.invoke(invocation);
@ -416,8 +445,8 @@ public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
return result;
}
protected abstract Result doInvoke(Invocation invocation, List<Invoker<T>> invokers,
LoadBalance loadbalance) throws RpcException;
protected abstract Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance)
throws RpcException;
protected List<Invoker<T>> list(Invocation invocation) throws RpcException {
return getDirectory().list(invocation);
@ -437,17 +466,17 @@ public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
protected LoadBalance initLoadBalance(List<Invoker<T>> invokers, Invocation invocation) {
ApplicationModel applicationModel = ScopeModelUtil.getApplicationModel(invocation.getModuleModel());
if (CollectionUtils.isNotEmpty(invokers)) {
return applicationModel.getExtensionLoader(LoadBalance.class).getExtension(
invokers.get(0).getUrl().getMethodParameter(
RpcUtils.getMethodName(invocation), LOADBALANCE_KEY, DEFAULT_LOADBALANCE
)
);
return applicationModel
.getExtensionLoader(LoadBalance.class)
.getExtension(invokers.get(0)
.getUrl()
.getMethodParameter(
RpcUtils.getMethodName(invocation), LOADBALANCE_KEY, DEFAULT_LOADBALANCE));
} else {
return applicationModel.getExtensionLoader(LoadBalance.class).getExtension(DEFAULT_LOADBALANCE);
}
}
private Invoker<T> setContext(Invoker<T> invoker) {
return setContext(invoker, null);
}
@ -456,7 +485,10 @@ public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
RpcServiceContext context = RpcContext.getServiceContext();
Invoker<?> originInvoker = context.getInvoker();
context.setInvoker(invoker)
.setConsumerUrl(null != consumerUrl ? consumerUrl : RpcContext.getServiceContext().getConsumerUrl());
.setConsumerUrl(
null != consumerUrl
? consumerUrl
: RpcContext.getServiceContext().getConsumerUrl());
return (Invoker<T>) originInvoker;
}

View File

@ -36,7 +36,8 @@ public class AvailableClusterInvoker<T> extends AbstractClusterInvoker<T> {
}
@Override
public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance)
throws RpcException {
for (Invoker<T> invoker : invokers) {
if (invoker.isAvailable()) {
return invokeWithContext(invoker, invocation);
@ -44,5 +45,4 @@ public class AvailableClusterInvoker<T> extends AbstractClusterInvoker<T> {
}
throw new RpcException("No provider available in " + invokers);
}
}

View File

@ -30,5 +30,4 @@ public class BroadcastCluster extends AbstractCluster {
public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
return new BroadcastClusterInvoker<>(directory);
}
}

View File

@ -39,7 +39,8 @@ import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_ERRO
*/
public class BroadcastClusterInvoker<T> extends AbstractClusterInvoker<T> {
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(BroadcastClusterInvoker.class);
private static final ErrorTypeAwareLogger logger =
LoggerFactory.getErrorTypeAwareLogger(BroadcastClusterInvoker.class);
private static final String BROADCAST_FAIL_PERCENT_KEY = "broadcast.fail.percent";
private static final int MAX_BROADCAST_FAIL_PERCENT = 100;
private static final int MIN_BROADCAST_FAIL_PERCENT = 0;
@ -50,19 +51,23 @@ public class BroadcastClusterInvoker<T> extends AbstractClusterInvoker<T> {
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public Result doInvoke(final Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
public Result doInvoke(final Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance)
throws RpcException {
RpcContext.getServiceContext().setInvokers((List) invokers);
RpcException exception = null;
Result result = null;
URL url = getUrl();
// The value range of broadcast.fail.threshold must be 0100.
// 100 means that an exception will be thrown last, and 0 means that as long as an exception occurs, it will be thrown.
// 100 means that an exception will be thrown last, and 0 means that as long as an exception occurs, it will be
// thrown.
// see https://github.com/apache/dubbo/pull/7174
int broadcastFailPercent = url.getParameter(BROADCAST_FAIL_PERCENT_KEY, MAX_BROADCAST_FAIL_PERCENT);
if (broadcastFailPercent < MIN_BROADCAST_FAIL_PERCENT || broadcastFailPercent > MAX_BROADCAST_FAIL_PERCENT) {
logger.info(String.format("The value corresponding to the broadcast.fail.percent parameter must be between 0 and 100. " +
"The current setting is %s, which is reset to 100.", broadcastFailPercent));
logger.info(String.format(
"The value corresponding to the broadcast.fail.percent parameter must be between 0 and 100. "
+ "The current setting is %s, which is reset to 100.",
broadcastFailPercent));
broadcastFailPercent = MAX_BROADCAST_FAIL_PERCENT;
}
@ -72,17 +77,29 @@ public class BroadcastClusterInvoker<T> extends AbstractClusterInvoker<T> {
Invoker<T> invoker = invokers.get(i);
RpcContext.RestoreContext restoreContext = new RpcContext.RestoreContext();
try {
RpcInvocation subInvocation = new RpcInvocation(invocation.getTargetServiceUniqueName(),
invocation.getServiceModel(), invocation.getMethodName(), invocation.getServiceName(), invocation.getProtocolServiceKey(),
invocation.getParameterTypes(), invocation.getArguments(), invocation.copyObjectAttachments(),
invocation.getInvoker(), Collections.synchronizedMap(new HashMap<>(invocation.getAttributes())),
invocation instanceof RpcInvocation ? ((RpcInvocation) invocation).getInvokeMode() : null);
RpcInvocation subInvocation = new RpcInvocation(
invocation.getTargetServiceUniqueName(),
invocation.getServiceModel(),
invocation.getMethodName(),
invocation.getServiceName(),
invocation.getProtocolServiceKey(),
invocation.getParameterTypes(),
invocation.getArguments(),
invocation.copyObjectAttachments(),
invocation.getInvoker(),
Collections.synchronizedMap(new HashMap<>(invocation.getAttributes())),
invocation instanceof RpcInvocation ? ((RpcInvocation) invocation).getInvokeMode() : null);
result = invokeWithContext(invoker, subInvocation);
if (null != result && result.hasException()) {
Throwable resultException = result.getException();
if (null != resultException) {
exception = getRpcException(result.getException());
logger.warn(CLUSTER_ERROR_RESPONSE,"provider return error response","",exception.getMessage(),exception);
logger.warn(
CLUSTER_ERROR_RESPONSE,
"provider return error response",
"",
exception.getMessage(),
exception);
failIndex++;
if (failIndex == failThresholdIndex) {
break;
@ -91,7 +108,12 @@ public class BroadcastClusterInvoker<T> extends AbstractClusterInvoker<T> {
}
} catch (Throwable e) {
exception = getRpcException(e);
logger.warn(CLUSTER_ERROR_RESPONSE,"provider return error response","",exception.getMessage(),exception);
logger.warn(
CLUSTER_ERROR_RESPONSE,
"provider return error response",
"",
exception.getMessage(),
exception);
failIndex++;
if (failIndex == failThresholdIndex) {
break;
@ -106,14 +128,15 @@ public class BroadcastClusterInvoker<T> extends AbstractClusterInvoker<T> {
if (exception != null) {
if (failIndex == failThresholdIndex) {
if (logger.isDebugEnabled()) {
logger.debug(
String.format("The number of BroadcastCluster call failures has reached the threshold %s", failThresholdIndex));
logger.debug(String.format(
"The number of BroadcastCluster call failures has reached the threshold %s",
failThresholdIndex));
}
} else {
if (logger.isDebugEnabled()) {
logger.debug(String.format("The number of BroadcastCluster call failures has not reached the threshold %s, fail size is %s",
failThresholdIndex, failIndex));
logger.debug(String.format(
"The number of BroadcastCluster call failures has not reached the threshold %s, fail size is %s",
failThresholdIndex, failIndex));
}
}
throw exception;

View File

@ -26,7 +26,6 @@ import java.util.Map;
import static org.apache.dubbo.common.constants.CommonConstants.URL_MERGE_PROCESSOR_KEY;
/**
* ClusterUtils
*/
@ -45,9 +44,13 @@ public class ClusterUtils implements ScopeModelAware {
ProviderURLMergeProcessor providerUrlMergeProcessor;
if (StringUtils.isNotEmpty(ump)) {
providerUrlMergeProcessor = applicationModel.getExtensionLoader(ProviderURLMergeProcessor.class).getExtension(ump);
providerUrlMergeProcessor = applicationModel
.getExtensionLoader(ProviderURLMergeProcessor.class)
.getExtension(ump);
} else {
providerUrlMergeProcessor = applicationModel.getExtensionLoader(ProviderURLMergeProcessor.class).getExtension("default");
providerUrlMergeProcessor = applicationModel
.getExtensionLoader(ProviderURLMergeProcessor.class)
.getExtension("default");
}
return providerUrlMergeProcessor.mergeUrl(remoteUrl, localMap);
@ -58,13 +61,15 @@ public class ClusterUtils implements ScopeModelAware {
ProviderURLMergeProcessor providerUrlMergeProcessor;
if (StringUtils.isNotEmpty(ump)) {
providerUrlMergeProcessor = applicationModel.getExtensionLoader(ProviderURLMergeProcessor.class).getExtension(ump);
providerUrlMergeProcessor = applicationModel
.getExtensionLoader(ProviderURLMergeProcessor.class)
.getExtension(ump);
} else {
providerUrlMergeProcessor = applicationModel.getExtensionLoader(ProviderURLMergeProcessor.class).getExtension("default");
providerUrlMergeProcessor = applicationModel
.getExtensionLoader(ProviderURLMergeProcessor.class)
.getExtension("default");
}
return providerUrlMergeProcessor.mergeLocalParams(localMap);
}
}

View File

@ -26,11 +26,10 @@ import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster;
*/
public class FailbackCluster extends AbstractCluster {
public final static String NAME = "failback";
public static final String NAME = "failback";
@Override
public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
return new FailbackClusterInvoker<>(directory);
}
}

View File

@ -53,7 +53,8 @@ import static org.apache.dubbo.rpc.cluster.Constants.FAIL_BACK_TASKS_KEY;
*/
public class FailbackClusterInvoker<T> extends AbstractClusterInvoker<T> {
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(FailbackClusterInvoker.class);
private static final ErrorTypeAwareLogger logger =
LoggerFactory.getErrorTypeAwareLogger(FailbackClusterInvoker.class);
private static final long RETRY_FAILED_PERIOD = 5;
@ -81,27 +82,41 @@ public class FailbackClusterInvoker<T> extends AbstractClusterInvoker<T> {
failbackTasks = failbackTasksConfig;
}
private void addFailed(LoadBalance loadbalance, Invocation invocation, List<Invoker<T>> invokers, Invoker<T> lastInvoker, URL consumerUrl) {
private void addFailed(
LoadBalance loadbalance,
Invocation invocation,
List<Invoker<T>> invokers,
Invoker<T> lastInvoker,
URL consumerUrl) {
if (failTimer == null) {
synchronized (this) {
if (failTimer == null) {
failTimer = new HashedWheelTimer(
new NamedThreadFactory("failback-cluster-timer", true),
1,
TimeUnit.SECONDS, 32, failbackTasks);
new NamedThreadFactory("failback-cluster-timer", true),
1,
TimeUnit.SECONDS,
32,
failbackTasks);
}
}
}
RetryTimerTask retryTimerTask = new RetryTimerTask(loadbalance, invocation, invokers, lastInvoker, retries, RETRY_FAILED_PERIOD, consumerUrl);
RetryTimerTask retryTimerTask = new RetryTimerTask(
loadbalance, invocation, invokers, lastInvoker, retries, RETRY_FAILED_PERIOD, consumerUrl);
try {
failTimer.newTimeout(retryTimerTask, RETRY_FAILED_PERIOD, TimeUnit.SECONDS);
} catch (Throwable e) {
logger.error(CLUSTER_TIMER_RETRY_FAILED,"add newTimeout exception","","Failback background works error, invocation->" + invocation + ", exception: " + e.getMessage(),e);
logger.error(
CLUSTER_TIMER_RETRY_FAILED,
"add newTimeout exception",
"",
"Failback background works error, invocation->" + invocation + ", exception: " + e.getMessage(),
e);
}
}
@Override
protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance)
throws RpcException {
Invoker<T> invoker = null;
URL consumerUrl = RpcContext.getServiceContext().getConsumerUrl();
try {
@ -110,10 +125,14 @@ public class FailbackClusterInvoker<T> extends AbstractClusterInvoker<T> {
// Then the serviceContext will be cleared after the call is completed.
return invokeWithContextAsync(invoker, invocation, consumerUrl);
} catch (Throwable e) {
logger.error(CLUSTER_FAILED_INVOKE_SERVICE,"Failback to invoke method and start to retries",
"","Failback to invoke method " + RpcUtils.getMethodName(invocation) +
", wait for retry in background. Ignored exception: "
+ e.getMessage() + ", ",e);
logger.error(
CLUSTER_FAILED_INVOKE_SERVICE,
"Failback to invoke method and start to retries",
"",
"Failback to invoke method " + RpcUtils.getMethodName(invocation)
+ ", wait for retry in background. Ignored exception: "
+ e.getMessage() + ", ",
e);
if (retries > 0) {
addFailed(loadbalance, invocation, invokers, invoker, consumerUrl);
}
@ -150,8 +169,14 @@ public class FailbackClusterInvoker<T> extends AbstractClusterInvoker<T> {
*/
private int retriedTimes = 0;
RetryTimerTask(LoadBalance loadbalance, Invocation invocation, List<Invoker<T>> invokers, Invoker<T> lastInvoker,
int retries, long tick, URL consumerUrl) {
RetryTimerTask(
LoadBalance loadbalance,
Invocation invocation,
List<Invoker<T>> invokers,
Invoker<T> lastInvoker,
int retries,
long tick,
URL consumerUrl) {
this.loadbalance = loadbalance;
this.invocation = invocation;
this.invokers = invokers;
@ -164,15 +189,28 @@ public class FailbackClusterInvoker<T> extends AbstractClusterInvoker<T> {
@Override
public void run(Timeout timeout) {
try {
logger.info("Attempt to retry to invoke method " + RpcUtils.getMethodName(invocation) +
". The total will retry " + retries + " times, the current is the " + retriedTimes + " retry");
Invoker<T> retryInvoker = select(loadbalance, invocation, invokers, Collections.singletonList(lastInvoker));
logger.info("Attempt to retry to invoke method " + RpcUtils.getMethodName(invocation)
+ ". The total will retry " + retries + " times, the current is the " + retriedTimes
+ " retry");
Invoker<T> retryInvoker =
select(loadbalance, invocation, invokers, Collections.singletonList(lastInvoker));
lastInvoker = retryInvoker;
invokeWithContextAsync(retryInvoker, invocation, consumerUrl);
} catch (Throwable e) {
logger.error(CLUSTER_FAILED_INVOKE_SERVICE,"Failed retry to invoke method","","Failed retry to invoke method " + RpcUtils.getMethodName(invocation) + ", waiting again.",e);
logger.error(
CLUSTER_FAILED_INVOKE_SERVICE,
"Failed retry to invoke method",
"",
"Failed retry to invoke method " + RpcUtils.getMethodName(invocation) + ", waiting again.",
e);
if ((++retriedTimes) >= retries) {
logger.error(CLUSTER_FAILED_INVOKE_SERVICE,"Failed retry to invoke method and retry times exceed threshold","","Failed retry times exceed threshold (" + retries + "), We have to abandon, invocation->" + invocation,e);
logger.error(
CLUSTER_FAILED_INVOKE_SERVICE,
"Failed retry to invoke method and retry times exceed threshold",
"",
"Failed retry times exceed threshold (" + retries + "), We have to abandon, invocation->"
+ invocation,
e);
} else {
rePut(timeout);
}

View File

@ -26,11 +26,10 @@ import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster;
*/
public class FailfastCluster extends AbstractCluster {
public final static String NAME = "failfast";
public static final String NAME = "failfast";
@Override
public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
return new FailfastClusterInvoker<>(directory);
}
}

View File

@ -41,7 +41,8 @@ public class FailfastClusterInvoker<T> extends AbstractClusterInvoker<T> {
}
@Override
public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance)
throws RpcException {
Invoker<T> invoker = select(loadbalance, invocation, invokers, null);
try {
return invokeWithContext(invoker, invocation);
@ -49,13 +50,16 @@ public class FailfastClusterInvoker<T> extends AbstractClusterInvoker<T> {
if (e instanceof RpcException && ((RpcException) e).isBiz()) { // biz exception.
throw (RpcException) e;
}
throw new RpcException(e instanceof RpcException ? ((RpcException) e).getCode() : 0,
"Failfast invoke providers " + invoker.getUrl() + " " + loadbalance.getClass().getSimpleName()
+ " for service " + getInterface().getName()
+ " method " + RpcUtils.getMethodName(invocation) + " on consumer " + NetUtils.getLocalHost()
+ " use dubbo version " + Version.getVersion()
+ ", but no luck to perform the invocation. Last error is: " + e.getMessage(),
e.getCause() != null ? e.getCause() : e);
throw new RpcException(
e instanceof RpcException ? ((RpcException) e).getCode() : 0,
"Failfast invoke providers " + invoker.getUrl() + " "
+ loadbalance.getClass().getSimpleName()
+ " for service " + getInterface().getName()
+ " method " + RpcUtils.getMethodName(invocation) + " on consumer "
+ NetUtils.getLocalHost()
+ " use dubbo version " + Version.getVersion()
+ ", but no luck to perform the invocation. Last error is: " + e.getMessage(),
e.getCause() != null ? e.getCause() : e);
}
}
}

View File

@ -26,11 +26,10 @@ import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster;
*/
public class FailoverCluster extends AbstractCluster {
public final static String NAME = "failover";
public static final String NAME = "failover";
@Override
public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
return new FailoverClusterInvoker<>(directory);
}
}

View File

@ -47,7 +47,8 @@ import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_FAIL
*/
public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(FailoverClusterInvoker.class);
private static final ErrorTypeAwareLogger logger =
LoggerFactory.getErrorTypeAwareLogger(FailoverClusterInvoker.class);
public FailoverClusterInvoker(Directory<T> directory) {
super(directory);
@ -55,7 +56,8 @@ public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance)
throws RpcException {
List<Invoker<T>> copyInvokers = invokers;
String methodName = RpcUtils.getMethodName(invocation);
int len = calculateInvokeTimes(methodName);
@ -64,8 +66,8 @@ public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyInvokers.size()); // invoked invokers.
Set<String> providers = new HashSet<String>(len);
for (int i = 0; i < len; i++) {
//Reselect before retry to avoid a change of candidate `invokers`.
//NOTE: if `invokers` changed, then `invoked` also lose accuracy.
// Reselect before retry to avoid a change of candidate `invokers`.
// NOTE: if `invokers` changed, then `invoked` also lose accuracy.
if (i > 0) {
checkWhetherDestroyed();
copyInvokers = list(invocation);
@ -79,15 +81,22 @@ public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
try {
Result result = invokeWithContext(invoker, invocation);
if (le != null && logger.isWarnEnabled()) {
logger.warn(CLUSTER_FAILED_MULTIPLE_RETRIES,"failed to retry do invoke","","Although retry the method " + methodName
+ " in the service " + getInterface().getName()
+ " was successful by the provider " + invoker.getUrl().getAddress()
+ ", but there have been failed providers " + providers
+ " (" + providers.size() + "/" + copyInvokers.size()
+ ") from the registry " + directory.getUrl().getAddress()
+ " on the consumer " + NetUtils.getLocalHost()
+ " using the dubbo version " + Version.getVersion() + ". Last error is: "
+ le.getMessage(),le);
logger.warn(
CLUSTER_FAILED_MULTIPLE_RETRIES,
"failed to retry do invoke",
"",
"Although retry the method " + methodName
+ " in the service " + getInterface().getName()
+ " was successful by the provider "
+ invoker.getUrl().getAddress()
+ ", but there have been failed providers " + providers
+ " (" + providers.size() + "/" + copyInvokers.size()
+ ") from the registry "
+ directory.getUrl().getAddress()
+ " on the consumer " + NetUtils.getLocalHost()
+ " using the dubbo version " + Version.getVersion() + ". Last error is: "
+ le.getMessage(),
le);
}
success = true;
return result;
@ -104,14 +113,17 @@ public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
}
}
}
throw new RpcException(le.getCode(), "Failed to invoke the method "
+ methodName + " in the service " + getInterface().getName()
+ ". Tried " + len + " times of the providers " + providers
+ " (" + providers.size() + "/" + copyInvokers.size()
+ ") from the registry " + directory.getUrl().getAddress()
+ " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version "
+ Version.getVersion() + ". Last error is: "
+ le.getMessage(), le.getCause() != null ? le.getCause() : le);
throw new RpcException(
le.getCode(),
"Failed to invoke the method "
+ methodName + " in the service " + getInterface().getName()
+ ". Tried " + len + " times of the providers " + providers
+ " (" + providers.size() + "/" + copyInvokers.size()
+ ") from the registry " + directory.getUrl().getAddress()
+ " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version "
+ Version.getVersion() + ". Last error is: "
+ le.getMessage(),
le.getCause() != null ? le.getCause() : le);
}
private int calculateInvokeTimes(String methodName) {
@ -128,5 +140,4 @@ public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
return len;
}
}

View File

@ -26,11 +26,10 @@ import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster;
*/
public class FailsafeCluster extends AbstractCluster {
public final static String NAME = "failsafe";
public static final String NAME = "failsafe";
@Override
public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
return new FailsafeClusterInvoker<>(directory);
}
}

View File

@ -38,19 +38,26 @@ import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_ERRO
*
*/
public class FailsafeClusterInvoker<T> extends AbstractClusterInvoker<T> {
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(FailsafeClusterInvoker.class);
private static final ErrorTypeAwareLogger logger =
LoggerFactory.getErrorTypeAwareLogger(FailsafeClusterInvoker.class);
public FailsafeClusterInvoker(Directory<T> directory) {
super(directory);
}
@Override
public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance)
throws RpcException {
try {
Invoker<T> invoker = select(loadbalance, invocation, invokers, null);
return invokeWithContext(invoker, invocation);
} catch (Throwable e) {
logger.error(CLUSTER_ERROR_RESPONSE,"Failsafe for provider exception","","Failsafe ignore exception: " + e.getMessage(),e);
logger.error(
CLUSTER_ERROR_RESPONSE,
"Failsafe for provider exception",
"",
"Failsafe ignore exception: " + e.getMessage(),
e);
return AsyncRpcResult.newDefaultAsyncResult(null, null, invocation); // ignore
}
}

View File

@ -26,11 +26,10 @@ import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster;
*/
public class ForkingCluster extends AbstractCluster {
public final static String NAME = "forking";
public static final String NAME = "forking";
@Override
public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
return new ForkingClusterInvoker<>(directory);
}
}

View File

@ -59,13 +59,18 @@ public class ForkingClusterInvoker<T> extends AbstractClusterInvoker<T> {
public ForkingClusterInvoker(Directory<T> directory) {
super(directory);
executor = directory.getUrl().getOrDefaultFrameworkModel().getBeanFactory()
.getBean(FrameworkExecutorRepository.class).getSharedExecutor();
executor = directory
.getUrl()
.getOrDefaultFrameworkModel()
.getBeanFactory()
.getBean(FrameworkExecutorRepository.class)
.getSharedExecutor();
}
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public Result doInvoke(final Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
public Result doInvoke(final Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance)
throws RpcException {
try {
final List<Invoker<T>> selected;
final int forks = getUrl().getParameter(FORKS_KEY, DEFAULT_FORKS);
@ -77,7 +82,7 @@ public class ForkingClusterInvoker<T> extends AbstractClusterInvoker<T> {
while (selected.size() < forks) {
Invoker<T> invoker = select(loadbalance, invocation, invokers, selected);
if (!selected.contains(invoker)) {
//Avoid add the same invoker several times.
// Avoid add the same invoker several times.
selected.add(invoker);
}
}
@ -87,34 +92,43 @@ public class ForkingClusterInvoker<T> extends AbstractClusterInvoker<T> {
final BlockingQueue<Object> ref = new LinkedBlockingQueue<>(1);
selected.forEach(invoker -> {
URL consumerUrl = RpcContext.getServiceContext().getConsumerUrl();
CompletableFuture.<Object>supplyAsync(() -> {
if (ref.size() > 0) {
return null;
}
return invokeWithContextAsync(invoker, invocation, consumerUrl);
}, executor).whenComplete((v, t) -> {
if (t == null) {
ref.offer(v);
} else {
int value = count.incrementAndGet();
if (value >= selected.size()) {
ref.offer(t);
}
}
});
CompletableFuture.<Object>supplyAsync(
() -> {
if (ref.size() > 0) {
return null;
}
return invokeWithContextAsync(invoker, invocation, consumerUrl);
},
executor)
.whenComplete((v, t) -> {
if (t == null) {
ref.offer(v);
} else {
int value = count.incrementAndGet();
if (value >= selected.size()) {
ref.offer(t);
}
}
});
});
try {
Object ret = ref.poll(timeout, TimeUnit.MILLISECONDS);
if (ret instanceof Throwable) {
Throwable e = ret instanceof CompletionException ? ((CompletionException) ret).getCause() : (Throwable) ret;
throw new RpcException(e instanceof RpcException ? ((RpcException) e).getCode() : RpcException.UNKNOWN_EXCEPTION,
"Failed to forking invoke provider " + selected + ", but no luck to perform the invocation. " +
"Last error is: " + e.getMessage(), e.getCause() != null ? e.getCause() : e);
Throwable e = ret instanceof CompletionException
? ((CompletionException) ret).getCause()
: (Throwable) ret;
throw new RpcException(
e instanceof RpcException ? ((RpcException) e).getCode() : RpcException.UNKNOWN_EXCEPTION,
"Failed to forking invoke provider " + selected
+ ", but no luck to perform the invocation. " + "Last error is: " + e.getMessage(),
e.getCause() != null ? e.getCause() : e);
}
return (Result) ret;
} catch (InterruptedException e) {
throw new RpcException("Failed to forking invoke provider " + selected + ", " +
"but no luck to perform the invocation. Last error is: " + e.getMessage(), e);
throw new RpcException(
"Failed to forking invoke provider " + selected + ", "
+ "but no luck to perform the invocation. Last error is: " + e.getMessage(),
e);
}
} finally {
// clear attachments which is binding to current thread.

View File

@ -43,7 +43,6 @@ import static org.apache.dubbo.common.constants.CommonConstants.THREAD_NAME_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
public class DefaultProviderURLMergeProcessor implements ProviderURLMergeProcessor {
@Override
@ -104,14 +103,18 @@ public class DefaultProviderURLMergeProcessor implements ProviderURLMergeProcess
// Combine filters and listeners on Provider and Consumer
String remoteFilter = remoteMap.get(REFERENCE_FILTER_KEY);
String localFilter = copyOfLocalMap.get(REFERENCE_FILTER_KEY);
if (remoteFilter != null && remoteFilter.length() > 0
&& localFilter != null && localFilter.length() > 0) {
if (remoteFilter != null
&& remoteFilter.length() > 0
&& localFilter != null
&& localFilter.length() > 0) {
map.put(REFERENCE_FILTER_KEY, remoteFilter + "," + localFilter);
}
String remoteListener = remoteMap.get(INVOKER_LISTENER_KEY);
String localListener = copyOfLocalMap.get(INVOKER_LISTENER_KEY);
if (remoteListener != null && remoteListener.length() > 0
&& localListener != null && localListener.length() > 0) {
if (remoteListener != null
&& remoteListener.length() > 0
&& localListener != null
&& localListener.length() > 0) {
map.put(INVOKER_LISTENER_KEY, remoteListener + "," + localListener);
}
}
@ -119,5 +122,4 @@ public class DefaultProviderURLMergeProcessor implements ProviderURLMergeProcess
return remoteUrl.clearParameters().addParameters(map);
}
}

View File

@ -23,11 +23,10 @@ import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster;
public class ZoneAwareCluster extends AbstractCluster {
public final static String NAME = "zone-aware";
public static final String NAME = "zone-aware";
@Override
protected <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
return new ZoneAwareClusterInvoker<T>(directory);
}
}

View File

@ -55,7 +55,8 @@ public class ZoneAwareClusterInvoker<T> extends AbstractClusterInvoker<T> {
public ZoneAwareClusterInvoker(Directory<T> directory) {
super(directory);
ExtensionLoader<ZoneDetector> loader = directory.getConsumerUrl().getOrDefaultApplicationModel().getExtensionLoader(ZoneDetector.class);
ExtensionLoader<ZoneDetector> loader =
directory.getConsumerUrl().getOrDefaultApplicationModel().getExtensionLoader(ZoneDetector.class);
if (loader.hasExtension("default")) {
zoneDetector = loader.getExtension("default");
}
@ -63,12 +64,13 @@ public class ZoneAwareClusterInvoker<T> extends AbstractClusterInvoker<T> {
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
// First, pick the invoker (XXXClusterInvoker) that comes from the local registry, distinguish by a 'preferred' key.
public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance)
throws RpcException {
// First, pick the invoker (XXXClusterInvoker) that comes from the local registry, distinguish by a 'preferred'
// key.
for (Invoker<T> invoker : invokers) {
ClusterInvoker<T> clusterInvoker = (ClusterInvoker<T>) invoker;
if (clusterInvoker.isAvailable() && clusterInvoker.getRegistryUrl()
.getParameter(PREFERRED_KEY, false)) {
if (clusterInvoker.isAvailable() && clusterInvoker.getRegistryUrl().getParameter(PREFERRED_KEY, false)) {
return clusterInvoker.invoke(invocation);
}
}
@ -85,25 +87,32 @@ public class ZoneAwareClusterInvoker<T> extends AbstractClusterInvoker<T> {
if (StringUtils.isNotEmpty(zone)) {
for (Invoker<T> invoker : invokers) {
ClusterInvoker<T> clusterInvoker = (ClusterInvoker<T>) invoker;
if (clusterInvoker.isAvailable() && zone.equals(clusterInvoker.getRegistryUrl().getParameter(ZONE_KEY))) {
if (clusterInvoker.isAvailable()
&& zone.equals(clusterInvoker.getRegistryUrl().getParameter(ZONE_KEY))) {
return clusterInvoker.invoke(invocation);
}
}
if (StringUtils.isNotEmpty(force) && "true".equalsIgnoreCase(force)) {
throw new IllegalStateException("No registry instance in zone or no available providers in the registry, zone: "
+ zone
+ ", registries: " + invokers.stream().map(invoker -> ((ClusterInvoker<T>) invoker).getRegistryUrl().toString()).collect(Collectors.joining(",")));
throw new IllegalStateException(
"No registry instance in zone or no available providers in the registry, zone: "
+ zone
+ ", registries: "
+ invokers.stream()
.map(invoker -> ((ClusterInvoker<T>) invoker)
.getRegistryUrl()
.toString())
.collect(Collectors.joining(",")));
}
}
// load balance among all registries, with registry weight count in.
Invoker<T> balancedInvoker = select(loadbalance, invocation, invokers, null);
if (balancedInvoker!=null && balancedInvoker.isAvailable()) {
if (balancedInvoker != null && balancedInvoker.isAvailable()) {
return balancedInvoker.invoke(invocation);
}
// If none of the invokers has a preferred signal or is picked by the loadbalancer, pick the first one available.
// If none of the invokers has a preferred signal or is picked by the loadbalancer, pick the first one
// available.
for (Invoker<T> invoker : invokers) {
ClusterInvoker<T> clusterInvoker = (ClusterInvoker<T>) invoker;
if (clusterInvoker.isAvailable()) {
@ -113,5 +122,4 @@ public class ZoneAwareClusterInvoker<T> extends AbstractClusterInvoker<T> {
throw new RpcException("No provider available in " + invokers);
}
}

View File

@ -45,7 +45,10 @@ public abstract class AbstractCluster implements Cluster {
private <T> Invoker<T> buildClusterInterceptors(AbstractClusterInvoker<T> clusterInvoker) {
AbstractClusterInvoker<T> last = buildInterceptorInvoker(new ClusterFilterInvoker<>(clusterInvoker));
if (Boolean.parseBoolean(ConfigurationUtils.getProperty(clusterInvoker.getDirectory().getConsumerUrl().getScopeModel(), CLUSTER_INTERCEPTOR_COMPATIBLE_KEY, "false"))) {
if (Boolean.parseBoolean(ConfigurationUtils.getProperty(
clusterInvoker.getDirectory().getConsumerUrl().getScopeModel(),
CLUSTER_INTERCEPTOR_COMPATIBLE_KEY,
"false"))) {
return build27xCompatibleClusterInterceptors(clusterInvoker, last);
}
return last;
@ -61,7 +64,10 @@ public abstract class AbstractCluster implements Cluster {
}
private <T> AbstractClusterInvoker<T> buildInterceptorInvoker(AbstractClusterInvoker<T> invoker) {
List<InvocationInterceptorBuilder> builders = ScopeModelUtil.getApplicationModel(invoker.getUrl().getScopeModel()).getExtensionLoader(InvocationInterceptorBuilder.class).getActivateExtensions();
List<InvocationInterceptorBuilder> builders = ScopeModelUtil.getApplicationModel(
invoker.getUrl().getScopeModel())
.getExtensionLoader(InvocationInterceptorBuilder.class)
.getActivateExtensions();
if (CollectionUtils.isEmpty(builders)) {
return invoker;
}
@ -74,13 +80,17 @@ public abstract class AbstractCluster implements Cluster {
private final ClusterInvoker<T> filterInvoker;
public ClusterFilterInvoker(AbstractClusterInvoker<T> invoker) {
List<FilterChainBuilder> builders = ScopeModelUtil.getApplicationModel(invoker.getUrl().getScopeModel()).getExtensionLoader(FilterChainBuilder.class).getActivateExtensions();
List<FilterChainBuilder> builders = ScopeModelUtil.getApplicationModel(
invoker.getUrl().getScopeModel())
.getExtensionLoader(FilterChainBuilder.class)
.getActivateExtensions();
if (CollectionUtils.isEmpty(builders)) {
filterInvoker = invoker;
} else {
ClusterInvoker<T> tmpInvoker = invoker;
for (FilterChainBuilder builder : builders) {
tmpInvoker = builder.buildClusterInvokerChain(tmpInvoker, REFERENCE_FILTER_KEY, CommonConstants.CONSUMER);
tmpInvoker = builder.buildClusterInvokerChain(
tmpInvoker, REFERENCE_FILTER_KEY, CommonConstants.CONSUMER);
}
filterInvoker = tmpInvoker;
}
@ -96,8 +106,6 @@ public abstract class AbstractCluster implements Cluster {
return filterInvoker.getDirectory();
}
@Override
public URL getRegistryUrl() {
return filterInvoker.getRegistryUrl();
@ -118,8 +126,9 @@ public abstract class AbstractCluster implements Cluster {
* Use ClusterInvoker<T> to replace AbstractClusterInvoker<T> in the future.
*/
@Override
protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
return null;
protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance)
throws RpcException {
return null;
}
public ClusterInvoker<T> getFilterInvoker() {
@ -130,10 +139,12 @@ public abstract class AbstractCluster implements Cluster {
static class InvocationInterceptorInvoker<T> extends AbstractClusterInvoker<T> {
private ClusterInvoker<T> interceptorInvoker;
public InvocationInterceptorInvoker(AbstractClusterInvoker<T> invoker, List<InvocationInterceptorBuilder> builders) {
public InvocationInterceptorInvoker(
AbstractClusterInvoker<T> invoker, List<InvocationInterceptorBuilder> builders) {
ClusterInvoker<T> tmpInvoker = invoker;
for (InvocationInterceptorBuilder builder : builders) {
tmpInvoker = builder.buildClusterInterceptorChain(tmpInvoker, INVOCATION_INTERCEPTOR_KEY, CommonConstants.CONSUMER);
tmpInvoker = builder.buildClusterInterceptorChain(
tmpInvoker, INVOCATION_INTERCEPTOR_KEY, CommonConstants.CONSUMER);
}
interceptorInvoker = tmpInvoker;
}
@ -168,14 +179,19 @@ public abstract class AbstractCluster implements Cluster {
* Use ClusterInvoker<T> to replace AbstractClusterInvoker<T> in the future.
*/
@Override
protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance)
throws RpcException {
return null;
}
}
@Deprecated
private <T> ClusterInvoker<T> build27xCompatibleClusterInterceptors(AbstractClusterInvoker<T> clusterInvoker, AbstractClusterInvoker<T> last) {
List<ClusterInterceptor> interceptors = ScopeModelUtil.getApplicationModel(clusterInvoker.getUrl().getScopeModel()).getExtensionLoader(ClusterInterceptor.class).getActivateExtensions();
private <T> ClusterInvoker<T> build27xCompatibleClusterInterceptors(
AbstractClusterInvoker<T> clusterInvoker, AbstractClusterInvoker<T> last) {
List<ClusterInterceptor> interceptors = ScopeModelUtil.getApplicationModel(
clusterInvoker.getUrl().getScopeModel())
.getExtensionLoader(ClusterInterceptor.class)
.getActivateExtensions();
if (!interceptors.isEmpty()) {
for (int i = interceptors.size() - 1; i >= 0; i--) {
@ -194,9 +210,10 @@ public abstract class AbstractCluster implements Cluster {
private final ClusterInterceptor interceptor;
private final AbstractClusterInvoker<T> next;
public InterceptorInvokerNode(AbstractClusterInvoker<T> clusterInvoker,
ClusterInterceptor interceptor,
AbstractClusterInvoker<T> next) {
public InterceptorInvokerNode(
AbstractClusterInvoker<T> clusterInvoker,
ClusterInterceptor interceptor,
AbstractClusterInvoker<T> next) {
this.clusterInvoker = clusterInvoker;
this.interceptor = interceptor;
this.next = next;
@ -257,11 +274,10 @@ public abstract class AbstractCluster implements Cluster {
}
@Override
protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance)
throws RpcException {
// The only purpose is to build an interceptor chain, so the cluster related logic doesn't matter.
return null;
}
}
}

View File

@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.cluster.support.wrapper;
import org.apache.dubbo.common.URL;
@ -62,7 +61,6 @@ public class ScopeClusterInvoker<T> implements ClusterInvoker<T>, ExporterChange
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(ScopeClusterInvoker.class);
private final Object createLock = new Object();
private Protocol protocolSPI;
private final Directory<T> directory;
@ -144,26 +142,30 @@ public class ScopeClusterInvoker<T> implements ClusterInvoker<T>, ExporterChange
// When broadcasting, it should be called remotely.
if (isBroadcast()) {
if (logger.isDebugEnabled()) {
logger.debug("Performing broadcast call for method: " + RpcUtils.getMethodName(invocation) + " of service: " + getUrl().getServiceKey());
logger.debug("Performing broadcast call for method: " + RpcUtils.getMethodName(invocation)
+ " of service: " + getUrl().getServiceKey());
}
return invoker.invoke(invocation);
}
if (peerFlag) {
if (logger.isDebugEnabled()) {
logger.debug("Performing point-to-point call for method: " + RpcUtils.getMethodName(invocation) + " of service: " + getUrl().getServiceKey());
logger.debug("Performing point-to-point call for method: " + RpcUtils.getMethodName(invocation)
+ " of service: " + getUrl().getServiceKey());
}
// If it's a point-to-point direct connection, invoke the original Invoker
return invoker.invoke(invocation);
}
if (isInjvmExported()) {
if (logger.isDebugEnabled()) {
logger.debug("Performing local JVM call for method: " + RpcUtils.getMethodName(invocation) + " of service: " + getUrl().getServiceKey());
logger.debug("Performing local JVM call for method: " + RpcUtils.getMethodName(invocation)
+ " of service: " + getUrl().getServiceKey());
}
// If it's exported to the local JVM, invoke the corresponding Invoker
return injvmInvoker.invoke(invocation);
}
if (logger.isDebugEnabled()) {
logger.debug("Performing remote call for method: " + RpcUtils.getMethodName(invocation) + " of service: " + getUrl().getServiceKey());
logger.debug("Performing remote call for method: " + RpcUtils.getMethodName(invocation) + " of service: "
+ getUrl().getServiceKey());
}
// Otherwise, delegate the invocation to the original Invoker
return invoker.invoke(invocation);
@ -179,7 +181,7 @@ public class ScopeClusterInvoker<T> implements ClusterInvoker<T>, ExporterChange
return;
}
if (getUrl().getServiceKey().equals(exporter.getInvoker().getUrl().getServiceKey())
&& exporter.getInvoker().getUrl().getProtocol().equalsIgnoreCase(LOCAL_PROTOCOL)) {
&& exporter.getInvoker().getUrl().getProtocol().equalsIgnoreCase(LOCAL_PROTOCOL)) {
createInjvmInvoker(exporter);
isExported.compareAndSet(false, true);
}
@ -188,7 +190,7 @@ public class ScopeClusterInvoker<T> implements ClusterInvoker<T>, ExporterChange
@Override
public void onExporterChangeUnExport(Exporter<?> exporter) {
if (getUrl().getServiceKey().equals(exporter.getInvoker().getUrl().getServiceKey())
&& exporter.getInvoker().getUrl().getProtocol().equalsIgnoreCase(LOCAL_PROTOCOL)) {
&& exporter.getInvoker().getUrl().getProtocol().equalsIgnoreCase(LOCAL_PROTOCOL)) {
destroyInjvmInvoker();
isExported.compareAndSet(true, false);
}
@ -211,21 +213,26 @@ public class ScopeClusterInvoker<T> implements ClusterInvoker<T>, ExporterChange
return;
}
// Check if the service has been exported through Injvm protocol
if (injvmInvoker == null && LOCAL_PROTOCOL.equalsIgnoreCase(getRegistryUrl().getProtocol())) {
if (injvmInvoker == null
&& LOCAL_PROTOCOL.equalsIgnoreCase(getRegistryUrl().getProtocol())) {
injvmInvoker = invoker;
isExported.compareAndSet(false, true);
injvmFlag = true;
return;
}
// Check if the service has been exported through Injvm protocol or the SCOPE_LOCAL parameter is set
if (Boolean.TRUE.toString().equalsIgnoreCase(isInjvm) || SCOPE_LOCAL.equalsIgnoreCase(getUrl().getParameter(SCOPE_KEY))) {
if (Boolean.TRUE.toString().equalsIgnoreCase(isInjvm)
|| SCOPE_LOCAL.equalsIgnoreCase(getUrl().getParameter(SCOPE_KEY))) {
injvmFlag = true;
} else if (isInjvm == null) {
injvmFlag = isNotRemoteOrGeneric();
}
protocolSPI = getUrl().getApplicationModel().getExtensionLoader(Protocol.class).getAdaptiveExtension();
injvmExporterListener = getUrl().getOrDefaultFrameworkModel().getBeanFactory().getBean(InjvmExporterListener.class);
protocolSPI = getUrl().getApplicationModel()
.getExtensionLoader(Protocol.class)
.getAdaptiveExtension();
injvmExporterListener =
getUrl().getOrDefaultFrameworkModel().getBeanFactory().getBean(InjvmExporterListener.class);
injvmExporterListener.addExporterChangeListener(this, getUrl().getServiceKey());
}
@ -235,8 +242,8 @@ public class ScopeClusterInvoker<T> implements ClusterInvoker<T>, ExporterChange
* @return boolean
*/
private boolean isNotRemoteOrGeneric() {
return !SCOPE_REMOTE.equalsIgnoreCase(getUrl().getParameter(SCOPE_KEY)) &&
!getUrl().getParameter(GENERIC_KEY, false);
return !SCOPE_REMOTE.equalsIgnoreCase(getUrl().getParameter(SCOPE_KEY))
&& !getUrl().getParameter(GENERIC_KEY, false);
}
/**
@ -262,15 +269,16 @@ public class ScopeClusterInvoker<T> implements ClusterInvoker<T>, ExporterChange
// When calling locally, determine whether it does not meet the requirements
if (!isExportedValue && (isForceLocal() || localOnce)) {
// If it's supposed to be exported to the local JVM ,but it's not, throw an exception
throw new RpcException("Local service for " + getUrl().getServiceInterface() + " has not been exposed yet!");
throw new RpcException(
"Local service for " + getUrl().getServiceInterface() + " has not been exposed yet!");
}
return isExportedValue && injvmFlag;
}
private boolean isForceLocal() {
return SCOPE_LOCAL.equalsIgnoreCase(getUrl().getParameter(SCOPE_KEY)) ||
Boolean.TRUE.toString().equalsIgnoreCase(getUrl().getParameter(LOCAL_PROTOCOL));
return SCOPE_LOCAL.equalsIgnoreCase(getUrl().getParameter(SCOPE_KEY))
|| Boolean.TRUE.toString().equalsIgnoreCase(getUrl().getParameter(LOCAL_PROTOCOL));
}
/**
@ -280,18 +288,26 @@ public class ScopeClusterInvoker<T> implements ClusterInvoker<T>, ExporterChange
if (injvmInvoker == null) {
synchronized (createLock) {
if (injvmInvoker == null) {
URL url = new ServiceConfigURL(LOCAL_PROTOCOL, NetUtils.getLocalHost(), getUrl().getPort(),
getInterface().getName(), getUrl().getParameters());
URL url = new ServiceConfigURL(
LOCAL_PROTOCOL,
NetUtils.getLocalHost(),
getUrl().getPort(),
getInterface().getName(),
getUrl().getParameters());
url = url.setScopeModel(getUrl().getScopeModel());
url = url.setServiceModel(getUrl().getServiceModel());
DubboServiceAddressURL consumerUrl = new DubboServiceAddressURL(url.getUrlAddress(), url.getUrlParam(),
exporter.getInvoker().getUrl(), null);
DubboServiceAddressURL consumerUrl = new DubboServiceAddressURL(
url.getUrlAddress(),
url.getUrlParam(),
exporter.getInvoker().getUrl(),
null);
Invoker<?> invoker = protocolSPI.refer(getInterface(), consumerUrl);
List<Invoker<?>> invokers = new ArrayList<>();
invokers.add(invoker);
injvmInvoker = Cluster.getCluster(url.getScopeModel(), Cluster.DEFAULT, false).join(new StaticDirectory(url, invokers), true);
injvmInvoker = Cluster.getCluster(url.getScopeModel(), Cluster.DEFAULT, false)
.join(new StaticDirectory(url, invokers), true);
}
}
}
@ -309,11 +325,10 @@ public class ScopeClusterInvoker<T> implements ClusterInvoker<T>, ExporterChange
@Override
public String toString() {
return "ScopeClusterInvoker{" +
"directory=" + directory +
", isExported=" + isExported +
", peerFlag=" + peerFlag +
", injvmFlag=" + injvmFlag +
'}';
return "ScopeClusterInvoker{" + "directory="
+ directory + ", isExported="
+ isExported + ", peerFlag="
+ peerFlag + ", injvmFlag="
+ injvmFlag + '}';
}
}

View File

@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.cluster.support.wrapper;
import org.apache.dubbo.common.extension.Wrapper;
@ -36,8 +35,7 @@ public class ScopeClusterWrapper implements Cluster {
@Override
public <T> Invoker<T> join(Directory<T> directory, boolean buildFilterChain) throws RpcException {
return new ScopeClusterInvoker<>(directory,
this.cluster.join(directory, buildFilterChain));
return new ScopeClusterInvoker<>(directory, this.cluster.join(directory, buildFilterChain));
}
public Cluster getCluster() {

View File

@ -21,13 +21,13 @@ import org.apache.dubbo.rpc.cluster.configurator.absent.AbsentConfigurator;
import org.apache.dubbo.rpc.cluster.configurator.override.OverrideConfigurator;
import org.apache.dubbo.rpc.cluster.configurator.parser.ConfigParser;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
/**
* {@link Configurator}
*/
@ -39,16 +39,17 @@ class ConfiguratorTest {
Optional<List<Configurator>> emptyOptional = Configurator.toConfigurators(Collections.emptyList());
Assertions.assertEquals(Optional.empty(), emptyOptional);
String configData = "[\"override://0.0.0.0/com.xx.Service?category=configurators&timeout=6666&disabled=true&dynamic=false&enabled=true&group=dubbo&priority=2&version=1.0\"" +
", \"absent://0.0.0.0/com.xx.Service?category=configurators&timeout=6666&disabled=true&dynamic=false&enabled=true&group=dubbo&priority=1&version=1.0\" ]";
String configData =
"[\"override://0.0.0.0/com.xx.Service?category=configurators&timeout=6666&disabled=true&dynamic=false&enabled=true&group=dubbo&priority=2&version=1.0\""
+ ", \"absent://0.0.0.0/com.xx.Service?category=configurators&timeout=6666&disabled=true&dynamic=false&enabled=true&group=dubbo&priority=1&version=1.0\" ]";
List<URL> urls = ConfigParser.parseConfigurators(configData);
Optional<List<Configurator>> optionalList = Configurator.toConfigurators(urls);
Assertions.assertTrue(optionalList.isPresent());
List<Configurator> configurators = optionalList.get();
Assertions.assertEquals(configurators.size(), 2);
// The hosts of AbsentConfigurator and OverrideConfigurator are equal, but the priority of OverrideConfigurator is higher
// The hosts of AbsentConfigurator and OverrideConfigurator are equal, but the priority of OverrideConfigurator
// is higher
Assertions.assertTrue(configurators.get(0) instanceof AbsentConfigurator);
Assertions.assertTrue(configurators.get(1) instanceof OverrideConfigurator);
}
}

View File

@ -1,253 +0,0 @@
///*
// * 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.dubbo.rpc.cluster;
//
//
//import java.util.Arrays;
//import java.util.HashMap;
//import java.util.List;
//import java.util.Map;
//import java.util.concurrent.ConcurrentHashMap;
//
//import org.apache.dubbo.common.URL;
//import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
//import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent;
//import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
//import org.apache.dubbo.common.url.component.ServiceConfigURL;
//import org.apache.dubbo.common.utils.CollectionUtils;
//import org.apache.dubbo.rpc.Invoker;
//import org.apache.dubbo.rpc.RpcContext;
//import org.apache.dubbo.rpc.RpcInvocation;
//import org.apache.dubbo.rpc.cluster.filter.DemoService;
//import org.apache.dubbo.rpc.cluster.router.RouterSnapshotSwitcher;
//import org.apache.dubbo.rpc.cluster.router.condition.config.AppStateRouter;
//import org.apache.dubbo.rpc.cluster.router.condition.config.ListenableStateRouter;
//import org.apache.dubbo.rpc.cluster.router.condition.config.ServiceStateRouter;
//import org.apache.dubbo.rpc.cluster.router.mesh.route.MeshAppRuleListener;
//import org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleManager;
//import org.apache.dubbo.rpc.cluster.router.state.BitList;
//import org.apache.dubbo.rpc.model.FrameworkModel;
//import org.junit.jupiter.api.Assertions;
//import org.junit.jupiter.api.Test;
//import org.mockito.Mockito;
//
//import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
//import static org.apache.dubbo.common.constants.CommonConstants.TAG_KEY;
//import static org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleConstants.MESH_RULE_DATA_ID_SUFFIX;
//import static org.mockito.Mockito.when;
//
//class RouterChainTest {
//
// /**
// * verify the router and state router loaded by default
// */
// @Test
// void testBuildRouterChain() {
// RouterChain<DemoService> routerChain = createRouterChanin();
// Assertions.assertEquals(0, routerChain.getRouters().size());
// Assertions.assertEquals(7, routerChain.getStateRouters().size());
// }
//
// private RouterChain<DemoService> createRouterChanin() {
// Map<String, String> parameters = new HashMap<>();
// parameters.put(INTERFACE_KEY, DemoService.class.getName());
// parameters.put("registry", "zookeeper");
// URL url = new ServiceConfigURL("dubbo",
// "127.0.0.1",
// 20881,
// DemoService.class.getName(),
// parameters);
//
// RouterChain<DemoService> routerChain = RouterChain.buildChain(DemoService.class, url);
// return routerChain;
// }
//
// @Test
// void testRoute() {
// RouterChain<DemoService> routerChain = createRouterChanin();
//
// // mockInvoker will be filtered out by MockInvokersSelector
// Invoker<DemoService> mockInvoker = createMockInvoker();
//
// // invoker1 will be filtered out by MeshStateRouter
// Map<String, String> map1 = new HashMap<>();
// map1.put("env-sign", "yyyyyyy");
// Invoker<DemoService> invoker1 = createNormalInvoker(map1);
//
// // invoker2 will be filtered out by TagStateRouter
// Map<String, String> map2 = new HashMap<>();
// map2.put("env-sign", "xxx");
// map2.put("tag1", "hello");
// Invoker<DemoService> invoker2 = createNormalInvoker(map2);
//
// // invoker3 will be filtered out by AppStateRouter
// Map<String, String> map3 = new HashMap<>();
// map3.put("env-sign", "xxx");
// map3.put("tag1", "hello");
// map3.put(TAG_KEY, "TAG_");
// Invoker<DemoService> invoker3 = createNormalInvoker(map3);
//
// // invoker4 will be filtered out by ServiceStateRouter
// Map<String, String> map4 = new HashMap<>();
// map4.put("env-sign", "xxx");
// map4.put("tag1", "hello");
// map4.put(TAG_KEY, "TAG_");
// map4.put("timeout", "5000");
// Invoker<DemoService> invoker4 = createNormalInvoker(map4);
//
// // invoker5 is the only one returned at the end that is not filtered out
// Map<String, String> map5 = new HashMap<>();
// map5.put("env-sign", "xxx");
// map5.put("tag1", "hello");
// map5.put(TAG_KEY, "TAG_");
// map5.put("timeout", "5000");
// map5.put("serialization", "hessian2");
// Invoker<DemoService> invoker5 = createNormalInvoker(map5);
//
// BitList<Invoker<DemoService>> invokers = new BitList<>(Arrays.asList(mockInvoker, invoker1, invoker2, invoker3, invoker4, invoker5));
// routerChain.setInvokers(invokers, () -> {});
//
// // mesh rule for MeshStateRouter
// MeshRuleManager meshRuleManager = mockInvoker.getUrl().getOrDefaultModuleModel().getBeanFactory().getBean(MeshRuleManager.class);
// ConcurrentHashMap<String, MeshAppRuleListener> appRuleListeners = meshRuleManager.getAppRuleListeners();
// MeshAppRuleListener meshAppRuleListener = appRuleListeners.get(invoker1.getUrl().getRemoteApplication());
// ConfigChangedEvent configChangedEvent = new ConfigChangedEvent("demo-route" + MESH_RULE_DATA_ID_SUFFIX, DynamicConfiguration.DEFAULT_GROUP,
// MESH_RULE1 + "---\n" + MESH_RULE2, ConfigChangeType.ADDED);
// meshAppRuleListener.process(configChangedEvent);
//
//
// // condition rule for AppStateRouter&ServiceStateRouter
// ListenableStateRouter serviceRouter = routerChain.getStateRouters().stream().filter(s -> s instanceof ServiceStateRouter).map(s -> (ListenableStateRouter) s).findAny().orElse(null);
// ConfigChangedEvent serviceConditionEvent = new ConfigChangedEvent(DynamicConfiguration.getRuleKey(mockInvoker.getUrl()) + ".condition-router", DynamicConfiguration.DEFAULT_GROUP,
// SERVICE_CONDITION_RULE, ConfigChangeType.ADDED);
// serviceRouter.process(serviceConditionEvent);
//
// ListenableStateRouter appRouter = routerChain.getStateRouters().stream().filter(s -> s instanceof AppStateRouter).map(s -> (ListenableStateRouter) s).findAny().orElse(null);
// ConfigChangedEvent appConditionEvent = new ConfigChangedEvent("app.condition-router", DynamicConfiguration.DEFAULT_GROUP,
// APP_CONDITION_RULE, ConfigChangeType.ADDED);
// appRouter.process(appConditionEvent);
//
// // prepare consumerUrl and RpcInvocation
// URL consumerUrl = URL.valueOf("consumer://localhost/DemoInterface?remote.application=app1");
// RpcInvocation rpcInvocation = new RpcInvocation();
// rpcInvocation.setServiceName("DemoService");
// rpcInvocation.setObjectAttachment("trafficLabel", "xxx");
// rpcInvocation.setObjectAttachment(TAG_KEY, "TAG_");
//
// RpcContext.getServiceContext().setNeedPrintRouterSnapshot(true);
// RouterSnapshotSwitcher routerSnapshotSwitcher = FrameworkModel.defaultModel().getBeanFactory().getBean(RouterSnapshotSwitcher.class);
// routerSnapshotSwitcher.addEnabledService("org.apache.dubbo.demo.DemoService");
// // route
// List<Invoker<DemoService>> result = routerChain.getSingleChain(consumerUrl, invokers, rpcInvocation)
// .route(consumerUrl, invokers, rpcInvocation);
// Assertions.assertEquals(result.size(), 1);
// Assertions.assertTrue(result.contains(invoker5));
//
// String snapshotLog =
// "[ Parent (Input: 6) (Current Node Output: 6) (Chain Node Output: 1) ] Input: localhost:9103,localhost:9103,localhost:9103,localhost:9103,localhost:9103 -> Chain Node Output: localhost:9103...\n" +
// " [ MockInvokersSelector (Input: 6) (Current Node Output: 5) (Chain Node Output: 1) Router message: invocation.need.mock not set. Return normal Invokers. ] Current Node Output: localhost:9103,localhost:9103,localhost:9103,localhost:9103,localhost:9103\n" +
// " [ StandardMeshRuleRouter (Input: 5) (Current Node Output: 4) (Chain Node Output: 1) Router message: Match App: app Subset: isolation ] Current Node Output: localhost:9103,localhost:9103,localhost:9103,localhost:9103\n" +
// " [ TagStateRouter (Input: 4) (Current Node Output: 3) (Chain Node Output: 1) Router message: Disable Tag Router. Reason: tagRouterRule is invalid or disabled ] Current Node Output: localhost:9103,localhost:9103,localhost:9103\n" +
// " [ ServiceStateRouter (Input: 3) (Current Node Output: 3) (Chain Node Output: 1) Router message: null ] Current Node Output: localhost:9103,localhost:9103,localhost:9103\n" +
// " [ ConditionStateRouter (Input: 3) (Current Node Output: 2) (Chain Node Output: 2) Router message: Match return. ] Current Node Output: localhost:9103,localhost:9103\n" +
// " [ ProviderAppStateRouter (Input: 2) (Current Node Output: 2) (Chain Node Output: 1) Router message: Directly return. Reason: Invokers from previous router is empty or conditionRouters is empty. ] Current Node Output: localhost:9103,localhost:9103\n" +
// " [ AppStateRouter (Input: 2) (Current Node Output: 2) (Chain Node Output: 1) Router message: null ] Current Node Output: localhost:9103,localhost:9103\n" +
// " [ ConditionStateRouter (Input: 2) (Current Node Output: 1) (Chain Node Output: 1) Router message: Match return. ] Current Node Output: localhost:9103\n" +
// " [ AppScriptStateRouter (Input: 1) (Current Node Output: 1) (Chain Node Output: 1) Router message: Directly return from script router. Reason: Invokers from previous router is empty or script is not enabled. Script rule is: null ] Current Node Output: localhost:9103";
// String[] snapshot = routerSnapshotSwitcher.cloneSnapshot();
// Assertions.assertTrue(snapshot[0].contains(snapshotLog));
//
// RpcContext.getServiceContext().setNeedPrintRouterSnapshot(false);
// result = routerChain.getSingleChain(consumerUrl, invokers, rpcInvocation)
// .route(consumerUrl, invokers, rpcInvocation);
// Assertions.assertEquals(result.size(), 1);
// Assertions.assertTrue(result.contains(invoker5));
//
// routerChain.destroy();
// Assertions.assertEquals(routerChain.getRouters().size(), 0);
// Assertions.assertEquals(routerChain.getStateRouters().size(), 0);
//
// }
//
// private Invoker<DemoService> createMockInvoker() {
// URL url = URL.valueOf("mock://localhost:9103/DemoInterface?remote.application=app");
// Invoker<DemoService> invoker = Mockito.mock(Invoker.class);
// when(invoker.getUrl()).thenReturn(url);
// return invoker;
// }
//
// private Invoker<DemoService> createNormalInvoker(Map<String, String> parameters) {
// URL url = URL.valueOf("dubbo://localhost:9103/DemoInterface?remote.application=app");
// if (CollectionUtils.isNotEmptyMap(parameters)) {
// url = url.addParameters(parameters);
// }
// Invoker<DemoService> invoker = Mockito.mock(Invoker.class);
// when(invoker.getUrl()).thenReturn(url);
// return invoker;
// }
//
//
// private final static String MESH_RULE1 = "apiVersion: service.dubbo.apache.org/v1alpha1\n" +
// "kind: DestinationRule\n" +
// "metadata: { name: demo-route }\n" +
// "spec:\n" +
// " host: demo\n" +
// " subsets:\n" +
// " - labels: { env-sign: xxx, tag1: hello }\n" +
// " name: isolation\n" +
// " - labels: { env-sign: yyy }\n" +
// " name: testing-trunk\n" +
// " - labels: { env-sign: zzz }\n" +
// " name: testing\n" +
// " trafficPolicy:\n" +
// " loadBalancer: { simple: ROUND_ROBIN }\n" +
// "\n";
//
// private final static String MESH_RULE2 = "apiVersion: service.dubbo.apache.org/v1alpha1\n" +
// "kind: VirtualService\n" +
// "metadata: { name: demo-route }\n" +
// "spec:\n" +
// " dubbo:\n" +
// " - routedetail:\n" +
// " - match:\n" +
// " - attachments: \n" +
// " dubboContext: {trafficLabel: {regex: xxx}}\n" +
// " name: xxx-project\n" +
// " route:\n" +
// " - destination: {host: demo, subset: isolation}\n" +
// " services:\n" +
// " - {regex: DemoService}\n" +
// " hosts: [demo]\n";
//
// private static final String APP_CONDITION_RULE = "scope: application\n" +
// "force: true\n" +
// "runtime: false\n" +
// "enabled: true\n" +
// "priority: 1\n" +
// "key: demo-consumer\n" +
// "conditions:\n" +
// "- => serialization=hessian2";
//
// private static final String SERVICE_CONDITION_RULE = "scope: service\n" +
// "force: true\n" +
// "runtime: false\n" +
// "enabled: true\n" +
// "priority: 1\n" +
// "key: org.apache.dubbo.demo.DemoService\n" +
// "conditions:\n" +
// "- => timeout=5000";
//}

View File

@ -16,7 +16,6 @@
*/
package org.apache.dubbo.rpc.cluster;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.Invocation;
@ -26,13 +25,13 @@ import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import static org.apache.dubbo.rpc.cluster.Constants.CLUSTER_STICKY_KEY;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
@ -42,17 +41,14 @@ class StickyTest {
private List<Invoker<StickyTest>> invokers = new ArrayList<Invoker<StickyTest>>();
private Invoker<StickyTest> invoker1 = mock(Invoker.class);
private Invoker<StickyTest> invoker2 = mock(Invoker.class);
private Invoker<StickyTest> invoker2 = mock(Invoker.class);
private RpcInvocation invocation;
private Directory<StickyTest> dic;
private Result result = new AppResponse();
private StickyClusterInvoker<StickyTest> clusterinvoker = null;
private URL url = URL.valueOf("test://test:11/test?"
+ "&loadbalance=roundrobin"
+ "&" + CLUSTER_STICKY_KEY + "=true"
);
private URL url =
URL.valueOf("test://test:11/test?" + "&loadbalance=roundrobin" + "&" + CLUSTER_STICKY_KEY + "=true");
private int runs = 1;
@BeforeEach
@ -70,7 +66,6 @@ class StickyTest {
invokers.add(invoker2);
clusterinvoker = new StickyClusterInvoker<StickyTest>(dic);
}
@Test
@ -101,7 +96,7 @@ class StickyTest {
@Test
void testMethodsSticky() {
for (int i = 0; i < 100; i++) {//Two different methods should always use the same invoker every time.
for (int i = 0; i < 100; i++) { // Two different methods should always use the same invoker every time.
int count1 = testSticky("method1", true);
int count2 = testSticky("method2", true);
Assertions.assertEquals(count1, count2);
@ -137,7 +132,6 @@ class StickyTest {
return count;
}
static class StickyClusterInvoker<T> extends AbstractClusterInvoker<T> {
private Invoker<T> selectedInvoker;
@ -150,8 +144,8 @@ class StickyTest {
}
@Override
protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers,
LoadBalance loadbalance) throws RpcException {
protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance)
throws RpcException {
Invoker<T> invoker = select(loadbalance, invocation, invokers, null);
selectedInvoker = invoker;
return null;

View File

@ -20,21 +20,21 @@ import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.rpc.cluster.configurator.consts.UrlConstant;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
/**
* OverrideConfiguratorTest
*/
class AbsentConfiguratorTest {
@Test
void testOverrideApplication() {
AbsentConfigurator configurator = new AbsentConfigurator(URL.valueOf("override://foo@0.0.0.0/com.foo.BarService?timeout=200"));
AbsentConfigurator configurator =
new AbsentConfigurator(URL.valueOf("override://foo@0.0.0.0/com.foo.BarService?timeout=200"));
URL url = configurator.configure(URL.valueOf(UrlConstant.URL_CONSUMER));
Assertions.assertEquals("200", url.getParameter("timeout"));
@ -51,7 +51,8 @@ class AbsentConfiguratorTest {
@Test
void testOverrideHost() {
AbsentConfigurator configurator = new AbsentConfigurator(URL.valueOf("override://" + NetUtils.getLocalHost() + "/com.foo.BarService?timeout=200"));
AbsentConfigurator configurator = new AbsentConfigurator(
URL.valueOf("override://" + NetUtils.getLocalHost() + "/com.foo.BarService?timeout=200"));
URL url = configurator.configure(URL.valueOf(UrlConstant.URL_CONSUMER));
Assertions.assertEquals("200", url.getParameter("timeout"));
@ -72,7 +73,8 @@ class AbsentConfiguratorTest {
@Test
void testAbsentForVersion27() {
{
String consumerUrlV27 = "dubbo://172.24.160.179/com.foo.BarService?application=foo&side=consumer&timeout=100";
String consumerUrlV27 =
"dubbo://172.24.160.179/com.foo.BarService?application=foo&side=consumer&timeout=100";
URL consumerConfiguratorUrl = URL.valueOf("absent://0.0.0.0/com.foo.BarService");
Map<String, String> params = new HashMap<>();
@ -95,7 +97,8 @@ class AbsentConfiguratorTest {
}
{
String providerUrlV27 = "dubbo://172.24.160.179:21880/com.foo.BarService?application=foo&side=provider&weight=100";
String providerUrlV27 =
"dubbo://172.24.160.179:21880/com.foo.BarService?application=foo&side=provider&weight=100";
URL providerConfiguratorUrl = URL.valueOf("absent://172.24.160.179:21880/com.foo.BarService");
Map<String, String> params = new HashMap<>();
@ -108,7 +111,8 @@ class AbsentConfiguratorTest {
// Meet the configured conditions:
// same side
// same port
// The host of configuratorUrl is 0.0.0.0 or the host of providerConfiguratorUrl is the same as consumerUrlV27
// The host of configuratorUrl is 0.0.0.0 or the host of providerConfiguratorUrl is the same as
// consumerUrlV27
// same appName
AbsentConfigurator configurator = new AbsentConfigurator(providerConfiguratorUrl);
URL url = configurator.configure(URL.valueOf(providerUrlV27));
@ -116,5 +120,4 @@ class AbsentConfiguratorTest {
Assertions.assertEquals("100", url.getParameter("weight"));
}
}
}

View File

@ -20,12 +20,17 @@ package org.apache.dubbo.rpc.cluster.configurator.consts;
* test case url constant
*/
public class UrlConstant {
public static final String URL_CONSUMER = "dubbo://10.20.153.10:20880/com.foo.BarService?application=foo&side=consumer";
public static final String URL_ONE = "dubbo://10.20.153.10:20880/com.foo.BarService?application=foo&timeout=1000&side=consumer";
public static final String APPLICATION_BAR_SIDE_CONSUMER_11 = "dubbo://10.20.153.11:20880/com.foo.BarService?application=bar&side=consumer";
public static final String TIMEOUT_1000_SIDE_CONSUMER_11 = "dubbo://10.20.153.11:20880/com.foo.BarService?application=bar&timeout=1000&side=consumer";
public static final String URL_CONSUMER =
"dubbo://10.20.153.10:20880/com.foo.BarService?application=foo&side=consumer";
public static final String URL_ONE =
"dubbo://10.20.153.10:20880/com.foo.BarService?application=foo&timeout=1000&side=consumer";
public static final String APPLICATION_BAR_SIDE_CONSUMER_11 =
"dubbo://10.20.153.11:20880/com.foo.BarService?application=bar&side=consumer";
public static final String TIMEOUT_1000_SIDE_CONSUMER_11 =
"dubbo://10.20.153.11:20880/com.foo.BarService?application=bar&timeout=1000&side=consumer";
public static final String SERVICE_TIMEOUT_200 = "override://10.20.153.10/com.foo.BarService?timeout=200";
public static final String APPLICATION_BAR_SIDE_CONSUMER_10 = "dubbo://10.20.153.10:20880/com.foo.BarService?application=bar&side=consumer";
public static final String TIMEOUT_1000_SIDE_CONSUMER_10 = "dubbo://10.20.153.10:20880/com.foo.BarService?application=bar&timeout=1000&side=consumer";
public static final String APPLICATION_BAR_SIDE_CONSUMER_10 =
"dubbo://10.20.153.10:20880/com.foo.BarService?application=bar&side=consumer";
public static final String TIMEOUT_1000_SIDE_CONSUMER_10 =
"dubbo://10.20.153.10:20880/com.foo.BarService?application=bar&timeout=1000&side=consumer";
}

View File

@ -24,13 +24,13 @@ import org.apache.dubbo.rpc.cluster.configurator.parser.model.ConditionMatch;
import org.apache.dubbo.rpc.cluster.configurator.parser.model.ParamMatch;
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.StringMatch;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import static org.apache.dubbo.rpc.cluster.configurator.parser.model.ConfiguratorConfig.MATCH_CONDITION;
/**
@ -40,7 +40,8 @@ class OverrideConfiguratorTest {
@Test
void testOverride_Application() {
OverrideConfigurator configurator = new OverrideConfigurator(URL.valueOf("override://foo@0.0.0.0/com.foo.BarService?timeout=200"));
OverrideConfigurator configurator =
new OverrideConfigurator(URL.valueOf("override://foo@0.0.0.0/com.foo.BarService?timeout=200"));
URL url = configurator.configure(URL.valueOf(UrlConstant.URL_CONSUMER));
Assertions.assertEquals("200", url.getParameter("timeout"));
@ -57,7 +58,8 @@ class OverrideConfiguratorTest {
@Test
void testOverride_Host() {
OverrideConfigurator configurator = new OverrideConfigurator(URL.valueOf("override://" + NetUtils.getLocalHost() + "/com.foo.BarService?timeout=200"));
OverrideConfigurator configurator = new OverrideConfigurator(
URL.valueOf("override://" + NetUtils.getLocalHost() + "/com.foo.BarService?timeout=200"));
URL url = configurator.configure(URL.valueOf(UrlConstant.URL_CONSUMER));
Assertions.assertEquals("200", url.getParameter("timeout"));
@ -65,7 +67,8 @@ class OverrideConfiguratorTest {
url = configurator.configure(URL.valueOf(UrlConstant.URL_ONE));
Assertions.assertEquals("200", url.getParameter("timeout"));
AbsentConfigurator configurator1 = new AbsentConfigurator(URL.valueOf("override://10.20.153.10/com.foo.BarService?timeout=200"));
AbsentConfigurator configurator1 =
new AbsentConfigurator(URL.valueOf("override://10.20.153.10/com.foo.BarService?timeout=200"));
url = configurator1.configure(URL.valueOf(UrlConstant.APPLICATION_BAR_SIDE_CONSUMER_10));
Assertions.assertNull(url.getParameter("timeout"));
@ -78,7 +81,8 @@ class OverrideConfiguratorTest {
@Test
void testOverrideForVersion27() {
{
String consumerUrlV27 = "dubbo://172.24.160.179/com.foo.BarService?application=foo&side=consumer&timeout=100";
String consumerUrlV27 =
"dubbo://172.24.160.179/com.foo.BarService?application=foo&side=consumer&timeout=100";
URL consumerConfiguratorUrl = URL.valueOf("override://0.0.0.0/com.foo.BarService");
Map<String, String> params = new HashMap<>();
@ -100,7 +104,8 @@ class OverrideConfiguratorTest {
}
{
String providerUrlV27 = "dubbo://172.24.160.179:21880/com.foo.BarService?application=foo&side=provider&weight=100";
String providerUrlV27 =
"dubbo://172.24.160.179:21880/com.foo.BarService?application=foo&side=provider&weight=100";
URL providerConfiguratorUrl = URL.valueOf("override://172.24.160.179:21880/com.foo.BarService");
Map<String, String> params = new HashMap<>();
@ -112,13 +117,13 @@ class OverrideConfiguratorTest {
// Meet the configured conditions:
// same side
// same port
// The host of configuratorUrl is 0.0.0.0 or the host of providerConfiguratorUrl is the same as consumerUrlV27
// The host of configuratorUrl is 0.0.0.0 or the host of providerConfiguratorUrl is the same as
// consumerUrlV27
// same appName
OverrideConfigurator configurator = new OverrideConfigurator(providerConfiguratorUrl);
URL url = configurator.configure(URL.valueOf(providerUrlV27));
Assertions.assertEquals(url.getParameter("weight"), "200");
}
}
// Test the version after 2.7
@ -126,7 +131,8 @@ class OverrideConfiguratorTest {
void testOverrideForVersion3() {
// match
{
String consumerUrlV3 = "dubbo://172.24.160.179/com.foo.BarService?match_key=value&application=foo&side=consumer&timeout=100";
String consumerUrlV3 =
"dubbo://172.24.160.179/com.foo.BarService?match_key=value&application=foo&side=consumer&timeout=100";
URL consumerConfiguratorUrl = URL.valueOf("override://0.0.0.0/com.foo.BarService");
Map<String, String> params = new HashMap<>();
@ -160,7 +166,8 @@ class OverrideConfiguratorTest {
// mismatch
{
String consumerUrlV3 = "dubbo://172.24.160.179/com.foo.BarService?match_key=value&application=foo&side=consumer&timeout=100";
String consumerUrlV3 =
"dubbo://172.24.160.179/com.foo.BarService?match_key=value&application=foo&side=consumer&timeout=100";
URL consumerConfiguratorUrl = URL.valueOf("override://0.0.0.0/com.foo.BarService");
Map<String, String> params = new HashMap<>();
@ -192,5 +199,4 @@ class OverrideConfiguratorTest {
Assertions.assertEquals("100", url.getParameter("timeout"));
}
}
}

View File

@ -20,17 +20,17 @@ import org.apache.dubbo.common.URL;
import org.apache.dubbo.rpc.cluster.configurator.parser.model.ConditionMatch;
import org.apache.dubbo.rpc.cluster.configurator.parser.model.ConfiguratorConfig;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import static org.apache.dubbo.common.constants.CommonConstants.LOADBALANCE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
import static org.apache.dubbo.rpc.cluster.Constants.OVERRIDE_PROVIDERS_KEY;
@ -121,7 +121,6 @@ class ConfigParserTest {
}
}
@Test
void parseConfiguratorsAppAnyServicesTest() throws IOException {
try (InputStream yamlStream = this.getClass().getResourceAsStream("/AppAnyServices.yml")) {
@ -182,9 +181,11 @@ class ConfigParserTest {
URL matchURL1 = URL.valueOf("dubbo://10.0.0.1:20880/DemoService?match_key1=value1");
URL matchURL2 = URL.valueOf("dubbo://10.0.0.1:20880/DemoService2?match_key1=value1");
URL notMatchURL1 = URL.valueOf("dubbo://10.0.0.2:20880/DemoService?match_key1=value1");// address not match
URL notMatchURL2 = URL.valueOf("dubbo://10.0.0.1:20880/DemoServiceNotMatch?match_key1=value1");// service not match
URL notMatchURL3 = URL.valueOf("dubbo://10.0.0.1:20880/DemoService?match_key1=value_not_match");// key not match
URL notMatchURL1 = URL.valueOf("dubbo://10.0.0.2:20880/DemoService?match_key1=value1"); // address not match
URL notMatchURL2 =
URL.valueOf("dubbo://10.0.0.1:20880/DemoServiceNotMatch?match_key1=value1"); // service not match
URL notMatchURL3 =
URL.valueOf("dubbo://10.0.0.1:20880/DemoService?match_key1=value_not_match"); // key not match
ConditionMatch matcher = (ConditionMatch) url.getAttribute(MATCH_CONDITION);
Assertions.assertTrue(matcher.isMatch(matchURL1.getAddress(), matchURL1));
@ -208,7 +209,8 @@ class ConfigParserTest {
Assertions.assertEquals("demo-provider", url.getApplication());
URL matchURL = URL.valueOf("dubbo://10.0.0.1:20880/DemoService?match_key1=value1");
URL notMatchURL = URL.valueOf("dubbo://10.0.0.1:20880/DemoService?match_key1=value_not_match");// key not match
URL notMatchURL =
URL.valueOf("dubbo://10.0.0.1:20880/DemoService?match_key1=value_not_match"); // key not match
ConditionMatch matcher = (ConditionMatch) url.getAttribute(MATCH_CONDITION);
Assertions.assertTrue(matcher.isMatch(matchURL.getAddress(), matchURL));
@ -229,7 +231,8 @@ class ConfigParserTest {
Assertions.assertEquals("demo-provider", url.getApplication());
URL matchURL = URL.valueOf("dubbo://10.0.0.1:20880/DemoService?match_key1=value1");
URL notMatchURL = URL.valueOf("dubbo://10.0.0.1:20880/DemoService?match_key1=value_not_match");// key not match
URL notMatchURL =
URL.valueOf("dubbo://10.0.0.1:20880/DemoService?match_key1=value_not_match"); // key not match
ConditionMatch matcher = (ConditionMatch) url.getAttribute(MATCH_CONDITION);
Assertions.assertTrue(matcher.isMatch(matchURL.getAddress(), matchURL));
@ -240,7 +243,8 @@ class ConfigParserTest {
@Test
void parseURLJsonArrayCompatible() {
String configData = "[\"override://0.0.0.0/com.xx.Service?category=configurators&timeout=6666&disabled=true&dynamic=false&enabled=true&group=dubbo&priority=1&version=1.0\" ]";
String configData =
"[\"override://0.0.0.0/com.xx.Service?category=configurators&timeout=6666&disabled=true&dynamic=false&enabled=true&group=dubbo&priority=1&version=1.0\" ]";
List<URL> urls = ConfigParser.parseConfigurators(configData);
@ -252,5 +256,4 @@ class ConfigParserTest {
Assertions.assertEquals("com.xx.Service", url.getServiceInterface());
Assertions.assertEquals(6666, url.getParameter(TIMEOUT_KEY, 0));
}
}

View File

@ -16,7 +16,6 @@
*/
package org.apache.dubbo.rpc.cluster.filter;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
@ -38,30 +37,34 @@ class DefaultFilterChainBuilderTest {
DefaultFilterChainBuilder defaultFilterChainBuilder = new DefaultFilterChainBuilder();
// verify that no filter is built by default
URL urlWithoutFilter = URL.valueOf("injvm://127.0.0.1/DemoService")
.addParameter(INTERFACE_KEY, DemoService.class.getName());
URL urlWithoutFilter =
URL.valueOf("injvm://127.0.0.1/DemoService").addParameter(INTERFACE_KEY, DemoService.class.getName());
urlWithoutFilter = urlWithoutFilter.setScopeModel(ApplicationModel.defaultModel());
AbstractInvoker<DemoService> invokerWithoutFilter = new AbstractInvoker<DemoService>(DemoService.class, urlWithoutFilter) {
@Override
protected Result doInvoke(Invocation invocation) {
return null;
}
};
AbstractInvoker<DemoService> invokerWithoutFilter =
new AbstractInvoker<DemoService>(DemoService.class, urlWithoutFilter) {
@Override
protected Result doInvoke(Invocation invocation) {
return null;
}
};
Invoker<?> invokerAfterBuild = defaultFilterChainBuilder.buildInvokerChain(invokerWithoutFilter, REFERENCE_FILTER_KEY, CONSUMER);
Invoker<?> invokerAfterBuild =
defaultFilterChainBuilder.buildInvokerChain(invokerWithoutFilter, REFERENCE_FILTER_KEY, CONSUMER);
// verify that if LogFilter is configured, LogFilter should exist in the filter chain
URL urlWithFilter = URL.valueOf("injvm://127.0.0.1/DemoService")
.addParameter(INTERFACE_KEY, DemoService.class.getName())
.addParameter(REFERENCE_FILTER_KEY, "log");
.addParameter(INTERFACE_KEY, DemoService.class.getName())
.addParameter(REFERENCE_FILTER_KEY, "log");
urlWithFilter = urlWithFilter.setScopeModel(ApplicationModel.defaultModel());
AbstractInvoker<DemoService> invokerWithFilter = new AbstractInvoker<DemoService>(DemoService.class, urlWithFilter) {
@Override
protected Result doInvoke(Invocation invocation) {
return null;
}
};
invokerAfterBuild = defaultFilterChainBuilder.buildInvokerChain(invokerWithFilter, REFERENCE_FILTER_KEY, CONSUMER);
AbstractInvoker<DemoService> invokerWithFilter =
new AbstractInvoker<DemoService>(DemoService.class, urlWithFilter) {
@Override
protected Result doInvoke(Invocation invocation) {
return null;
}
};
invokerAfterBuild =
defaultFilterChainBuilder.buildInvokerChain(invokerWithFilter, REFERENCE_FILTER_KEY, CONSUMER);
Assertions.assertTrue(invokerAfterBuild instanceof FilterChainBuilder.CallbackRegistrationInvoker);
}
@ -71,31 +74,34 @@ class DefaultFilterChainBuilderTest {
// verify that no filter is built by default
URL urlWithoutFilter = URL.valueOf("dubbo://127.0.0.1:20880/DemoService")
.addParameter(INTERFACE_KEY, DemoService.class.getName());
.addParameter(INTERFACE_KEY, DemoService.class.getName());
urlWithoutFilter = urlWithoutFilter.setScopeModel(ApplicationModel.defaultModel());
AbstractInvoker<DemoService> invokerWithoutFilter = new AbstractInvoker<DemoService>(DemoService.class, urlWithoutFilter) {
@Override
protected Result doInvoke(Invocation invocation) {
return null;
}
};
AbstractInvoker<DemoService> invokerWithoutFilter =
new AbstractInvoker<DemoService>(DemoService.class, urlWithoutFilter) {
@Override
protected Result doInvoke(Invocation invocation) {
return null;
}
};
Invoker<?> invokerAfterBuild = defaultFilterChainBuilder.buildInvokerChain(invokerWithoutFilter, REFERENCE_FILTER_KEY, CONSUMER);
// Assertions.assertTrue(invokerAfterBuild instanceof AbstractInvoker);
Invoker<?> invokerAfterBuild =
defaultFilterChainBuilder.buildInvokerChain(invokerWithoutFilter, REFERENCE_FILTER_KEY, CONSUMER);
// Assertions.assertTrue(invokerAfterBuild instanceof AbstractInvoker);
// verify that if LogFilter is configured, LogFilter should exist in the filter chain
URL urlWithFilter = URL.valueOf("dubbo://127.0.0.1:20880/DemoService")
.addParameter(INTERFACE_KEY, DemoService.class.getName())
.addParameter(REFERENCE_FILTER_KEY, "log");
.addParameter(INTERFACE_KEY, DemoService.class.getName())
.addParameter(REFERENCE_FILTER_KEY, "log");
urlWithFilter = urlWithFilter.setScopeModel(ApplicationModel.defaultModel());
AbstractInvoker<DemoService> invokerWithFilter = new AbstractInvoker<DemoService>(DemoService.class, urlWithFilter) {
@Override
protected Result doInvoke(Invocation invocation) {
return null;
}
};
invokerAfterBuild = defaultFilterChainBuilder.buildInvokerChain(invokerWithFilter, REFERENCE_FILTER_KEY, CONSUMER);
AbstractInvoker<DemoService> invokerWithFilter =
new AbstractInvoker<DemoService>(DemoService.class, urlWithFilter) {
@Override
protected Result doInvoke(Invocation invocation) {
return null;
}
};
invokerAfterBuild =
defaultFilterChainBuilder.buildInvokerChain(invokerWithFilter, REFERENCE_FILTER_KEY, CONSUMER);
Assertions.assertTrue(invokerAfterBuild instanceof FilterChainBuilder.CallbackRegistrationInvoker);
}
}

View File

@ -19,7 +19,6 @@ package org.apache.dubbo.rpc.cluster.filter;
/**
* <code>TestService</code>
*/
public interface DemoService {
String sayHello(String name);

View File

@ -16,8 +16,7 @@
*/
package org.apache.dubbo.rpc.cluster.filter;
class DemoServiceImpl implements DemoService{
class DemoServiceImpl implements DemoService {
@Override
public String sayHello(String name) {

View File

@ -19,11 +19,9 @@ package org.apache.dubbo.rpc.cluster.filter;
/**
* <code>TestService</code>
*/
class DemoServiceLocal implements DemoService {
public DemoServiceLocal(DemoService demoService) {
}
public DemoServiceLocal(DemoService demoService) {}
public String sayHello(String name) {
return name;
@ -33,11 +31,7 @@ class DemoServiceLocal implements DemoService {
return a + b;
}
public void ondisconnect() {
public void ondisconnect() {}
}
public void onconnect() {
}
public void onconnect() {}
}

View File

@ -19,11 +19,9 @@ package org.apache.dubbo.rpc.cluster.filter;
/**
* <code>TestService</code>
*/
class DemoServiceStub implements DemoService {
public DemoServiceStub(DemoService demoService) {
}
public DemoServiceStub(DemoService demoService) {}
public String sayHello(String name) {
return name;

View File

@ -25,7 +25,6 @@ import org.apache.dubbo.rpc.RpcException;
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
@Activate(group = CONSUMER, value = "log")
public class LogFilter implements Filter, Filter.Listener {
@ -35,12 +34,8 @@ public class LogFilter implements Filter, Filter.Listener {
}
@Override
public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {
}
public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {}
@Override
public void onError(Throwable t, Invoker<?> invoker, Invocation invocation) {
}
public void onError(Throwable t, Invoker<?> invoker, Invocation invocation) {}
}

View File

@ -23,13 +23,13 @@ import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.cluster.ClusterInvoker;
import java.util.HashMap;
import java.util.List;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.util.HashMap;
import java.util.List;
import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY;
import static org.apache.dubbo.rpc.cluster.Constants.WEIGHT_KEY;
import static org.mockito.BDDMockito.given;
@ -71,10 +71,12 @@ class AbstractLoadBalanceTest {
URL url1 = new ServiceConfigURL("", "", 0, "DemoService", new HashMap<>());
given(invoker1.getUrl()).willReturn(url1);
ClusterInvoker invoker2 = mock(ClusterInvoker.class, Mockito.withSettings().stubOnly());
ClusterInvoker invoker2 =
mock(ClusterInvoker.class, Mockito.withSettings().stubOnly());
URL url2 = new ServiceConfigURL("", "", 0, "org.apache.dubbo.registry.RegistryService", new HashMap<>());
url2 = url2.addParameter(WEIGHT_KEY, 20);
URL registryUrl2 = new ServiceConfigURL("", "", 0, "org.apache.dubbo.registry.RegistryService", new HashMap<>());
URL registryUrl2 =
new ServiceConfigURL("", "", 0, "org.apache.dubbo.registry.RegistryService", new HashMap<>());
registryUrl2 = registryUrl2.addParameter(WEIGHT_KEY, 30);
given(invoker2.getUrl()).willReturn(url2);
given(invoker2.getRegistryUrl()).willReturn(registryUrl2);

View File

@ -16,16 +16,17 @@
*/
package org.apache.dubbo.rpc.cluster.loadbalance;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.cluster.LoadBalance;
import org.apache.dubbo.rpc.cluster.RouterChain;
import org.apache.dubbo.rpc.cluster.router.state.BitList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -41,21 +42,20 @@ class ConsistentHashLoadBalanceTest extends LoadBalanceBaseTest {
Invoker genericHitted = findHitted(genericInvokeCounter);
Invoker hitted = findHitted(invokeCounter);
Assertions.assertEquals(hitted,
genericHitted, "hitted should equals to genericHitted");
Assertions.assertEquals(hitted, genericHitted, "hitted should equals to genericHitted");
}
private Invoker findHitted(Map<Invoker,AtomicLong> invokerCounter) {
private Invoker findHitted(Map<Invoker, AtomicLong> invokerCounter) {
Invoker invoker = null;
for (Map.Entry<Invoker,AtomicLong> entry : invokerCounter.entrySet()) {
for (Map.Entry<Invoker, AtomicLong> entry : invokerCounter.entrySet()) {
if (entry.getValue().longValue() > 0) {
invoker = entry.getKey();
break;
}
}
Assertions.assertNotNull(invoker,"invoker should be found");
Assertions.assertNotNull(invoker, "invoker should be found");
return null;
}
@ -76,11 +76,13 @@ class ConsistentHashLoadBalanceTest extends LoadBalanceBaseTest {
}
}
Assertions.assertEquals(counter.size() - 1,
unHitedInvokerCount, "the number of unHitedInvoker should be counter.size() - 1");
Assertions.assertEquals(
counter.size() - 1, unHitedInvokerCount, "the number of unHitedInvoker should be counter.size() - 1");
Assertions.assertEquals(1, hitedInvokers.size(), "the number of hitedInvoker should be 1");
Assertions.assertEquals(runs,
hitedInvokers.values().iterator().next().intValue(), "the number of hited count should be the number of runs");
Assertions.assertEquals(
runs,
hitedInvokers.values().iterator().next().intValue(),
"the number of hited count should be the number of runs");
}
// https://github.com/apache/dubbo/issues/5429
@ -93,8 +95,9 @@ class ConsistentHashLoadBalanceTest extends LoadBalanceBaseTest {
for (int i = 0; i < 100; i++) {
routerChain.setInvokers(new BitList<>(invokers), () -> {});
List<Invoker<LoadBalanceBaseTest>> routeInvokers = routerChain.getSingleChain(url, new BitList<>(invokers), invocation)
.route(url, new BitList<>(invokers), invocation);
List<Invoker<LoadBalanceBaseTest>> routeInvokers = routerChain
.getSingleChain(url, new BitList<>(invokers), invocation)
.route(url, new BitList<>(invokers), invocation);
Invoker<LoadBalanceBaseTest> finalInvoker = lb.select(routeInvokers, url, invocation);
Assertions.assertEquals(result, finalInvoker);
}

View File

@ -18,13 +18,13 @@ package org.apache.dubbo.rpc.cluster.loadbalance;
import org.apache.dubbo.rpc.Invoker;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
class LeastActiveBalanceTest extends LoadBalanceBaseTest {
@Disabled
@Test
@ -35,7 +35,8 @@ class LeastActiveBalanceTest extends LoadBalanceBaseTest {
Long count = entry.getValue().get();
// System.out.println(count);
Assertions.assertTrue(
Math.abs(count - runs / (0f + invokers.size())) < runs / (0f + invokers.size()), "abs diff should < avg");
Math.abs(count - runs / (0f + invokers.size())) < runs / (0f + invokers.size()),
"abs diff should < avg");
}
}
@ -57,7 +58,8 @@ class LeastActiveBalanceTest extends LoadBalanceBaseTest {
sumInvoker2++;
}
// never select invoker3 because it's active is more than invoker1 and invoker2
Assertions.assertTrue(!selected.getUrl().getProtocol().equals("test3"), "select is not the least active one");
Assertions.assertTrue(
!selected.getUrl().getProtocol().equals("test3"), "select is not the least active one");
}
// the sumInvoker1 : sumInvoker2 approximately equal to 1: 9

View File

@ -25,18 +25,18 @@ import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.RpcStatus;
import org.apache.dubbo.rpc.cluster.LoadBalance;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import static org.apache.dubbo.rpc.cluster.Constants.DEFAULT_WARMUP;
import static org.apache.dubbo.rpc.cluster.Constants.DEFAULT_WEIGHT;
import static org.mockito.BDDMockito.given;
@ -67,8 +67,7 @@ class LoadBalanceBaseTest {
* @throws java.lang.Exception
*/
@BeforeAll
public static void setUpBeforeClass() throws Exception {
}
public static void setUpBeforeClass() throws Exception {}
/**
* @throws java.lang.Exception
@ -78,14 +77,14 @@ class LoadBalanceBaseTest {
invocation = mock(Invocation.class);
given(invocation.getMethodName()).willReturn("method1");
given(invocation.getArguments()).willReturn(new Object[] {"arg1","arg2","arg3"});
given(invocation.getArguments()).willReturn(new Object[] {"arg1", "arg2", "arg3"});
genericInvocation = mock(Invocation.class);
String methodName = "method1";
given(genericInvocation.getMethodName()).willReturn("$invoke");
String[] paraTypes = new String[] {String.class.getName(),String.class.getName(),String.class.getName()};
Object[] argsObject = new Object[] {"arg1","arg2","arg3"};
Object[] args = new Object[] {methodName,paraTypes,argsObject};
String[] paraTypes = new String[] {String.class.getName(), String.class.getName(), String.class.getName()};
Object[] argsObject = new Object[] {"arg1", "arg2", "arg3"};
Object[] args = new Object[] {methodName, paraTypes, argsObject};
given(genericInvocation.getArguments()).willReturn(args);
invoker1 = mock(Invoker.class);
@ -156,7 +155,8 @@ class LoadBalanceBaseTest {
}
protected AbstractLoadBalance getLoadBalance(String loadbalanceName) {
return (AbstractLoadBalance) ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(loadbalanceName);
return (AbstractLoadBalance)
ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(loadbalanceName);
}
@Test
@ -229,7 +229,7 @@ class LoadBalanceBaseTest {
}
protected List<Invoker<LoadBalanceBaseTest>> weightInvokers = new ArrayList<Invoker<LoadBalanceBaseTest>>();
protected List<Invoker<LoadBalanceBaseTest>> weightInvokersSR= new ArrayList<Invoker<LoadBalanceBaseTest>>();
protected List<Invoker<LoadBalanceBaseTest>> weightInvokersSR = new ArrayList<Invoker<LoadBalanceBaseTest>>();
protected Invoker<LoadBalanceBaseTest> weightInvoker1;
protected Invoker<LoadBalanceBaseTest> weightInvoker2;
@ -287,7 +287,6 @@ class LoadBalanceBaseTest {
weightTestRpcStatus3 = RpcStatus.getStatus(weightInvoker3.getUrl(), weightTestInvocation.getMethodName());
weightTestRpcStatus5 = RpcStatus.getStatus(weightInvoker5.getUrl(), weightTestInvocation.getMethodName());
// weightTestRpcStatus3 active is 1
RpcStatus.beginCount(weightInvoker3.getUrl(), weightTestInvocation.getMethodName());
@ -302,7 +301,7 @@ class LoadBalanceBaseTest {
Map<Invoker, InvokeResult> counter = new ConcurrentHashMap<Invoker, InvokeResult>();
AbstractLoadBalance lb = getLoadBalance(loadbalanceName);
int totalWeight = 0;
for (int i = 0; i < weightInvokers.size(); i ++) {
for (int i = 0; i < weightInvokers.size(); i++) {
InvokeResult invokeResult = new InvokeResult(lb.getWeight(weightInvokers.get(i), weightTestInvocation));
counter.put(weightInvokers.get(i), invokeResult);
totalWeight += invokeResult.getWeight();
@ -317,5 +316,4 @@ class LoadBalanceBaseTest {
}
return counter;
}
}

View File

@ -19,12 +19,12 @@ package org.apache.dubbo.rpc.cluster.loadbalance;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.RpcStatus;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
/**
* RandomLoadBalance Test
*/
@ -35,7 +35,9 @@ class RandomLoadBalanceTest extends LoadBalanceBaseTest {
Map<Invoker, AtomicLong> counter = getInvokeCounter(runs, RandomLoadBalance.NAME);
for (Map.Entry<Invoker, AtomicLong> entry : counter.entrySet()) {
Long count = entry.getValue().get();
Assertions.assertTrue(Math.abs(count - runs / (0f + invokers.size())) < runs / (0f + invokers.size()), "abs diff should < avg");
Assertions.assertTrue(
Math.abs(count - runs / (0f + invokers.size())) < runs / (0f + invokers.size()),
"abs diff should < avg");
}
for (int i = 0; i < 5; i++) {
@ -84,5 +86,4 @@ class RandomLoadBalanceTest extends LoadBalanceBaseTest {
System.out.println(sumInvoker3);
Assertions.assertEquals(sumInvoker1 + sumInvoker2 + sumInvoker3, loop, "select failed!");
}
}

View File

@ -18,10 +18,6 @@ package org.apache.dubbo.rpc.cluster.loadbalance;
import org.apache.dubbo.rpc.Invoker;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
@ -31,6 +27,10 @@ import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@Disabled
class RoundRobinLoadBalanceTest extends LoadBalanceBaseTest {
@ -77,7 +77,9 @@ class RoundRobinLoadBalanceTest extends LoadBalanceBaseTest {
if (!totalMap.containsKey(entry.getKey())) {
totalMap.put(entry.getKey(), entry.getValue());
} else {
totalMap.get(entry.getKey()).getCount().addAndGet(entry.getValue().getCount().get());
totalMap.get(entry.getKey())
.getCount()
.addAndGet(entry.getValue().getCount().get());
}
}
}
@ -100,7 +102,7 @@ class RoundRobinLoadBalanceTest extends LoadBalanceBaseTest {
@Test
void testNodeCacheShouldNotRecycle() {
int loop = 10000;
//tmperately add a new invoker
// tmperately add a new invoker
weightInvokers.add(weightInvokerTmp);
try {
Map<Invoker, InvokeResult> resultMap = getWeightedInvokeResult(loop, RoundRobinLoadBalance.NAME);
@ -108,16 +110,20 @@ class RoundRobinLoadBalanceTest extends LoadBalanceBaseTest {
// inner nodes cache judgement
RoundRobinLoadBalance lb = (RoundRobinLoadBalance) getLoadBalance(RoundRobinLoadBalance.NAME);
Assertions.assertEquals(weightInvokers.size(), lb.getInvokerAddrList(weightInvokers, weightTestInvocation).size());
Assertions.assertEquals(
weightInvokers.size(),
lb.getInvokerAddrList(weightInvokers, weightTestInvocation).size());
weightInvokers.remove(weightInvokerTmp);
resultMap = getWeightedInvokeResult(loop, RoundRobinLoadBalance.NAME);
assertStrictWRRResult(loop, resultMap);
Assertions.assertNotEquals(weightInvokers.size(), lb.getInvokerAddrList(weightInvokers, weightTestInvocation).size());
Assertions.assertNotEquals(
weightInvokers.size(),
lb.getInvokerAddrList(weightInvokers, weightTestInvocation).size());
} finally {
//prevent other UT's failure
// prevent other UT's failure
weightInvokers.remove(weightInvokerTmp);
}
}
@ -127,7 +133,7 @@ class RoundRobinLoadBalanceTest extends LoadBalanceBaseTest {
{
Field recycleTimeField = null;
try {
//change recycle time to 1 ms
// change recycle time to 1 ms
recycleTimeField = RoundRobinLoadBalance.class.getDeclaredField("RECYCLE_PERIOD");
recycleTimeField.setAccessible(true);
recycleTimeField.setInt(RoundRobinLoadBalance.class, 10);
@ -137,7 +143,7 @@ class RoundRobinLoadBalanceTest extends LoadBalanceBaseTest {
}
int loop = 10000;
//tmperately add a new invoker
// tmperately add a new invoker
weightInvokers.add(weightInvokerTmp);
try {
Map<Invoker, InvokeResult> resultMap = getWeightedInvokeResult(loop, RoundRobinLoadBalance.NAME);
@ -145,18 +151,21 @@ class RoundRobinLoadBalanceTest extends LoadBalanceBaseTest {
// inner nodes cache judgement
RoundRobinLoadBalance lb = (RoundRobinLoadBalance) getLoadBalance(RoundRobinLoadBalance.NAME);
Assertions.assertEquals(weightInvokers.size(), lb.getInvokerAddrList(weightInvokers, weightTestInvocation).size());
Assertions.assertEquals(
weightInvokers.size(),
lb.getInvokerAddrList(weightInvokers, weightTestInvocation).size());
weightInvokers.remove(weightInvokerTmp);
resultMap = getWeightedInvokeResult(loop, RoundRobinLoadBalance.NAME);
assertStrictWRRResult(loop, resultMap);
Assertions.assertEquals(weightInvokers.size(), lb.getInvokerAddrList(weightInvokers, weightTestInvocation).size());
Assertions.assertEquals(
weightInvokers.size(),
lb.getInvokerAddrList(weightInvokers, weightTestInvocation).size());
} finally {
//prevent other UT's failure
// prevent other UT's failure
weightInvokers.remove(weightInvokerTmp);
}
}
}

View File

@ -21,18 +21,18 @@ import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.RpcStatus;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class ShortestResponseLoadBalanceTest extends LoadBalanceBaseTest {
@ -74,13 +74,14 @@ class ShortestResponseLoadBalanceTest extends LoadBalanceBaseTest {
int sumInvoker5 = 0;
int loop = 10000;
//active -> 0
// active -> 0
RpcStatus.endCount(weightInvoker5.getUrl(), weightTestInvocation.getMethodName(), 5000L, true);
ShortestResponseLoadBalance lb = new ShortestResponseLoadBalance();
lb.setApplicationModel(ApplicationModel.defaultModel());
//reset slideWindow
Field lastUpdateTimeField = ReflectUtils.forName(ShortestResponseLoadBalance.class.getName()).getDeclaredField("lastUpdateTime");
// reset slideWindow
Field lastUpdateTimeField = ReflectUtils.forName(ShortestResponseLoadBalance.class.getName())
.getDeclaredField("lastUpdateTime");
lastUpdateTimeField.setAccessible(true);
lastUpdateTimeField.setLong(lb, System.currentTimeMillis() - TimeUnit.SECONDS.toMillis(31));
lb.select(weightInvokersSR, null, weightTestInvocation);
@ -101,14 +102,19 @@ class ShortestResponseLoadBalanceTest extends LoadBalanceBaseTest {
}
}
Map<Invoker<LoadBalanceBaseTest>, Integer> weightMap = weightInvokersSR.stream()
.collect(Collectors.toMap(Function.identity(), e -> Integer.valueOf(e.getUrl().getParameter("weight"))));
.collect(Collectors.toMap(
Function.identity(), e -> Integer.valueOf(e.getUrl().getParameter("weight"))));
Integer totalWeight = weightMap.values().stream().reduce(0, Integer::sum);
// max deviation = expectWeightValue * 2
int expectWeightValue = loop / totalWeight;
int maxDeviation = expectWeightValue * 2;
Assertions.assertEquals(sumInvoker1 + sumInvoker2 + sumInvoker5, loop, "select failed!");
Assertions.assertTrue(Math.abs(sumInvoker2 / weightMap.get(weightInvoker2) - expectWeightValue) < maxDeviation, "select failed!");
Assertions.assertTrue(Math.abs(sumInvoker5 / weightMap.get(weightInvoker5) - expectWeightValue) < maxDeviation, "select failed!");
Assertions.assertTrue(
Math.abs(sumInvoker2 / weightMap.get(weightInvoker2) - expectWeightValue) < maxDeviation,
"select failed!");
Assertions.assertTrue(
Math.abs(sumInvoker5 / weightMap.get(weightInvoker5) - expectWeightValue) < maxDeviation,
"select failed!");
}
}

View File

@ -26,8 +26,7 @@ public class MockInvoker<T> implements Invoker<T> {
private boolean available = false;
private URL url;
public MockInvoker() {
}
public MockInvoker() {}
public MockInvoker(URL url) {
super();
@ -64,6 +63,5 @@ public class MockInvoker<T> implements Invoker<T> {
}
@Override
public void destroy() {
}
public void destroy() {}
}

Some files were not shown because too many files have changed in this diff Show More