[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:
parent
88deb9be3d
commit
d979b211ce
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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) {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,5 @@ public class ClusterScopeModelInitializer implements ScopeModelInitializer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void initializeModuleModel(ModuleModel moduleModel) {
|
||||
}
|
||||
public void initializeModuleModel(ModuleModel moduleModel) {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -36,5 +36,4 @@ public interface ConfiguratorFactory {
|
|||
*/
|
||||
@Adaptive(CommonConstants.PROTOCOL_KEY)
|
||||
Configurator getConfigurator(URL url);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -46,5 +46,4 @@ public interface LoadBalance {
|
|||
*/
|
||||
@Adaptive("loadbalance")
|
||||
<T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,5 +22,4 @@ import org.apache.dubbo.common.extension.SPI;
|
|||
public interface Merger<T> {
|
||||
|
||||
T merge(T... items);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,5 +32,4 @@ public class AbsentConfigurator extends AbstractConfigurator {
|
|||
public URL doConfigure(URL currentUrl, URL configUrl) {
|
||||
return currentUrl.addParametersIfAbsent(configUrl.getParameters());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,5 +30,4 @@ public class AbsentConfiguratorFactory implements ConfiguratorFactory {
|
|||
public Configurator getConfigurator(URL url) {
|
||||
return new AbsentConfigurator(url);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,5 +36,4 @@ public class OverrideConfigurator extends AbstractConfigurator {
|
|||
logger.info("Start overriding url " + currentUrl + " with override url " + configUrl);
|
||||
return currentUrl.addParameters(configUrl.getParameters());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,5 +30,4 @@ public class OverrideConfiguratorFactory implements ConfiguratorFactory {
|
|||
public Configurator getConfigurator(URL url) {
|
||||
return new OverrideConfigurator(url);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) -> {
|
||||
|
|
|
|||
|
|
@ -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 + '\'' + '}';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -50,9 +50,6 @@ public class ParamMatch {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ParamMatch{" +
|
||||
"key='" + key + '\'' +
|
||||
", value='" + value + '\'' +
|
||||
'}';
|
||||
return "ParamMatch{" + "key='" + key + '\'' + ", value='" + value + '\'' + '}';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(", "))
|
||||
+ "]" + ')';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -56,5 +56,4 @@ public class DefaultGovernanceRuleRepositoryImpl implements GovernanceRuleReposi
|
|||
private DynamicConfiguration getDynamicConfiguration() {
|
||||
return moduleModel.modelEnvironment().getDynamicConfiguration().orElse(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ public interface GovernanceRuleRepository {
|
|||
addListener(key, DEFAULT_GROUP, listener);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@link #removeListener(String, String, ConfigurationListener)}
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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("...");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 + '}';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 + '\'' + '}';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,5 +30,4 @@ public class BroadcastCluster extends AbstractCluster {
|
|||
public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
|
||||
return new BroadcastClusterInvoker<>(directory);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 0~100.
|
||||
// 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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 + '}';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
//}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ package org.apache.dubbo.rpc.cluster.filter;
|
|||
/**
|
||||
* <code>TestService</code>
|
||||
*/
|
||||
|
||||
public interface DemoService {
|
||||
String sayHello(String name);
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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!");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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!");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue