[3.2]Use spotless to format the code (#13320)

* Use spotless to format the code

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

* Support develop with JDK 21

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

---------

Signed-off-by: crazyhzm <crazyhzm@gmail.com>
This commit is contained in:
huazhongming 2023-11-07 15:40:13 +08:00 committed by GitHub
parent 04f134a168
commit 730695a7a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3271 changed files with 53817 additions and 49413 deletions

View File

@ -13,76 +13,77 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<project xmlns="http://maven.apache.org/POM/4.0.0" <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/xsd/maven-4.0.0.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <modelVersion>4.0.0</modelVersion>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.dubbo</groupId> <groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-build-tools</artifactId> <artifactId>dubbo-build-tools</artifactId>
<version>1.0.0</version> <version>1.0.0</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<properties> <properties>
<maven.deploy.skip>true</maven.deploy.skip> <maven.deploy.skip>true</maven.deploy.skip>
<spotless-maven-plugin.version>2.40.0</spotless-maven-plugin.version> <spotless-maven-plugin.version>2.40.0</spotless-maven-plugin.version>
<spotless.action>check</spotless.action> <spotless.action>check</spotless.action>
<dubbo-shared-resources.version>1.0.0</dubbo-shared-resources.version> <dubbo-shared-resources.version>1.0.0</dubbo-shared-resources.version>
</properties> <palantirJavaFormat.version>2.38.0</palantirJavaFormat.version>
</properties>
<profiles> <profiles>
<profile> <profile>
<id>java11+</id> <id>java11+</id>
<activation> <activation>
<jdk>[11,)</jdk> <jdk>[11,)</jdk>
</activation> </activation>
<build> <build>
<!--- newer versions of plugins requires JDK 11 --> <!--- newer versions of plugins requires JDK 11 -->
<plugins> <plugins>
<plugin> <plugin>
<groupId>com.diffplug.spotless</groupId> <groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId> <artifactId>spotless-maven-plugin</artifactId>
<version>${spotless-maven-plugin.version}</version> <version>${spotless-maven-plugin.version}</version>
<configuration> <configuration>
<java> <java>
<palantirJavaFormat /> <palantirJavaFormat>
<removeUnusedImports /> <version>${palantirJavaFormat.version}</version>
<importOrder> </palantirJavaFormat>
<file>dubbo-importorder.txt</file> <removeUnusedImports />
</importOrder> <importOrder>
<licenseHeader> <file>dubbo-importorder.txt</file>
<file>checkstyle-header.txt</file> </importOrder>
</licenseHeader> <licenseHeader>
</java> <file>checkstyle-header.txt</file>
<pom> </licenseHeader>
<sortPom> </java>
<expandEmptyElements>false</expandEmptyElements> <pom>
<spaceBeforeCloseEmptyElement>true</spaceBeforeCloseEmptyElement> <sortPom>
</sortPom> <expandEmptyElements>false</expandEmptyElements>
</pom> <spaceBeforeCloseEmptyElement>true</spaceBeforeCloseEmptyElement>
<upToDateChecking> </sortPom>
<enabled>true</enabled> </pom>
</upToDateChecking> <upToDateChecking>
</configuration> <enabled>true</enabled>
<dependencies> </upToDateChecking>
<dependency> </configuration>
<groupId>com.alibaba</groupId> <dependencies>
<artifactId>dubbo-shared-resources</artifactId> <dependency>
<version>${dubbo-shared-resources.version}</version> <groupId>com.alibaba</groupId>
</dependency> <artifactId>dubbo-shared-resources</artifactId>
</dependencies> <version>${dubbo-shared-resources.version}</version>
<executions> </dependency>
<execution> </dependencies>
<goals> <executions>
<goal>${spotless.action}</goal> <execution>
</goals> <goals>
<phase>process-sources</phase> <goal>${spotless.action}</goal>
</execution> </goals>
</executions> <phase>process-sources</phase>
</plugin> </execution>
</plugins> </executions>
</build> </plugin>
</profile> </plugins>
</profiles> </build>
</profile>
</profiles>
</project> </project>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -68,8 +68,8 @@ public interface Router extends Comparable<Router> {
* @return state with route result * @return state with route result
* @throws RpcException * @throws RpcException
*/ */
default <T> RouterResult<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation, default <T> RouterResult<Invoker<T>> route(
boolean needToPrintMessage) throws RpcException { List<Invoker<T>> invokers, URL url, Invocation invocation, boolean needToPrintMessage) throws RpcException {
return new RouterResult<>(route(invokers, url, invocation)); return new RouterResult<>(route(invokers, url, invocation));
} }
@ -80,9 +80,7 @@ public interface Router extends Comparable<Router> {
* @param invokers invoker list * @param invokers invoker list
* @param <T> invoker's type * @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 * 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(); int getPriority();
default void stop() { default void stop() {
//do nothing by default // do nothing by default
} }
@Override @Override

View File

@ -16,12 +16,6 @@
*/ */
package org.apache.dubbo.rpc.cluster; 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.URL;
import org.apache.dubbo.common.config.ConfigurationUtils; import org.apache.dubbo.common.config.ConfigurationUtils;
import org.apache.dubbo.common.constants.LoggerCodeConstants; 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.ModuleModel;
import org.apache.dubbo.rpc.model.ScopeModelUtil; 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; 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) { public static <T> RouterChain<T> buildChain(Class<T> interfaceClass, URL url) {
SingleRouterChain<T> chain1 = buildSingleChain(interfaceClass, url); SingleRouterChain<T> chain1 = buildSingleChain(interfaceClass, url);
SingleRouterChain<T> chain2 = 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) { public static <T> SingleRouterChain<T> buildSingleChain(Class<T> interfaceClass, URL url) {
ModuleModel moduleModel = url.getOrDefaultModuleModel(); ModuleModel moduleModel = url.getOrDefaultModuleModel();
List<RouterFactory> extensionFactories = moduleModel.getExtensionLoader(RouterFactory.class) List<RouterFactory> extensionFactories =
.getActivateExtension(url, ROUTER_KEY); moduleModel.getExtensionLoader(RouterFactory.class).getActivateExtension(url, ROUTER_KEY);
List<Router> routers = extensionFactories.stream() List<Router> routers = extensionFactories.stream()
.map(factory -> factory.getRouter(url)) .map(factory -> factory.getRouter(url))
.sorted(Router::compareTo) .sorted(Router::compareTo)
.collect(Collectors.toList()); .collect(Collectors.toList());
List<StateRouter<T>> stateRouters = moduleModel List<StateRouter<T>> stateRouters =
.getExtensionLoader(StateRouterFactory.class) moduleModel.getExtensionLoader(StateRouterFactory.class).getActivateExtension(url, ROUTER_KEY).stream()
.getActivateExtension(url, ROUTER_KEY) .map(factory -> factory.getRouter(interfaceClass, url))
.stream() .collect(Collectors.toList());
.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); 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 origin invokers => use backup chain
// If `availableInvokers` is created from newly invokers => use main chain // If `availableInvokers` is created from newly invokers => use main chain
BitList<Invoker<T>> notifying = notifyingInvokers.get(); BitList<Invoker<T>> notifying = notifyingInvokers.get();
if (notifying != null && if (notifying != null
currentChain == backupChain && && currentChain == backupChain
availableInvokers.getOriginList() == notifying.getOriginList()) { && availableInvokers.getOriginList() == notifying.getOriginList()) {
return mainChain; return mainChain;
} }
return currentChain; return currentChain;
@ -140,7 +139,8 @@ public class RouterChain<T> {
} }
// Refresh main chain. // 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 { try {
// Lock main chain to wait all invocation end // Lock main chain to wait all invocation end
// To wait until no one is using main chain. // 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. // 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` // Reason: The next step will switch the invokers reference in directory, so we should check the
// argument when `route`. If the current invocation use newly invokers, we should use main chain to route, and // `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. // this can prevent use newly invokers to route backup chain, which can only route origin invokers now.
notifyingInvokers.set(invokers); notifyingInvokers.set(invokers);
// Switch the invokers reference in directory. // 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(); switchAction.run();
try { try {
// Lock to prevent directory continue list // 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(); lock.writeLock().lock();
// Switch to main chain. Will update backup chain later. // Switch to main chain. Will update backup chain later.
currentChain = mainChain; currentChain = mainChain;
// Clean up temp variable. // Clean up temp variable.
// `availableInvokers` check is useless now, because `route` method will no longer receive any `availableInvokers` related // `availableInvokers` check is useless now, because `route` method will no longer receive any
// with the origin invokers. The getter of invokers reference in directory is locked now, and will return newly invokers // `availableInvokers` related
// with the origin invokers. The getter of invokers reference in directory is locked now, and will return
// newly invokers
// once lock released. // once lock released.
notifyingInvokers.set(null); notifyingInvokers.set(null);
} finally { } finally {
@ -186,7 +192,8 @@ public class RouterChain<T> {
} }
// Refresh main chain. // 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 { try {
// Lock main chain to wait all invocation end // Lock main chain to wait all invocation end
backupChain.getLock().writeLock().lock(); backupChain.getLock().writeLock().lock();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -68,32 +68,33 @@ public class ConfigItem {
Object addresses = map.get(ADDRESSES_KEY); Object addresses = map.get(ADDRESSES_KEY);
if (addresses != null && List.class.isAssignableFrom(addresses.getClass())) { if (addresses != null && List.class.isAssignableFrom(addresses.getClass())) {
configItem.setAddresses(((List<Object>) addresses).stream() configItem.setAddresses(
.map(String::valueOf).collect(Collectors.toList())); ((List<Object>) addresses).stream().map(String::valueOf).collect(Collectors.toList()));
} }
Object providerAddresses = map.get(PROVIDER_ADDRESSES_KEY); Object providerAddresses = map.get(PROVIDER_ADDRESSES_KEY);
if (providerAddresses != null && List.class.isAssignableFrom(providerAddresses.getClass())) { if (providerAddresses != null && List.class.isAssignableFrom(providerAddresses.getClass())) {
configItem.setProviderAddresses(((List<Object>) providerAddresses).stream() configItem.setProviderAddresses(((List<Object>) providerAddresses)
.map(String::valueOf).collect(Collectors.toList())); .stream().map(String::valueOf).collect(Collectors.toList()));
} }
Object services = map.get(SERVICES_KEY); Object services = map.get(SERVICES_KEY);
if (services != null && List.class.isAssignableFrom(services.getClass())) { if (services != null && List.class.isAssignableFrom(services.getClass())) {
configItem.setServices(((List<Object>) services).stream() configItem.setServices(
.map(String::valueOf).collect(Collectors.toList())); ((List<Object>) services).stream().map(String::valueOf).collect(Collectors.toList()));
} }
Object applications = map.get(APPLICATIONS_KEY); Object applications = map.get(APPLICATIONS_KEY);
if (applications != null && List.class.isAssignableFrom(applications.getClass())) { if (applications != null && List.class.isAssignableFrom(applications.getClass())) {
configItem.setApplications(((List<Object>) applications).stream() configItem.setApplications(
.map(String::valueOf).collect(Collectors.toList())); ((List<Object>) applications).stream().map(String::valueOf).collect(Collectors.toList()));
} }
Object parameters = map.get(PARAMETERS_KEY); Object parameters = map.get(PARAMETERS_KEY);
if (parameters != null && Map.class.isAssignableFrom(parameters.getClass())) { if (parameters != null && Map.class.isAssignableFrom(parameters.getClass())) {
configItem.setParameters(((Map<String, Object>) parameters).entrySet() configItem.setParameters(((Map<String, Object>) parameters)
.stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().toString()))); .entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue()
.toString())));
} }
try { try {
@ -102,7 +103,12 @@ public class ConfigItem {
configItem.setMatch(PojoUtils.mapToPojo((Map<String, Object>) match, ConditionMatch.class)); configItem.setMatch(PojoUtils.mapToPojo((Map<String, Object>) match, ConditionMatch.class));
} }
} catch (Throwable t) { } 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)); configItem.setSide((String) map.get(SIDE_KEY));

View File

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

View File

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

View File

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

View File

@ -55,7 +55,12 @@ public class StaticDirectory<T> extends AbstractDirectory<T> {
} }
public StaticDirectory(URL url, List<Invoker<T>> invokers, RouterChain<T> routerChain) { 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)) { if (CollectionUtils.isEmpty(invokers)) {
throw new IllegalArgumentException("invokers == null"); throw new IllegalArgumentException("invokers == null");
} }
@ -101,28 +106,34 @@ public class StaticDirectory<T> extends AbstractDirectory<T> {
public void buildRouterChain() { public void buildRouterChain() {
RouterChain<T> routerChain = RouterChain.buildChain(getInterface(), getUrl()); RouterChain<T> routerChain = RouterChain.buildChain(getInterface(), getUrl());
routerChain.setInvokers(getInvokers(), () -> { routerChain.setInvokers(getInvokers(), () -> {});
});
this.setRouterChain(routerChain); this.setRouterChain(routerChain);
} }
public void notify(List<Invoker<T>> invokers) { public void notify(List<Invoker<T>> invokers) {
BitList<Invoker<T>> bitList = new BitList<>(invokers); BitList<Invoker<T>> bitList = new BitList<>(invokers);
if (routerChain != null) { if (routerChain != null) {
refreshRouter(bitList.clone(), () -> this.setInvokers(bitList)); refreshRouter(bitList.clone(), () -> this.setInvokers(bitList));
} else { } else {
this.setInvokers(bitList); this.setInvokers(bitList);
} }
} }
@Override @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) { if (singleRouterChain != null) {
try { try {
List<Invoker<T>> finalInvokers = singleRouterChain.route(getConsumerUrl(), invokers, invocation); List<Invoker<T>> finalInvokers = singleRouterChain.route(getConsumerUrl(), invokers, invocation);
return finalInvokers == null ? BitList.emptyList() : finalInvokers; return finalInvokers == null ? BitList.emptyList() : finalInvokers;
} catch (Throwable t) { } 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(); return BitList.emptyList();
} }
} }

View File

@ -21,5 +21,4 @@ import org.apache.dubbo.common.extension.SPI;
import org.apache.dubbo.rpc.BaseFilter; import org.apache.dubbo.rpc.BaseFilter;
@SPI(scope = ExtensionScope.MODULE) @SPI(scope = ExtensionScope.MODULE)
public interface ClusterFilter extends BaseFilter { public interface ClusterFilter extends BaseFilter {}
}

View File

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

View File

@ -92,7 +92,8 @@ public interface FilterChainBuilder {
public Result invoke(Invocation invocation) throws RpcException { public Result invoke(Invocation invocation) throws RpcException {
Result asyncResult; Result asyncResult;
try { try {
InvocationProfilerUtils.enterDetailProfiler(invocation, () -> "Filter " + filter.getClass().getName() + " invoke."); InvocationProfilerUtils.enterDetailProfiler(
invocation, () -> "Filter " + filter.getClass().getName() + " invoke.");
asyncResult = filter.invoke(nextNode, invocation); asyncResult = filter.invoke(nextNode, invocation);
} catch (Exception e) { } catch (Exception e) {
InvocationProfilerUtils.releaseDetailProfiler(invocation); InvocationProfilerUtils.releaseDetailProfiler(invocation);
@ -159,12 +160,11 @@ public interface FilterChainBuilder {
* @param <TYPE> * @param <TYPE>
*/ */
class ClusterFilterChainNode<T, TYPE extends ClusterInvoker<T>, FILTER extends BaseFilter> 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) { public ClusterFilterChainNode(TYPE originalInvoker, Invoker<T> nextNode, FILTER filter) {
super(originalInvoker, nextNode, filter); super(originalInvoker, nextNode, filter);
} }
@Override @Override
public URL getRegistryUrl() { public URL getRegistryUrl() {
return getOriginalInvoker().getRegistryUrl(); return getOriginalInvoker().getRegistryUrl();
@ -182,7 +182,8 @@ public interface FilterChainBuilder {
} }
class CallbackRegistrationInvoker<T, FILTER extends BaseFilter> implements Invoker<T> { 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 Invoker<T> filterInvoker;
final List<FILTER> filters; final List<FILTER> filters;
@ -223,9 +224,20 @@ public interface FilterChainBuilder {
} }
} }
} catch (RuntimeException runtimeException) { } 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()) { 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; filterRuntimeException = runtimeException;
t = runtimeException; t = runtimeException;
@ -264,11 +276,12 @@ public interface FilterChainBuilder {
} }
} }
class ClusterCallbackRegistrationInvoker<T, FILTER extends BaseFilter> extends CallbackRegistrationInvoker<T, FILTER> class ClusterCallbackRegistrationInvoker<T, FILTER extends BaseFilter>
implements ClusterInvoker<T> { extends CallbackRegistrationInvoker<T, FILTER> implements ClusterInvoker<T> {
private ClusterInvoker<T> originalInvoker; 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); super(filterInvoker, filters);
this.originalInvoker = originalInvoker; this.originalInvoker = originalInvoker;
} }
@ -293,10 +306,11 @@ public interface FilterChainBuilder {
} }
} }
@Experimental(
@Experimental("Works for the same purpose as FilterChainNode, replace FilterChainNode with this one when proved stable enough") "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> { 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; TYPE originalInvoker;
Invoker<T> nextNode; Invoker<T> nextNode;
FILTER filter; FILTER filter;
@ -330,11 +344,14 @@ public interface FilterChainBuilder {
public Result invoke(Invocation invocation) throws RpcException { public Result invoke(Invocation invocation) throws RpcException {
Result asyncResult; Result asyncResult;
try { try {
InvocationProfilerUtils.enterDetailProfiler(invocation, () -> "Filter " + filter.getClass().getName() + " invoke."); InvocationProfilerUtils.enterDetailProfiler(
invocation, () -> "Filter " + filter.getClass().getName() + " invoke.");
asyncResult = filter.invoke(nextNode, invocation); asyncResult = filter.invoke(nextNode, invocation);
if (!(asyncResult instanceof AsyncRpcResult)) { 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.) " + String msg =
"Filter class: " + filter.getClass().getName() + ". Result class: " + asyncResult.getClass().getName() + "."; "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); LOGGER.error(INTERNAL_ERROR, "", "", msg);
throw new RpcException(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> 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) { public CopyOfClusterFilterChainNode(TYPE originalInvoker, Invoker<T> nextNode, FILTER filter) {
super(originalInvoker, nextNode, filter); super(originalInvoker, nextNode, filter);
} }
@Override @Override
public URL getRegistryUrl() { public URL getRegistryUrl() {
return getOriginalInvoker().getRegistryUrl(); return getOriginalInvoker().getRegistryUrl();

View File

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

View File

@ -35,8 +35,8 @@ public class ConsumerClassLoaderFilter implements ClusterFilter {
ClassLoader originClassLoader = Thread.currentThread().getContextClassLoader(); ClassLoader originClassLoader = Thread.currentThread().getContextClassLoader();
try { try {
Optional.ofNullable(invocation.getServiceModel()) Optional.ofNullable(invocation.getServiceModel())
.map(ServiceModel::getClassLoader) .map(ServiceModel::getClassLoader)
.ifPresent(Thread.currentThread()::setContextClassLoader); .ifPresent(Thread.currentThread()::setContextClassLoader);
return invoker.invoke(invocation); return invoker.invoke(invocation);
} finally { } finally {
Thread.currentThread().setContextClassLoader(originClassLoader); Thread.currentThread().setContextClassLoader(originClassLoader);

View File

@ -56,16 +56,17 @@ public class ConsumerContextFilter implements ClusterFilter, ClusterFilter.Liste
private Set<PenetrateAttachmentSelector> supportedSelectors; private Set<PenetrateAttachmentSelector> supportedSelectors;
public ConsumerContextFilter(ApplicationModel applicationModel) { public ConsumerContextFilter(ApplicationModel applicationModel) {
ExtensionLoader<PenetrateAttachmentSelector> selectorExtensionLoader = applicationModel.getExtensionLoader(PenetrateAttachmentSelector.class); ExtensionLoader<PenetrateAttachmentSelector> selectorExtensionLoader =
applicationModel.getExtensionLoader(PenetrateAttachmentSelector.class);
supportedSelectors = selectorExtensionLoader.getSupportedExtensionInstances(); supportedSelectors = selectorExtensionLoader.getSupportedExtensionInstances();
} }
@Override @Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
RpcContext.getServiceContext() RpcContext.getServiceContext()
.setInvoker(invoker) .setInvoker(invoker)
.setInvocation(invocation) .setInvocation(invocation)
.setLocalAddress(NetUtils.getLocalHost(), 0); .setLocalAddress(NetUtils.getLocalHost(), 0);
RpcContext context = RpcContext.getClientAttachment(); RpcContext context = RpcContext.getClientAttachment();
context.setAttachment(REMOTE_APPLICATION_KEY, invoker.getUrl().getApplication()); context.setAttachment(REMOTE_APPLICATION_KEY, invoker.getUrl().getApplication());
@ -75,15 +76,18 @@ public class ConsumerContextFilter implements ClusterFilter, ClusterFilter.Liste
if (CollectionUtils.isNotEmpty(supportedSelectors)) { if (CollectionUtils.isNotEmpty(supportedSelectors)) {
for (PenetrateAttachmentSelector supportedSelector : supportedSelectors) { for (PenetrateAttachmentSelector supportedSelector : supportedSelectors) {
Map<String, Object> selected = supportedSelector.select(invocation, RpcContext.getClientAttachment(), RpcContext.getServerAttachment()); Map<String, Object> selected = supportedSelector.select(
invocation, RpcContext.getClientAttachment(), RpcContext.getServerAttachment());
if (CollectionUtils.isNotEmptyMap(selected)) { if (CollectionUtils.isNotEmptyMap(selected)) {
((RpcInvocation) invocation).addObjectAttachments(selected); ((RpcInvocation) invocation).addObjectAttachments(selected);
} }
} }
} else { } else {
((RpcInvocation) invocation).addObjectAttachments(RpcContext.getServerAttachment().getObjectAttachments()); ((RpcInvocation) invocation)
.addObjectAttachments(RpcContext.getServerAttachment().getObjectAttachments());
} }
Map<String, Object> contextAttachments = RpcContext.getClientAttachment().getObjectAttachments(); Map<String, Object> contextAttachments =
RpcContext.getClientAttachment().getObjectAttachments();
if (CollectionUtils.isNotEmptyMap(contextAttachments)) { if (CollectionUtils.isNotEmptyMap(contextAttachments)) {
/** /**
* invocation.addAttachmentsIfAbsent(context){@link RpcInvocation#addAttachmentsIfAbsent(Map)}should not be used here, * invocation.addAttachmentsIfAbsent(context){@link RpcInvocation#addAttachmentsIfAbsent(Map)}should not be used here,
@ -106,9 +110,12 @@ public class ConsumerContextFilter implements ClusterFilter, ClusterFilter.Liste
TimeoutCountDown timeoutCountDown = (TimeoutCountDown) countDown; TimeoutCountDown timeoutCountDown = (TimeoutCountDown) countDown;
if (timeoutCountDown.isExpired()) { if (timeoutCountDown.isExpired()) {
return AsyncRpcResult.newDefaultAsyncResult(new RpcException(RpcException.TIMEOUT_TERMINATE, return AsyncRpcResult.newDefaultAsyncResult(
"No time left for making the following call: " + invocation.getServiceName() + "." new RpcException(
+ RpcUtils.getMethodName(invocation) + ", terminate directly."), invocation); RpcException.TIMEOUT_TERMINATE,
"No time left for making the following call: " + invocation.getServiceName() + "."
+ RpcUtils.getMethodName(invocation) + ", terminate directly."),
invocation);
} }
} }
} }
@ -135,14 +142,15 @@ public class ConsumerContextFilter implements ClusterFilter, ClusterFilter.Liste
RpcInvocation rpcInvocation = (RpcInvocation) invocation; RpcInvocation rpcInvocation = (RpcInvocation) invocation;
if (rpcInvocation.getInvokeMode() != null) { if (rpcInvocation.getInvokeMode() != null) {
// clear service context if not in sync mode // clear service context if not in sync mode
if (rpcInvocation.getInvokeMode() == InvokeMode.ASYNC || rpcInvocation.getInvokeMode() == InvokeMode.FUTURE) { if (rpcInvocation.getInvokeMode() == InvokeMode.ASYNC
|| rpcInvocation.getInvokeMode() == InvokeMode.FUTURE) {
RpcContext.removeServiceContext(); RpcContext.removeServiceContext();
} }
} }
} }
// server context must not be removed because user might use it on callback. // server context must not be removed because user might use it on callback.
// So the clear of is delayed til the start of the next rpc call, see RpcContext.removeServerContext(); in invoke() above // So the clear of is delayed til the start of the next rpc call, see RpcContext.removeServerContext(); in
// invoke() above
// RpcContext.removeServerContext(); // RpcContext.removeServerContext();
} }
} }

View File

@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.filter.support; package org.apache.dubbo.rpc.cluster.filter.support;
import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector; import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
import org.apache.dubbo.metrics.event.MetricsDispatcher; import org.apache.dubbo.metrics.event.MetricsDispatcher;
@ -76,9 +74,15 @@ public class MetricsClusterFilter implements ClusterFilter, BaseFilter.Listener,
if (t instanceof RpcException) { if (t instanceof RpcException) {
RpcException e = (RpcException) t; RpcException e = (RpcException) t;
if (e.isForbidden()) { if (e.isForbidden()) {
MetricsEventBus.publish(RequestEvent.toRequestErrorEvent(applicationModel, appName, metricsDispatcher, invocation, CONSUMER_SIDE, e.getCode(), serviceLevel)); MetricsEventBus.publish(RequestEvent.toRequestErrorEvent(
applicationModel,
appName,
metricsDispatcher,
invocation,
CONSUMER_SIDE,
e.getCode(),
serviceLevel));
} }
} }
} }
} }

View File

@ -27,10 +27,11 @@ import org.apache.dubbo.rpc.cluster.filter.ClusterFilter;
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER; 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 class MetricsConsumerFilter extends MetricsFilter implements ClusterFilter, BaseFilter.Listener {
public MetricsConsumerFilter() { public MetricsConsumerFilter() {}
}
@Override @Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {

View File

@ -50,7 +50,8 @@ public class ObservationSenderFilter implements ClusterFilter, BaseFilter.Listen
applicationModel.getApplicationConfigManager().getTracing().ifPresent(cfg -> { applicationModel.getApplicationConfigManager().getTracing().ifPresent(cfg -> {
if (Boolean.TRUE.equals(cfg.getEnabled())) { if (Boolean.TRUE.equals(cfg.getEnabled())) {
observationRegistry = applicationModel.getBeanFactory().getBean(ObservationRegistry.class); observationRegistry = applicationModel.getBeanFactory().getBean(ObservationRegistry.class);
clientObservationConvention = applicationModel.getBeanFactory().getBean(DubboClientObservationConvention.class); clientObservationConvention =
applicationModel.getBeanFactory().getBean(DubboClientObservationConvention.class);
} }
}); });
} }
@ -64,7 +65,8 @@ public class ObservationSenderFilter implements ClusterFilter, BaseFilter.Listen
final Observation observation = DubboObservationDocumentation.CLIENT.observation( final Observation observation = DubboObservationDocumentation.CLIENT.observation(
this.clientObservationConvention, this.clientObservationConvention,
DefaultDubboClientObservationConvention.getInstance(), DefaultDubboClientObservationConvention.getInstance(),
() -> senderContext, observationRegistry); () -> senderContext,
observationRegistry);
invocation.put(Observation.class, observation.start()); invocation.put(Observation.class, observation.start());
return observation.scoped(() -> invoker.invoke(invocation)); return observation.scoped(() -> invoker.invoke(invocation));
} }

View File

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

View File

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

View File

@ -47,7 +47,7 @@ public abstract class AbstractLoadBalance implements LoadBalance {
* @return weight which takes warmup into account * @return weight which takes warmup into account
*/ */
static int calculateWarmupWeight(int uptime, int warmup, int weight) { 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)); 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); 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 * 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 * 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); int warmup = invoker.getUrl().getParameter(WARMUP_KEY, DEFAULT_WARMUP);
if (uptime > 0 && uptime < warmup) { if (uptime > 0 && uptime < warmup) {
weight = calculateWarmupWeight((int)uptime, warmup, weight); weight = calculateWarmupWeight((int) uptime, warmup, weight);
} }
} }
} }

View File

@ -41,36 +41,36 @@ public class AdaptiveLoadBalance extends AbstractLoadBalance {
public static final String NAME = "adaptive"; public static final String NAME = "adaptive";
//default key // default key
private String attachmentKey = "mem,load"; private String attachmentKey = "mem,load";
private final AdaptiveMetrics adaptiveMetrics; private final AdaptiveMetrics adaptiveMetrics;
public AdaptiveLoadBalance(ApplicationModel scopeModel){ public AdaptiveLoadBalance(ApplicationModel scopeModel) {
adaptiveMetrics = scopeModel.getBeanFactory().getBean(AdaptiveMetrics.class); adaptiveMetrics = scopeModel.getBeanFactory().getBean(AdaptiveMetrics.class);
} }
@Override @Override
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) { protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
Invoker<T> invoker = selectByP2C(invokers,invocation); Invoker<T> invoker = selectByP2C(invokers, invocation);
invocation.setAttachment(Constants.ADAPTIVE_LOADBALANCE_ATTACHMENT_KEY,attachmentKey); invocation.setAttachment(Constants.ADAPTIVE_LOADBALANCE_ATTACHMENT_KEY, attachmentKey);
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
invocation.getAttributes().put(Constants.ADAPTIVE_LOADBALANCE_START_TIME,startTime); invocation.getAttributes().put(Constants.ADAPTIVE_LOADBALANCE_START_TIME, startTime);
invocation.getAttributes().put(LOADBALANCE_KEY,LoadbalanceRules.ADAPTIVE); invocation.getAttributes().put(LOADBALANCE_KEY, LoadbalanceRules.ADAPTIVE);
adaptiveMetrics.addConsumerReq(getServiceKey(invoker,invocation)); adaptiveMetrics.addConsumerReq(getServiceKey(invoker, invocation));
adaptiveMetrics.setPickTime(getServiceKey(invoker,invocation),startTime); adaptiveMetrics.setPickTime(getServiceKey(invoker, invocation), startTime);
return invoker; return invoker;
} }
private <T> Invoker<T> selectByP2C(List<Invoker<T>> invokers, Invocation invocation){ private <T> Invoker<T> selectByP2C(List<Invoker<T>> invokers, Invocation invocation) {
int length = invokers.size(); int length = invokers.size();
if(length == 1) { if (length == 1) {
return invokers.get(0); return invokers.get(0);
} }
if(length == 2) { if (length == 2) {
return chooseLowLoadInvoker(invokers.get(0),invokers.get(1),invocation); return chooseLowLoadInvoker(invokers.get(0), invokers.get(1), invocation);
} }
int pos1 = ThreadLocalRandom.current().nextInt(length); int pos1 = ThreadLocalRandom.current().nextInt(length);
@ -79,22 +79,22 @@ public class AdaptiveLoadBalance extends AbstractLoadBalance {
pos2 = pos2 + 1; pos2 = pos2 + 1;
} }
return chooseLowLoadInvoker(invokers.get(pos1),invokers.get(pos2),invocation); return chooseLowLoadInvoker(invokers.get(pos1), invokers.get(pos2), invocation);
} }
private String getServiceKey(Invoker<?> invoker,Invocation invocation){ private String getServiceKey(Invoker<?> invoker, Invocation invocation) {
String key = (String) invocation.getAttributes().get(invoker); String key = (String) invocation.getAttributes().get(invoker);
if (StringUtils.isNotEmpty(key)){ if (StringUtils.isNotEmpty(key)) {
return key; return key;
} }
key = buildServiceKey(invoker,invocation); key = buildServiceKey(invoker, invocation);
invocation.getAttributes().put(invoker,key); invocation.getAttributes().put(invoker, key);
return key; return key;
} }
private String buildServiceKey(Invoker<?> invoker,Invocation invocation){ private String buildServiceKey(Invoker<?> invoker, Invocation invocation) {
URL url = invoker.getUrl(); URL url = invoker.getUrl();
StringBuilder sb = new StringBuilder(128); StringBuilder sb = new StringBuilder(128);
sb.append(url.getAddress()).append(":").append(invocation.getProtocolServiceKey()); sb.append(url.getAddress()).append(":").append(invocation.getProtocolServiceKey());
@ -104,16 +104,19 @@ public class AdaptiveLoadBalance extends AbstractLoadBalance {
private int getTimeout(Invoker<?> invoker, Invocation invocation) { private int getTimeout(Invoker<?> invoker, Invocation invocation) {
URL url = invoker.getUrl(); URL url = invoker.getUrl();
String methodName = RpcUtils.getMethodName(invocation); String methodName = RpcUtils.getMethodName(invocation);
return (int) RpcUtils.getTimeout(url,methodName, RpcContext.getClientAttachment(),invocation, DEFAULT_TIMEOUT); return (int)
RpcUtils.getTimeout(url, methodName, RpcContext.getClientAttachment(), invocation, DEFAULT_TIMEOUT);
} }
private <T> Invoker<T> chooseLowLoadInvoker(Invoker<T> invoker1,Invoker<T> invoker2,Invocation invocation){ private <T> Invoker<T> chooseLowLoadInvoker(Invoker<T> invoker1, Invoker<T> invoker2, Invocation invocation) {
int weight1 = getWeight(invoker1, invocation); int weight1 = getWeight(invoker1, invocation);
int weight2 = getWeight(invoker2, invocation); int weight2 = getWeight(invoker2, invocation);
int timeout1 = getTimeout(invoker1, invocation); int timeout1 = getTimeout(invoker1, invocation);
int timeout2 = getTimeout(invoker2, invocation); int timeout2 = getTimeout(invoker2, invocation);
long load1 = Double.doubleToLongBits(adaptiveMetrics.getLoad(getServiceKey(invoker1,invocation),weight1,timeout1 )); long load1 = Double.doubleToLongBits(
long load2 = Double.doubleToLongBits(adaptiveMetrics.getLoad(getServiceKey(invoker2,invocation),weight2,timeout2 )); adaptiveMetrics.getLoad(getServiceKey(invoker1, invocation), weight1, timeout1));
long load2 = Double.doubleToLongBits(
adaptiveMetrics.getLoad(getServiceKey(invoker2, invocation), weight2, timeout2));
if (load1 == load2) { if (load1 == load2) {
// The sum of weights // The sum of weights
@ -129,5 +132,4 @@ public class AdaptiveLoadBalance extends AbstractLoadBalance {
} }
return load1 > load2 ? invoker2 : invoker1; return load1 > load2 ? invoker2 : invoker1;
} }
} }

View File

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

View File

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

View File

@ -78,7 +78,8 @@ public class RandomLoadBalance extends AbstractLoadBalance {
} }
} }
if (totalWeight > 0 && !sameWeight) { 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); int offset = ThreadLocalRandom.current().nextInt(totalWeight);
// Return an invoker based on the random value. // Return an invoker based on the random value.
if (length <= 4) { if (length <= 4) {
@ -92,7 +93,7 @@ public class RandomLoadBalance extends AbstractLoadBalance {
if (i < 0) { if (i < 0) {
i = -i - 1; i = -i - 1;
} else { } else {
while (weights[i+1] == offset) { while (weights[i + 1] == offset) {
i++; i++;
} }
i++; i++;

View File

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

View File

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

View File

@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.merger; package org.apache.dubbo.rpc.cluster.merger;
import org.apache.dubbo.common.utils.ArrayUtils; import org.apache.dubbo.common.utils.ArrayUtils;
@ -43,5 +42,4 @@ public class BooleanArrayMerger implements Merger<boolean[]> {
} }
return result; return result;
} }
} }

View File

@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.merger; package org.apache.dubbo.rpc.cluster.merger;
import org.apache.dubbo.common.utils.ArrayUtils; import org.apache.dubbo.common.utils.ArrayUtils;
@ -43,5 +42,4 @@ public class ByteArrayMerger implements Merger<byte[]> {
} }
return result; return result;
} }
} }

View File

@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.merger; package org.apache.dubbo.rpc.cluster.merger;
import org.apache.dubbo.common.utils.ArrayUtils; import org.apache.dubbo.common.utils.ArrayUtils;

View File

@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.merger; package org.apache.dubbo.rpc.cluster.merger;
import org.apache.dubbo.common.utils.ArrayUtils; import org.apache.dubbo.common.utils.ArrayUtils;
@ -30,7 +29,8 @@ public class DoubleArrayMerger implements Merger<double[]> {
if (ArrayUtils.isEmpty(items)) { if (ArrayUtils.isEmpty(items)) {
return new double[0]; return new double[0];
} }
return Arrays.stream(items).filter(Objects::nonNull) return Arrays.stream(items)
.filter(Objects::nonNull)
.flatMapToDouble(Arrays::stream) .flatMapToDouble(Arrays::stream)
.toArray(); .toArray();
} }

View File

@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.merger; package org.apache.dubbo.rpc.cluster.merger;
import org.apache.dubbo.common.utils.ArrayUtils; import org.apache.dubbo.common.utils.ArrayUtils;

View File

@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.merger; package org.apache.dubbo.rpc.cluster.merger;
import org.apache.dubbo.common.utils.ArrayUtils; import org.apache.dubbo.common.utils.ArrayUtils;
@ -30,9 +29,9 @@ public class IntArrayMerger implements Merger<int[]> {
if (ArrayUtils.isEmpty(items)) { if (ArrayUtils.isEmpty(items)) {
return new int[0]; return new int[0];
} }
return Arrays.stream(items).filter(Objects::nonNull) return Arrays.stream(items)
.filter(Objects::nonNull)
.flatMapToInt(Arrays::stream) .flatMapToInt(Arrays::stream)
.toArray(); .toArray();
} }
} }

View File

@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.merger; package org.apache.dubbo.rpc.cluster.merger;
import org.apache.dubbo.common.utils.ArrayUtils; import org.apache.dubbo.common.utils.ArrayUtils;
@ -34,10 +33,9 @@ public class ListMerger implements Merger<List<?>> {
if (ArrayUtils.isEmpty(items)) { if (ArrayUtils.isEmpty(items)) {
return Collections.emptyList(); return Collections.emptyList();
} }
return Stream.of(items).filter(Objects::nonNull) return Stream.of(items)
.filter(Objects::nonNull)
.flatMap(Collection::stream) .flatMap(Collection::stream)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
} }

View File

@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.merger; package org.apache.dubbo.rpc.cluster.merger;
import org.apache.dubbo.common.utils.ArrayUtils; import org.apache.dubbo.common.utils.ArrayUtils;
@ -30,7 +29,8 @@ public class LongArrayMerger implements Merger<long[]> {
if (ArrayUtils.isEmpty(items)) { if (ArrayUtils.isEmpty(items)) {
return new long[0]; return new long[0];
} }
return Arrays.stream(items).filter(Objects::nonNull) return Arrays.stream(items)
.filter(Objects::nonNull)
.flatMapToLong(Arrays::stream) .flatMapToLong(Arrays::stream)
.toArray(); .toArray();
} }

View File

@ -36,5 +36,4 @@ public class MapMerger implements Merger<Map<?, ?>> {
Stream.of(items).filter(Objects::nonNull).forEach(result::putAll); Stream.of(items).filter(Objects::nonNull).forEach(result::putAll);
return result; return result;
} }
} }

View File

@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.merger; package org.apache.dubbo.rpc.cluster.merger;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
@ -69,13 +68,17 @@ public class MergerFactory implements ScopeModelAware {
} }
private void loadMergers() { private void loadMergers() {
Set<String> names = scopeModel.getExtensionLoader(Merger.class) Set<String> names = scopeModel.getExtensionLoader(Merger.class).getSupportedExtensions();
.getSupportedExtensions();
for (String name : names) { for (String name : names) {
Merger m = scopeModel.getExtensionLoader(Merger.class).getExtension(name); Merger m = scopeModel.getExtensionLoader(Merger.class).getExtension(name);
Class<?> actualTypeArg = getActualTypeArgument(m.getClass()); Class<?> actualTypeArg = getActualTypeArgument(m.getClass());
if (actualTypeArg == null) { if (actualTypeArg == null) {
logger.warn(CLUSTER_FAILED_LOAD_MERGER,"load merger config failed","","Failed to get actual type argument from merger " + m.getClass().getName()); logger.warn(
CLUSTER_FAILED_LOAD_MERGER,
"load merger config failed",
"",
"Failed to get actual type argument from merger "
+ m.getClass().getName());
continue; continue;
} }
MERGER_CACHE.putIfAbsent(actualTypeArg, m); MERGER_CACHE.putIfAbsent(actualTypeArg, m);
@ -94,7 +97,7 @@ public class MergerFactory implements ScopeModelAware {
ParameterizedType mergerType; ParameterizedType mergerType;
for (Type it : interfaceTypes) { for (Type it : interfaceTypes) {
if (it instanceof ParameterizedType if (it instanceof ParameterizedType
&& (mergerType = ((ParameterizedType) it)).getRawType() == Merger.class) { && (mergerType = ((ParameterizedType) it)).getRawType() == Merger.class) {
Type typeArg = mergerType.getActualTypeArguments()[0]; Type typeArg = mergerType.getActualTypeArguments()[0];
return TypeUtils.getRawClass(typeArg); return TypeUtils.getRawClass(typeArg);
} }

View File

@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.merger; package org.apache.dubbo.rpc.cluster.merger;
import org.apache.dubbo.common.utils.ArrayUtils; import org.apache.dubbo.common.utils.ArrayUtils;

View File

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

View File

@ -34,7 +34,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
public class RouterSnapshotFilter implements ClusterFilter, BaseFilter.Listener { public class RouterSnapshotFilter implements ClusterFilter, BaseFilter.Listener {
private final RouterSnapshotSwitcher switcher; 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) { public RouterSnapshotFilter(FrameworkModel frameworkModel) {
this.switcher = frameworkModel.getBeanFactory().getBean(RouterSnapshotSwitcher.class); this.switcher = frameworkModel.getBeanFactory().getBean(RouterSnapshotSwitcher.class);

View File

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

View File

@ -26,7 +26,7 @@ public class RouterSnapshotSwitcher {
private volatile boolean enable; private volatile boolean enable;
private final Set<String> enabledService = new ConcurrentHashSet<>(); 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 final AtomicInteger offset = new AtomicInteger(0);
private volatile String[] recentSnapshot = new String[MAX_LENGTH]; private volatile String[] recentSnapshot = new String[MAX_LENGTH];

View File

@ -84,7 +84,8 @@ public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
super(url); super(url);
this.setForce(force); this.setForce(force);
this.enabled = enabled; this.enabled = enabled;
matcherFactories = moduleModel.getExtensionLoader(ConditionMatcherFactory.class).getActivateExtensions(); matcherFactories =
moduleModel.getExtensionLoader(ConditionMatcherFactory.class).getActivateExtensions();
if (enabled) { if (enabled) {
this.init(rule); this.init(rule);
} }
@ -94,7 +95,8 @@ public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
super(url); super(url);
this.setUrl(url); this.setUrl(url);
this.setForce(url.getParameter(FORCE_KEY, false)); this.setForce(url.getParameter(FORCE_KEY, false));
matcherFactories = moduleModel.getExtensionLoader(ConditionMatcherFactory.class).getActivateExtensions(); matcherFactories =
moduleModel.getExtensionLoader(ConditionMatcherFactory.class).getActivateExtensions();
this.enabled = url.getParameter(ENABLED_KEY, true); this.enabled = url.getParameter(ENABLED_KEY, true);
if (enabled) { if (enabled) {
init(url.getParameterAndDecoded(RULE_KEY)); init(url.getParameterAndDecoded(RULE_KEY));
@ -110,8 +112,10 @@ public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
int i = rule.indexOf("=>"); int i = rule.indexOf("=>");
String whenRule = i < 0 ? null : rule.substring(0, i).trim(); String whenRule = i < 0 ? null : rule.substring(0, i).trim();
String thenRule = i < 0 ? rule.trim() : rule.substring(i + 2).trim(); String thenRule = i < 0 ? rule.trim() : rule.substring(i + 2).trim();
Map<String, ConditionMatcher> when = StringUtils.isBlank(whenRule) || "true".equals(whenRule) ? new HashMap<>() : parseRule(whenRule); Map<String, ConditionMatcher> when =
Map<String, ConditionMatcher> then = StringUtils.isBlank(thenRule) || "false".equals(thenRule) ? null : parseRule(thenRule); StringUtils.isBlank(whenRule) || "true".equals(whenRule) ? new HashMap<>() : parseRule(whenRule);
Map<String, ConditionMatcher> then =
StringUtils.isBlank(thenRule) || "false".equals(thenRule) ? null : parseRule(thenRule);
// NOTE: It should be determined on the business level whether the `When condition` can be empty or not. // NOTE: It should be determined on the business level whether the `When condition` can be empty or not.
this.whenCondition = when; this.whenCondition = when;
this.thenCondition = then; this.thenCondition = then;
@ -120,8 +124,7 @@ public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
} }
} }
private Map<String, ConditionMatcher> parseRule(String rule) private Map<String, ConditionMatcher> parseRule(String rule) throws ParseException {
throws ParseException {
Map<String, ConditionMatcher> condition = new HashMap<>(); Map<String, ConditionMatcher> condition = new HashMap<>();
if (StringUtils.isBlank(rule)) { if (StringUtils.isBlank(rule)) {
return condition; return condition;
@ -151,10 +154,12 @@ public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
// The Value in the KV part. // The Value in the KV part.
else if ("=".equals(separator)) { else if ("=".equals(separator)) {
if (matcherPair == null) { if (matcherPair == null) {
throw new ParseException("Illegal route rule \"" throw new ParseException(
+ rule + "\", The error char '" + separator "Illegal route rule \""
+ "' at index " + matcher.start() + " before \"" + rule + "\", The error char '" + separator
+ content + "\".", matcher.start()); + "' at index " + matcher.start() + " before \""
+ content + "\".",
matcher.start());
} }
values = matcherPair.getMatches(); values = matcherPair.getMatches();
@ -163,10 +168,12 @@ public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
// The Value in the KV part. // The Value in the KV part.
else if ("!=".equals(separator)) { else if ("!=".equals(separator)) {
if (matcherPair == null) { if (matcherPair == null) {
throw new ParseException("Illegal route rule \"" throw new ParseException(
+ rule + "\", The error char '" + separator "Illegal route rule \""
+ "' at index " + matcher.start() + " before \"" + rule + "\", The error char '" + separator
+ content + "\".", matcher.start()); + "' at index " + matcher.start() + " before \""
+ content + "\".",
matcher.start());
} }
values = matcherPair.getMismatches(); values = matcherPair.getMismatches();
@ -175,25 +182,34 @@ public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
// The Value in the KV part, if Value have more than one items. // The Value in the KV part, if Value have more than one items.
else if (",".equals(separator)) { // Should be separated by ',' else if (",".equals(separator)) { // Should be separated by ','
if (values == null || values.isEmpty()) { if (values == null || values.isEmpty()) {
throw new ParseException("Illegal route rule \"" throw new ParseException(
+ rule + "\", The error char '" + separator "Illegal route rule \""
+ "' at index " + matcher.start() + " before \"" + rule + "\", The error char '" + separator
+ content + "\".", matcher.start()); + "' at index " + matcher.start() + " before \""
+ content + "\".",
matcher.start());
} }
values.add(content); values.add(content);
} else { } else {
throw new ParseException("Illegal route rule \"" + rule throw new ParseException(
+ "\", The error char '" + separator + "' at index " "Illegal route rule \"" + rule
+ matcher.start() + " before \"" + content + "\".", matcher.start()); + "\", The error char '" + separator + "' at index "
+ matcher.start() + " before \"" + content + "\".",
matcher.start());
} }
} }
return condition; return condition;
} }
@Override @Override
protected BitList<Invoker<T>> doRoute(BitList<Invoker<T>> invokers, URL url, Invocation invocation, protected BitList<Invoker<T>> doRoute(
boolean needToPrintMessage, Holder<RouterSnapshotNode<T>> nodeHolder, BitList<Invoker<T>> invokers,
Holder<String> messageHolder) throws RpcException { URL url,
Invocation invocation,
boolean needToPrintMessage,
Holder<RouterSnapshotNode<T>> nodeHolder,
Holder<String> messageHolder)
throws RpcException {
if (!enabled) { if (!enabled) {
if (needToPrintMessage) { if (needToPrintMessage) {
messageHolder.set("Directly return. Reason: ConditionRouter disabled."); messageHolder.set("Directly return. Reason: ConditionRouter disabled.");
@ -215,7 +231,13 @@ public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
return invokers; return invokers;
} }
if (thenCondition == null) { if (thenCondition == null) {
logger.warn(CLUSTER_CONDITIONAL_ROUTE_LIST_EMPTY,"condition state router thenCondition is empty","","The current consumer in the service blacklist. consumer: " + NetUtils.getLocalHost() + ", service: " + url.getServiceKey()); if (needToPrintMessage) { logger.warn(
CLUSTER_CONDITIONAL_ROUTE_LIST_EMPTY,
"condition state router thenCondition is empty",
"",
"The current consumer in the service blacklist. consumer: " + NetUtils.getLocalHost()
+ ", service: " + url.getServiceKey());
if (needToPrintMessage) {
messageHolder.set("Empty return. Reason: ThenCondition is empty."); messageHolder.set("Empty return. Reason: ThenCondition is empty.");
} }
return BitList.emptyList(); return BitList.emptyList();
@ -229,14 +251,26 @@ public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
} }
return result; return result;
} else if (this.isForce()) { } else if (this.isForce()) {
logger.warn(CLUSTER_CONDITIONAL_ROUTE_LIST_EMPTY,"execute condition state router result list is empty. and force=true","","The route result is empty and force execute. consumer: " + NetUtils.getLocalHost() + ", service: " + url.getServiceKey() + ", router: " + url.getParameterAndDecoded(RULE_KEY)); logger.warn(
CLUSTER_CONDITIONAL_ROUTE_LIST_EMPTY,
"execute condition state router result list is empty. and force=true",
"",
"The route result is empty and force execute. consumer: " + NetUtils.getLocalHost()
+ ", service: " + url.getServiceKey() + ", router: "
+ url.getParameterAndDecoded(RULE_KEY));
if (needToPrintMessage) { if (needToPrintMessage) {
messageHolder.set("Empty return. Reason: Empty result from condition and condition is force."); messageHolder.set("Empty return. Reason: Empty result from condition and condition is force.");
} }
return result; return result;
} }
} catch (Throwable t) { } catch (Throwable t) {
logger.error(CLUSTER_FAILED_EXEC_CONDITION_ROUTER,"execute condition state router exception","","Failed to execute condition router rule: " + getUrl() + ", invokers: " + invokers + ", cause: " + t.getMessage(),t); logger.error(
CLUSTER_FAILED_EXEC_CONDITION_ROUTER,
"execute condition state router exception",
"",
"Failed to execute condition router rule: " + getUrl() + ", invokers: " + invokers + ", cause: "
+ t.getMessage(),
t);
} }
if (needToPrintMessage) { if (needToPrintMessage) {
messageHolder.set("Directly return. Reason: Error occurred ( or result is empty )."); messageHolder.set("Directly return. Reason: Error occurred ( or result is empty ).");
@ -247,7 +281,7 @@ public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
@Override @Override
public boolean isRuntime() { public boolean isRuntime() {
// We always return true for previously defined Router, that is, old Router doesn't support cache anymore. // We always return true for previously defined Router, that is, old Router doesn't support cache anymore.
// return true; // return true;
return this.getUrl().getParameter(RUNTIME_KEY, false); return this.getUrl().getParameter(RUNTIME_KEY, false);
} }
@ -257,7 +291,10 @@ public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
return factory.createMatcher(key, moduleModel); return factory.createMatcher(key, moduleModel);
} }
} }
return moduleModel.getExtensionLoader(ConditionMatcherFactory.class).getExtension("param").createMatcher(key, moduleModel); return moduleModel
.getExtensionLoader(ConditionMatcherFactory.class)
.getExtension("param")
.createMatcher(key, moduleModel);
} }
boolean matchWhen(URL url, Invocation invocation) { boolean matchWhen(URL url, Invocation invocation) {
@ -276,7 +313,12 @@ public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
return doMatch(url, param, null, thenCondition, false); return doMatch(url, param, null, thenCondition, false);
} }
private boolean doMatch(URL url, URL param, Invocation invocation, Map<String, ConditionMatcher> conditions, boolean isWhenCondition) { private boolean doMatch(
URL url,
URL param,
Invocation invocation,
Map<String, ConditionMatcher> conditions,
boolean isWhenCondition) {
Map<String, String> sample = url.toOriginalMap(); Map<String, String> sample = url.toOriginalMap();
for (Map.Entry<String, ConditionMatcher> entry : conditions.entrySet()) { for (Map.Entry<String, ConditionMatcher> entry : conditions.entrySet()) {
ConditionMatcher matchPair = entry.getValue(); ConditionMatcher matchPair = entry.getValue();

View File

@ -50,7 +50,8 @@ public abstract class ListenableStateRouter<T> extends AbstractStateRouter<T> im
public static final String NAME = "LISTENABLE_ROUTER"; public static final String NAME = "LISTENABLE_ROUTER";
public static final String RULE_SUFFIX = ".condition-router"; public static final String RULE_SUFFIX = ".condition-router";
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(ListenableStateRouter.class); private static final ErrorTypeAwareLogger logger =
LoggerFactory.getErrorTypeAwareLogger(ListenableStateRouter.class);
private volatile ConditionRouterRule routerRule; private volatile ConditionRouterRule routerRule;
private volatile List<ConditionStateRouter<T>> conditionRouters = Collections.emptyList(); private volatile List<ConditionStateRouter<T>> conditionRouters = Collections.emptyList();
private final String ruleKey; private final String ruleKey;
@ -65,8 +66,8 @@ public abstract class ListenableStateRouter<T> extends AbstractStateRouter<T> im
@Override @Override
public synchronized void process(ConfigChangedEvent event) { public synchronized void process(ConfigChangedEvent event) {
if (logger.isInfoEnabled()) { if (logger.isInfoEnabled()) {
logger.info("Notification of condition rule, change type is: " + event.getChangeType() + logger.info("Notification of condition rule, change type is: " + event.getChangeType() + ", raw rule is:\n "
", raw rule is:\n " + event.getContent()); + event.getContent());
} }
if (event.getChangeType().equals(ConfigChangeType.DELETED)) { if (event.getChangeType().equals(ConfigChangeType.DELETED)) {
@ -77,18 +78,31 @@ public abstract class ListenableStateRouter<T> extends AbstractStateRouter<T> im
routerRule = ConditionRuleParser.parse(event.getContent()); routerRule = ConditionRuleParser.parse(event.getContent());
generateConditions(routerRule); generateConditions(routerRule);
} catch (Exception e) { } catch (Exception e) {
logger.error(CLUSTER_FAILED_RULE_PARSING,"Failed to parse the raw condition rule","","Failed to parse the raw condition rule and it will not take effect, please check " + logger.error(
"if the condition rule matches with the template, the raw rule is:\n " + event.getContent(),e); CLUSTER_FAILED_RULE_PARSING,
"Failed to parse the raw condition rule",
"",
"Failed to parse the raw condition rule and it will not take effect, please check "
+ "if the condition rule matches with the template, the raw rule is:\n "
+ event.getContent(),
e);
} }
} }
} }
@Override @Override
public BitList<Invoker<T>> doRoute(BitList<Invoker<T>> invokers, URL url, Invocation invocation, public BitList<Invoker<T>> doRoute(
boolean needToPrintMessage, Holder<RouterSnapshotNode<T>> nodeHolder, Holder<String> messageHolder) throws RpcException { BitList<Invoker<T>> invokers,
URL url,
Invocation invocation,
boolean needToPrintMessage,
Holder<RouterSnapshotNode<T>> nodeHolder,
Holder<String> messageHolder)
throws RpcException {
if (CollectionUtils.isEmpty(invokers) || conditionRouters.size() == 0) { if (CollectionUtils.isEmpty(invokers) || conditionRouters.size() == 0) {
if (needToPrintMessage) { if (needToPrintMessage) {
messageHolder.set("Directly return. Reason: Invokers from previous router is empty or conditionRouters is empty."); messageHolder.set(
"Directly return. Reason: Invokers from previous router is empty or conditionRouters is empty.");
} }
return invokers; return invokers;
} }
@ -123,9 +137,9 @@ public abstract class ListenableStateRouter<T> extends AbstractStateRouter<T> im
private void generateConditions(ConditionRouterRule rule) { private void generateConditions(ConditionRouterRule rule) {
if (rule != null && rule.isValid()) { if (rule != null && rule.isValid()) {
this.conditionRouters = rule.getConditions() this.conditionRouters = rule.getConditions().stream()
.stream() .map(condition ->
.map(condition -> new ConditionStateRouter<T>(getUrl(), condition, rule.isForce(), rule.isEnabled())) new ConditionStateRouter<T>(getUrl(), condition, rule.isForce(), rule.isEnabled()))
.collect(Collectors.toList()); .collect(Collectors.toList());
for (ConditionStateRouter<T> conditionRouter : this.conditionRouters) { for (ConditionStateRouter<T> conditionRouter : this.conditionRouters) {
conditionRouter.setNextRouter(TailStateRouter.getInstance()); conditionRouter.setNextRouter(TailStateRouter.getInstance());

View File

@ -33,7 +33,8 @@ import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
* Application level router, "application.condition-router" * Application level router, "application.condition-router"
*/ */
public class ProviderAppStateRouter<T> extends ListenableStateRouter<T> { public class ProviderAppStateRouter<T> extends ListenableStateRouter<T> {
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(ListenableStateRouter.class); private static final ErrorTypeAwareLogger logger =
LoggerFactory.getErrorTypeAwareLogger(ListenableStateRouter.class);
public static final String NAME = "PROVIDER_APP_ROUTER"; public static final String NAME = "PROVIDER_APP_ROUTER";
private String application; private String application;
private final String currentApplication; private final String currentApplication;
@ -55,7 +56,11 @@ public class ProviderAppStateRouter<T> extends ListenableStateRouter<T> {
// provider application is empty or equals with the current application // provider application is empty or equals with the current application
if (isEmpty(providerApplication)) { if (isEmpty(providerApplication)) {
logger.warn(CLUSTER_TAG_ROUTE_EMPTY, "condition router get providerApplication is empty, will not subscribe to provider app rules.", "", ""); logger.warn(
CLUSTER_TAG_ROUTE_EMPTY,
"condition router get providerApplication is empty, will not subscribe to provider app rules.",
"",
"");
return; return;
} }
if (providerApplication.equals(currentApplication)) { if (providerApplication.equals(currentApplication)) {

View File

@ -34,5 +34,4 @@ public class ServiceStateRouterFactory extends CacheableStateRouterFactory {
protected <T> StateRouter<T> createRouter(Class<T> interfaceClass, URL url) { protected <T> StateRouter<T> createRouter(Class<T> interfaceClass, URL url) {
return new ServiceStateRouter<T>(url); return new ServiceStateRouter<T>(url);
} }
} }

View File

@ -34,15 +34,14 @@ public class ConditionRouterRule extends AbstractRouterRule {
Object conditions = map.get(CONDITIONS_KEY); Object conditions = map.get(CONDITIONS_KEY);
if (conditions != null && List.class.isAssignableFrom(conditions.getClass())) { if (conditions != null && List.class.isAssignableFrom(conditions.getClass())) {
conditionRouterRule.setConditions(((List<Object>) conditions).stream() conditionRouterRule.setConditions(
.map(String::valueOf).collect(Collectors.toList())); ((List<Object>) conditions).stream().map(String::valueOf).collect(Collectors.toList()));
} }
return conditionRouterRule; return conditionRouterRule;
} }
public ConditionRouterRule() { public ConditionRouterRule() {}
}
public List<String> getConditions() { public List<String> getConditions() {
return conditions; return conditions;

View File

@ -18,12 +18,12 @@ package org.apache.dubbo.rpc.cluster.router.condition.config.model;
import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.common.utils.CollectionUtils;
import java.util.Map;
import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor; import org.yaml.snakeyaml.constructor.SafeConstructor;
import java.util.Map;
/** /**
* %YAML1.2 * %YAML1.2
* *
@ -51,5 +51,4 @@ public class ConditionRuleParser {
return rule; return rule;
} }
} }

View File

@ -38,7 +38,8 @@ import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_FAIL
* provides the common match logics. * provides the common match logics.
*/ */
public abstract class AbstractConditionMatcher implements ConditionMatcher { public abstract class AbstractConditionMatcher implements ConditionMatcher {
public static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(AbstractConditionMatcher.class); public static final ErrorTypeAwareLogger logger =
LoggerFactory.getErrorTypeAwareLogger(AbstractConditionMatcher.class);
public static final String DOES_NOT_FOUND_VALUE = "dubbo_internal_not_found_argument_condition_value"; public static final String DOES_NOT_FOUND_VALUE = "dubbo_internal_not_found_argument_condition_value";
final Set<String> matches = new HashSet<>(); final Set<String> matches = new HashSet<>();
final Set<String> mismatches = new HashSet<>(); final Set<String> mismatches = new HashSet<>();
@ -52,9 +53,10 @@ public abstract class AbstractConditionMatcher implements ConditionMatcher {
this.valueMatchers = model.getExtensionLoader(ValuePattern.class).getActivateExtensions(); this.valueMatchers = model.getExtensionLoader(ValuePattern.class).getActivateExtensions();
} }
public static String getSampleValueFromUrl(String conditionKey, Map<String, String> sample, URL param, Invocation invocation) { public static String getSampleValueFromUrl(
String conditionKey, Map<String, String> sample, URL param, Invocation invocation) {
String sampleValue; String sampleValue;
//get real invoked method name from invocation // get real invoked method name from invocation
if (invocation != null && (METHOD_KEY.equals(conditionKey) || METHODS_KEY.equals(conditionKey))) { if (invocation != null && (METHOD_KEY.equals(conditionKey) || METHODS_KEY.equals(conditionKey))) {
sampleValue = RpcUtils.getMethodName(invocation); sampleValue = RpcUtils.getMethodName(invocation);
} else { } else {
@ -67,7 +69,8 @@ public abstract class AbstractConditionMatcher implements ConditionMatcher {
public boolean isMatch(Map<String, String> sample, URL param, Invocation invocation, boolean isWhenCondition) { public boolean isMatch(Map<String, String> sample, URL param, Invocation invocation, boolean isWhenCondition) {
String value = getValue(sample, param, invocation); String value = getValue(sample, param, invocation);
if (value == null) { if (value == null) {
// if key does not present in whichever of url, invocation or attachment based on the matcher type, then return false. // if key does not present in whichever of url, invocation or attachment based on the matcher type, then
// return false.
return false; return false;
} }
@ -90,7 +93,7 @@ public abstract class AbstractConditionMatcher implements ConditionMatcher {
} }
if (!matches.isEmpty() && !mismatches.isEmpty()) { if (!matches.isEmpty() && !mismatches.isEmpty()) {
//when both mismatches and matches contain the same value, then using mismatches first // when both mismatches and matches contain the same value, then using mismatches first
for (String mismatch : mismatches) { for (String mismatch : mismatches) {
if (doPatternMatch(mismatch, value, param, invocation, isWhenCondition)) { if (doPatternMatch(mismatch, value, param, invocation, isWhenCondition)) {
return false; return false;
@ -117,16 +120,23 @@ public abstract class AbstractConditionMatcher implements ConditionMatcher {
} }
// range, equal or other methods // range, equal or other methods
protected boolean doPatternMatch(String pattern, String value, URL url, Invocation invocation, boolean isWhenCondition) { protected boolean doPatternMatch(
String pattern, String value, URL url, Invocation invocation, boolean isWhenCondition) {
for (ValuePattern valueMatcher : valueMatchers) { for (ValuePattern valueMatcher : valueMatchers) {
if (valueMatcher.shouldMatch(pattern)) { if (valueMatcher.shouldMatch(pattern)) {
return valueMatcher.match(pattern, value, url, invocation, isWhenCondition); return valueMatcher.match(pattern, value, url, invocation, isWhenCondition);
} }
} }
// this should never happen. // this should never happen.
logger.error(CLUSTER_FAILED_EXEC_CONDITION_ROUTER, "Executing condition rule value match expression error.", "pattern is " + pattern + ", value is " + value + ", condition type " + (isWhenCondition ? "when" : "then"), "There should at least has one ValueMatcher instance that applies to all patterns, will force to use wildcard matcher now."); logger.error(
CLUSTER_FAILED_EXEC_CONDITION_ROUTER,
"Executing condition rule value match expression error.",
"pattern is " + pattern + ", value is " + value + ", condition type "
+ (isWhenCondition ? "when" : "then"),
"There should at least has one ValueMatcher instance that applies to all patterns, will force to use wildcard matcher now.");
ValuePattern paramValueMatcher = model.getExtensionLoader(ValuePattern.class).getExtension("wildcard"); ValuePattern paramValueMatcher =
model.getExtensionLoader(ValuePattern.class).getExtension("wildcard");
return paramValueMatcher.match(pattern, value, url, invocation, isWhenCondition); return paramValueMatcher.match(pattern, value, url, invocation, isWhenCondition);
} }
@ -135,5 +145,4 @@ public abstract class AbstractConditionMatcher implements ConditionMatcher {
* This makes condition rule possible to check values in any place of a request. * This makes condition rule possible to check values in any place of a request.
*/ */
protected abstract String getValue(Map<String, String> sample, URL url, Invocation invocation); protected abstract String getValue(Map<String, String> sample, URL url, Invocation invocation);
} }

View File

@ -38,7 +38,8 @@ import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_FAIL
*/ */
@Activate @Activate
public class ArgumentConditionMatcher extends AbstractConditionMatcher { public class ArgumentConditionMatcher extends AbstractConditionMatcher {
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(ArgumentConditionMatcher.class); private static final ErrorTypeAwareLogger logger =
LoggerFactory.getErrorTypeAwareLogger(ArgumentConditionMatcher.class);
private static final Pattern ARGUMENTS_PATTERN = Pattern.compile("arguments\\[([0-9]+)\\]"); private static final Pattern ARGUMENTS_PATTERN = Pattern.compile("arguments\\[([0-9]+)\\]");
public ArgumentConditionMatcher(String key, ModuleModel model) { public ArgumentConditionMatcher(String key, ModuleModel model) {
@ -56,16 +57,21 @@ public class ArgumentConditionMatcher extends AbstractConditionMatcher {
return DOES_NOT_FOUND_VALUE; return DOES_NOT_FOUND_VALUE;
} }
//extract the argument index // extract the argument index
int index = Integer.parseInt(matcher.group(1)); int index = Integer.parseInt(matcher.group(1));
if (index < 0 || index > invocation.getArguments().length) { if (index < 0 || index > invocation.getArguments().length) {
return DOES_NOT_FOUND_VALUE; return DOES_NOT_FOUND_VALUE;
} }
//extract the argument value // extract the argument value
return String.valueOf(invocation.getArguments()[index]); return String.valueOf(invocation.getArguments()[index]);
} catch (Exception e) { } catch (Exception e) {
logger.warn(CLUSTER_FAILED_EXEC_CONDITION_ROUTER, "Parse argument match condition failed", "", "Invalid , will ignore., ", e); logger.warn(
CLUSTER_FAILED_EXEC_CONDITION_ROUTER,
"Parse argument match condition failed",
"",
"Invalid , will ignore., ",
e);
} }
return DOES_NOT_FOUND_VALUE; return DOES_NOT_FOUND_VALUE;
} }

View File

@ -38,7 +38,8 @@ import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_FAIL
*/ */
@Activate @Activate
public class AttachmentConditionMatcher extends AbstractConditionMatcher { public class AttachmentConditionMatcher extends AbstractConditionMatcher {
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(AttachmentConditionMatcher.class); private static final ErrorTypeAwareLogger logger =
LoggerFactory.getErrorTypeAwareLogger(AttachmentConditionMatcher.class);
private static final Pattern ATTACHMENTS_PATTERN = Pattern.compile("attachments\\[(.+)\\]"); private static final Pattern ATTACHMENTS_PATTERN = Pattern.compile("attachments\\[(.+)\\]");
public AttachmentConditionMatcher(String key, ModuleModel model) { public AttachmentConditionMatcher(String key, ModuleModel model) {
@ -56,20 +57,21 @@ public class AttachmentConditionMatcher extends AbstractConditionMatcher {
return DOES_NOT_FOUND_VALUE; return DOES_NOT_FOUND_VALUE;
} }
//extract the argument index // extract the argument index
String attachmentKey = matcher.group(1); String attachmentKey = matcher.group(1);
if (StringUtils.isEmpty(attachmentKey)) { if (StringUtils.isEmpty(attachmentKey)) {
return DOES_NOT_FOUND_VALUE; return DOES_NOT_FOUND_VALUE;
} }
//extract the argument value // extract the argument value
return invocation.getAttachment(attachmentKey); return invocation.getAttachment(attachmentKey);
} catch (Exception e) { } catch (Exception e) {
logger.warn(CLUSTER_FAILED_EXEC_CONDITION_ROUTER, logger.warn(
"condition state router attachment match failed", CLUSTER_FAILED_EXEC_CONDITION_ROUTER,
"", "condition state router attachment match failed",
"Invalid match condition: " + key, "",
e); "Invalid match condition: " + key,
e);
} }
return DOES_NOT_FOUND_VALUE; return DOES_NOT_FOUND_VALUE;
} }

View File

@ -37,5 +37,4 @@ public class UrlParamConditionMatcher extends AbstractConditionMatcher {
protected String getValue(Map<String, String> sample, URL url, Invocation invocation) { protected String getValue(Map<String, String> sample, URL url, Invocation invocation) {
return getSampleValueFromUrl(key, sample, url, invocation); return getSampleValueFromUrl(key, sample, url, invocation);
} }
} }

View File

@ -46,7 +46,11 @@ public class RangeValuePattern implements ValuePattern {
String[] arr = pattern.split("~"); String[] arr = pattern.split("~");
if (arr.length < 2) { if (arr.length < 2) {
logger.error(CLUSTER_FAILED_EXEC_CONDITION_ROUTER, "", "", "Invalid condition rule " + pattern + " or value " + value + ", will ignore."); logger.error(
CLUSTER_FAILED_EXEC_CONDITION_ROUTER,
"",
"",
"Invalid condition rule " + pattern + " or value " + value + ", will ignore.");
return defaultValue; return defaultValue;
} }
@ -75,7 +79,12 @@ public class RangeValuePattern implements ValuePattern {
} }
} }
} catch (Exception e) { } catch (Exception e) {
logger.error(CLUSTER_FAILED_EXEC_CONDITION_ROUTER, "Parse integer error", "", "Invalid condition rule " + pattern + " or value " + value + ", will ignore.", e); logger.error(
CLUSTER_FAILED_EXEC_CONDITION_ROUTER,
"Parse integer error",
"",
"Invalid condition rule " + pattern + " or value " + value + ", will ignore.",
e);
return defaultValue; return defaultValue;
} }

View File

@ -46,7 +46,9 @@ public class FileStateRouterFactory implements StateRouterFactory {
try { try {
// Transform File URL into Script Route URL, and Load // Transform File URL into Script Route URL, and Load
// file:///d:/path/to/route.js?router=script ==> script:///d:/path/to/route.js?type=js&rule=<file-content> // file:///d:/path/to/route.js?router=script ==> script:///d:/path/to/route.js?type=js&rule=<file-content>
String protocol = url.getParameter(ROUTER_KEY, ScriptStateRouterFactory.NAME); // Replace original protocol (maybe 'file') with 'script' String protocol = url.getParameter(
ROUTER_KEY,
ScriptStateRouterFactory.NAME); // Replace original protocol (maybe 'file') with 'script'
String type = null; // Use file suffix to config script type, e.g., js, groovy ... String type = null; // Use file suffix to config script type, e.g., js, groovy ...
String path = url.getPath(); String path = url.getPath();
if (path != null) { if (path != null) {
@ -71,5 +73,4 @@ public class FileStateRouterFactory implements StateRouterFactory {
throw new IllegalStateException(e.getMessage(), e); throw new IllegalStateException(e.getMessage(), e);
} }
} }
} }

View File

@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.route; package org.apache.dubbo.rpc.cluster.router.mesh.route;
import org.apache.dubbo.common.config.configcenter.ConfigChangeType; import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
@ -26,24 +25,23 @@ import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.rpc.cluster.router.mesh.util.MeshRuleDispatcher; import org.apache.dubbo.rpc.cluster.router.mesh.util.MeshRuleDispatcher;
import org.apache.dubbo.rpc.cluster.router.mesh.util.MeshRuleListener; import org.apache.dubbo.rpc.cluster.router.mesh.util.MeshRuleListener;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import org.yaml.snakeyaml.representer.Representer;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import org.yaml.snakeyaml.representer.Representer;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_FAILED_RECEIVE_RULE; import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_FAILED_RECEIVE_RULE;
import static org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleConstants.METADATA_KEY; import static org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleConstants.METADATA_KEY;
import static org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleConstants.NAME_KEY; import static org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleConstants.NAME_KEY;
import static org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleConstants.STANDARD_ROUTER_KEY; import static org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleConstants.STANDARD_ROUTER_KEY;
public class MeshAppRuleListener implements ConfigurationListener { public class MeshAppRuleListener implements ConfigurationListener {
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(MeshAppRuleListener.class); private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(MeshAppRuleListener.class);
@ -62,8 +60,7 @@ public class MeshAppRuleListener implements ConfigurationListener {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void receiveConfigInfo(String configInfo) { public void receiveConfigInfo(String configInfo) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug(MessageFormat.format("[MeshAppRule] Received rule for app [{0}]: {1}.", logger.debug(MessageFormat.format("[MeshAppRule] Received rule for app [{0}]: {1}.", appName, configInfo));
appName, configInfo));
} }
try { try {
Map<String, List<Map<String, Object>>> groupMap = new HashMap<>(); Map<String, List<Map<String, Object>>> groupMap = new HashMap<>();
@ -79,19 +76,34 @@ public class MeshAppRuleListener implements ConfigurationListener {
String ruleType = computeRuleType(resultMap); String ruleType = computeRuleType(resultMap);
if (ruleType != null) { if (ruleType != null) {
groupMap.computeIfAbsent(ruleType, (k)-> new LinkedList<>()).add(resultMap); groupMap.computeIfAbsent(ruleType, (k) -> new LinkedList<>())
.add(resultMap);
} else { } else {
logger.error(CLUSTER_FAILED_RECEIVE_RULE,"receive mesh app route rule is invalid","","Unable to get rule type from raw rule. " + logger.error(
"Probably the metadata.name is absent. App Name: " + appName + " RawRule: " + configInfo); CLUSTER_FAILED_RECEIVE_RULE,
"receive mesh app route rule is invalid",
"",
"Unable to get rule type from raw rule. "
+ "Probably the metadata.name is absent. App Name: " + appName + " RawRule: "
+ configInfo);
} }
} else { } else {
logger.error(CLUSTER_FAILED_RECEIVE_RULE,"receive mesh app route rule is invalid","","Rule format is unacceptable. App Name: " + appName + " RawRule: " + configInfo); logger.error(
CLUSTER_FAILED_RECEIVE_RULE,
"receive mesh app route rule is invalid",
"",
"Rule format is unacceptable. App Name: " + appName + " RawRule: " + configInfo);
} }
} }
ruleMapHolder = groupMap; ruleMapHolder = groupMap;
} catch (Exception e) { } catch (Exception e) {
logger.error(CLUSTER_FAILED_RECEIVE_RULE,"failed to receive mesh app route rule","","[MeshAppRule] parse failed: " + configInfo,e); logger.error(
CLUSTER_FAILED_RECEIVE_RULE,
"failed to receive mesh app route rule",
"",
"[MeshAppRule] parse failed: " + configInfo,
e);
} }
if (ruleMapHolder != null) { if (ruleMapHolder != null) {
meshRuleDispatcher.post(ruleMapHolder); meshRuleDispatcher.post(ruleMapHolder);
@ -123,7 +135,6 @@ public class MeshAppRuleListener implements ConfigurationListener {
meshRuleDispatcher.register(subscriber); meshRuleDispatcher.register(subscriber);
} }
public <T> void unregister(MeshRuleListener subscriber) { public <T> void unregister(MeshRuleListener subscriber) {
meshRuleDispatcher.unregister(subscriber); meshRuleDispatcher.unregister(subscriber);
} }

View File

@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.route; package org.apache.dubbo.rpc.cluster.router.mesh.route;
/** /**

View File

@ -41,7 +41,11 @@ public class MeshRuleCache<T> {
private final Map<String, Map<String, BitList<Invoker<T>>>> totalSubsetMap; private final Map<String, Map<String, BitList<Invoker<T>>>> totalSubsetMap;
private final BitList<Invoker<T>> unmatchedInvokers; private final BitList<Invoker<T>> unmatchedInvokers;
private MeshRuleCache(List<String> appList, Map<String, VsDestinationGroup> appToVDGroup, Map<String, Map<String, BitList<Invoker<T>>>> totalSubsetMap, BitList<Invoker<T>> unmatchedInvokers) { private MeshRuleCache(
List<String> appList,
Map<String, VsDestinationGroup> appToVDGroup,
Map<String, Map<String, BitList<Invoker<T>>>> totalSubsetMap,
BitList<Invoker<T>> unmatchedInvokers) {
this.appList = appList; this.appList = appList;
this.appToVDGroup = appToVDGroup; this.appToVDGroup = appToVDGroup;
this.totalSubsetMap = totalSubsetMap; this.totalSubsetMap = totalSubsetMap;
@ -83,7 +87,10 @@ public class MeshRuleCache<T> {
return !totalSubsetMap.isEmpty(); return !totalSubsetMap.isEmpty();
} }
public static <T> MeshRuleCache<T> build(String protocolServiceKey, BitList<Invoker<T>> invokers, Map<String, VsDestinationGroup> vsDestinationGroupMap) { public static <T> MeshRuleCache<T> build(
String protocolServiceKey,
BitList<Invoker<T>> invokers,
Map<String, VsDestinationGroup> vsDestinationGroupMap) {
if (CollectionUtils.isNotEmptyMap(vsDestinationGroupMap)) { if (CollectionUtils.isNotEmptyMap(vsDestinationGroupMap)) {
BitList<Invoker<T>> unmatchedInvokers = new BitList<>(invokers.getOriginList(), true); BitList<Invoker<T>> unmatchedInvokers = new BitList<>(invokers.getOriginList(), true);
Map<String, Map<String, BitList<Invoker<T>>>> totalSubsetMap = new HashMap<>(); Map<String, Map<String, BitList<Invoker<T>>>> totalSubsetMap = new HashMap<>();
@ -99,7 +106,8 @@ public class MeshRuleCache<T> {
unmatchedInvokers.add(invoker); unmatchedInvokers.add(invoker);
continue; continue;
} }
Map<String, BitList<Invoker<T>>> subsetMap = totalSubsetMap.computeIfAbsent(remoteApplication, (k) -> new HashMap<>()); Map<String, BitList<Invoker<T>>> subsetMap =
totalSubsetMap.computeIfAbsent(remoteApplication, (k) -> new HashMap<>());
boolean matched = false; boolean matched = false;
for (DestinationRule destinationRule : vsDestinationGroup.getDestinationRuleList()) { for (DestinationRule destinationRule : vsDestinationGroup.getDestinationRuleList()) {
@ -107,7 +115,8 @@ public class MeshRuleCache<T> {
List<Subset> subsetList = destinationRuleSpec.getSubsets(); List<Subset> subsetList = destinationRuleSpec.getSubsets();
for (Subset subset : subsetList) { for (Subset subset : subsetList) {
String subsetName = subset.getName(); String subsetName = subset.getName();
List<Invoker<T>> subsetInvokers = subsetMap.computeIfAbsent(subsetName, (k) -> new BitList<>(invokers.getOriginList(), true)); List<Invoker<T>> subsetInvokers = subsetMap.computeIfAbsent(
subsetName, (k) -> new BitList<>(invokers.getOriginList(), true));
Map<String, String> labels = subset.getLabels(); Map<String, String> labels = subset.getLabels();
if (isLabelMatch(invoker.getUrl(), protocolServiceKey, labels)) { if (isLabelMatch(invoker.getUrl(), protocolServiceKey, labels)) {
@ -121,17 +130,20 @@ public class MeshRuleCache<T> {
} }
} }
return new MeshRuleCache<>(new LinkedList<>(vsDestinationGroupMap.keySet()), return new MeshRuleCache<>(
Collections.unmodifiableMap(vsDestinationGroupMap), new LinkedList<>(vsDestinationGroupMap.keySet()),
Collections.unmodifiableMap(totalSubsetMap), Collections.unmodifiableMap(vsDestinationGroupMap),
unmatchedInvokers); Collections.unmodifiableMap(totalSubsetMap),
unmatchedInvokers);
} else { } else {
return new MeshRuleCache<T>(Collections.emptyList(), Collections.emptyMap(), Collections.emptyMap(), invokers); return new MeshRuleCache<T>(
Collections.emptyList(), Collections.emptyMap(), Collections.emptyMap(), invokers);
} }
} }
public static <T> MeshRuleCache<T> emptyCache() { public static <T> MeshRuleCache<T> emptyCache() {
return new MeshRuleCache<>(Collections.emptyList(), Collections.emptyMap(), Collections.emptyMap(), BitList.emptyList()); return new MeshRuleCache<>(
Collections.emptyList(), Collections.emptyMap(), Collections.emptyMap(), BitList.emptyList());
} }
protected static boolean isLabelMatch(URL url, String protocolServiceKey, Map<String, String> inputMap) { protected static boolean isLabelMatch(URL url, String protocolServiceKey, Map<String, String> inputMap) {
@ -161,7 +173,10 @@ public class MeshRuleCache<T> {
return false; return false;
} }
MeshRuleCache<?> ruleCache = (MeshRuleCache<?>) o; MeshRuleCache<?> ruleCache = (MeshRuleCache<?>) o;
return Objects.equals(appList, ruleCache.appList) && Objects.equals(appToVDGroup, ruleCache.appToVDGroup) && Objects.equals(totalSubsetMap, ruleCache.totalSubsetMap) && Objects.equals(unmatchedInvokers, ruleCache.unmatchedInvokers); return Objects.equals(appList, ruleCache.appList)
&& Objects.equals(appToVDGroup, ruleCache.appToVDGroup)
&& Objects.equals(totalSubsetMap, ruleCache.totalSubsetMap)
&& Objects.equals(unmatchedInvokers, ruleCache.unmatchedInvokers);
} }
@Override @Override

View File

@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.route; package org.apache.dubbo.rpc.cluster.router.mesh.route;
import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
@ -44,11 +43,12 @@ public class MeshRuleManager {
public MeshRuleManager(ModuleModel moduleModel) { public MeshRuleManager(ModuleModel moduleModel) {
this.ruleRepository = moduleModel.getDefaultExtension(GovernanceRuleRepository.class); this.ruleRepository = moduleModel.getDefaultExtension(GovernanceRuleRepository.class);
Set<MeshEnvListenerFactory> envListenerFactories = moduleModel.getExtensionLoader(MeshEnvListenerFactory.class).getSupportedExtensionInstances(); Set<MeshEnvListenerFactory> envListenerFactories =
moduleModel.getExtensionLoader(MeshEnvListenerFactory.class).getSupportedExtensionInstances();
this.envListeners = envListenerFactories.stream() this.envListeners = envListenerFactories.stream()
.map(MeshEnvListenerFactory::getListener) .map(MeshEnvListenerFactory::getListener)
.filter(Objects::nonNull) .filter(Objects::nonNull)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }
private synchronized MeshAppRuleListener subscribeAppRule(String app) { private synchronized MeshAppRuleListener subscribeAppRule(String app) {
@ -64,7 +64,12 @@ public class MeshRuleManager {
meshAppRuleListener.receiveConfigInfo(rawConfig); meshAppRuleListener.receiveConfigInfo(rawConfig);
} }
} catch (Throwable throwable) { } catch (Throwable throwable) {
logger.error(CLUSTER_FAILED_RECEIVE_RULE,"failed to get mesh app route rule","","get MeshRuleManager app rule failed.",throwable); logger.error(
CLUSTER_FAILED_RECEIVE_RULE,
"failed to get mesh app route rule",
"",
"get MeshRuleManager app rule failed.",
throwable);
} }
ruleRepository.addListener(appRuleDataId, DynamicConfiguration.DEFAULT_GROUP, meshAppRuleListener); ruleRepository.addListener(appRuleDataId, DynamicConfiguration.DEFAULT_GROUP, meshAppRuleListener);
@ -93,7 +98,6 @@ public class MeshRuleManager {
envListener.onUnSubscribe(app); envListener.onUnSubscribe(app);
} }
} }
} }
public synchronized <T> void register(String app, MeshRuleListener subscriber) { public synchronized <T> void register(String app, MeshRuleListener subscriber) {

View File

@ -74,13 +74,20 @@ public abstract class MeshRuleRouter<T> extends AbstractStateRouter<T> implement
super(url); super(url);
sourcesLabels = Collections.unmodifiableMap(new HashMap<>(url.getParameters())); sourcesLabels = Collections.unmodifiableMap(new HashMap<>(url.getParameters()));
this.meshRuleManager = url.getOrDefaultModuleModel().getBeanFactory().getBean(MeshRuleManager.class); this.meshRuleManager = url.getOrDefaultModuleModel().getBeanFactory().getBean(MeshRuleManager.class);
this.tracingContextProviders = url.getOrDefaultModuleModel().getExtensionLoader(TracingContextProvider.class).getSupportedExtensionInstances(); this.tracingContextProviders = url.getOrDefaultModuleModel()
.getExtensionLoader(TracingContextProvider.class)
.getSupportedExtensionInstances();
} }
@Override @Override
protected BitList<Invoker<T>> doRoute(BitList<Invoker<T>> invokers, URL url, Invocation invocation, protected BitList<Invoker<T>> doRoute(
boolean needToPrintMessage, Holder<RouterSnapshotNode<T>> nodeHolder, BitList<Invoker<T>> invokers,
Holder<String> messageHolder) throws RpcException { URL url,
Invocation invocation,
boolean needToPrintMessage,
Holder<RouterSnapshotNode<T>> nodeHolder,
Holder<String> messageHolder)
throws RpcException {
MeshRuleCache<T> ruleCache = this.meshRuleCache; MeshRuleCache<T> ruleCache = this.meshRuleCache;
if (!ruleCache.containsRule()) { if (!ruleCache.containsRule()) {
if (needToPrintMessage) { if (needToPrintMessage) {
@ -96,7 +103,8 @@ public abstract class MeshRuleRouter<T> extends AbstractStateRouter<T> implement
// loop each application // loop each application
for (String appName : ruleCache.getAppList()) { for (String appName : ruleCache.getAppList()) {
// find destination by invocation // find destination by invocation
List<DubboRouteDestination> routeDestination = getDubboRouteDestination(ruleCache.getVsDestinationGroup(appName), invocation); List<DubboRouteDestination> routeDestination =
getDubboRouteDestination(ruleCache.getVsDestinationGroup(appName), invocation);
if (routeDestination != null) { if (routeDestination != null) {
// aggregate target invokers // aggregate target invokers
String subset = randomSelectDestination(ruleCache, appName, routeDestination, invokers); String subset = randomSelectDestination(ruleCache, appName, routeDestination, invokers);
@ -104,7 +112,12 @@ public abstract class MeshRuleRouter<T> extends AbstractStateRouter<T> implement
BitList<Invoker<T>> destination = meshRuleCache.getSubsetInvokers(appName, subset); BitList<Invoker<T>> destination = meshRuleCache.getSubsetInvokers(appName, subset);
result = result.or(destination); result = result.or(destination);
if (stringBuilder != null) { if (stringBuilder != null) {
stringBuilder.append("Match App: ").append(appName).append(" Subset: ").append(subset).append(' '); stringBuilder
.append("Match App: ")
.append(appName)
.append(" Subset: ")
.append(subset)
.append(' ');
} }
} }
} }
@ -129,7 +142,8 @@ public abstract class MeshRuleRouter<T> extends AbstractStateRouter<T> implement
/** /**
* Select RouteDestination by Invocation * Select RouteDestination by Invocation
*/ */
protected List<DubboRouteDestination> getDubboRouteDestination(VsDestinationGroup vsDestinationGroup, Invocation invocation) { protected List<DubboRouteDestination> getDubboRouteDestination(
VsDestinationGroup vsDestinationGroup, Invocation invocation) {
if (vsDestinationGroup != null) { if (vsDestinationGroup != null) {
List<VirtualServiceRule> virtualServiceRuleList = vsDestinationGroup.getVirtualServiceRuleList(); List<VirtualServiceRule> virtualServiceRuleList = vsDestinationGroup.getVirtualServiceRuleList();
if (CollectionUtils.isNotEmpty(virtualServiceRuleList)) { if (CollectionUtils.isNotEmpty(virtualServiceRuleList)) {
@ -182,8 +196,8 @@ public abstract class MeshRuleRouter<T> extends AbstractStateRouter<T> implement
return dubboRouteDetail.getRoute(); return dubboRouteDetail.getRoute();
} }
if (matchRequestList.stream().allMatch( if (matchRequestList.stream()
request -> request.isMatch(invocation, sourcesLabels, tracingContextProviders))) { .allMatch(request -> request.isMatch(invocation, sourcesLabels, tracingContextProviders))) {
return dubboRouteDetail.getRoute(); return dubboRouteDetail.getRoute();
} }
} }
@ -195,7 +209,12 @@ public abstract class MeshRuleRouter<T> extends AbstractStateRouter<T> implement
/** /**
* Find out target invokers from RouteDestination * Find out target invokers from RouteDestination
*/ */
protected String randomSelectDestination(MeshRuleCache<T> meshRuleCache, String appName, List<DubboRouteDestination> routeDestination, BitList<Invoker<T>> availableInvokers) throws RpcException { protected String randomSelectDestination(
MeshRuleCache<T> meshRuleCache,
String appName,
List<DubboRouteDestination> routeDestination,
BitList<Invoker<T>> availableInvokers)
throws RpcException {
// randomly select one DubboRouteDestination from list by weight // randomly select one DubboRouteDestination from list by weight
int totalWeight = 0; int totalWeight = 0;
for (DubboRouteDestination dubboRouteDestination : routeDestination) { for (DubboRouteDestination dubboRouteDestination : routeDestination) {
@ -206,7 +225,8 @@ public abstract class MeshRuleRouter<T> extends AbstractStateRouter<T> implement
target -= Math.max(destination.getWeight(), 1); target -= Math.max(destination.getWeight(), 1);
if (target <= 0) { if (target <= 0) {
// match weight // match weight
String result = computeDestination(meshRuleCache, appName, destination.getDestination(), availableInvokers); String result =
computeDestination(meshRuleCache, appName, destination.getDestination(), availableInvokers);
if (result != null) { if (result != null) {
return result; return result;
} }
@ -226,13 +246,19 @@ public abstract class MeshRuleRouter<T> extends AbstractStateRouter<T> implement
/** /**
* Compute Destination Subset * Compute Destination Subset
*/ */
protected String computeDestination(MeshRuleCache<T> meshRuleCache, String appName, DubboDestination dubboDestination, BitList<Invoker<T>> availableInvokers) throws RpcException { protected String computeDestination(
MeshRuleCache<T> meshRuleCache,
String appName,
DubboDestination dubboDestination,
BitList<Invoker<T>> availableInvokers)
throws RpcException {
String subset = dubboDestination.getSubset(); String subset = dubboDestination.getSubset();
do { do {
BitList<Invoker<T>> result = meshRuleCache.getSubsetInvokers(appName, subset); BitList<Invoker<T>> result = meshRuleCache.getSubsetInvokers(appName, subset);
if (CollectionUtils.isNotEmpty(result) && !availableInvokers.clone().and(result).isEmpty()) { if (CollectionUtils.isNotEmpty(result)
&& !availableInvokers.clone().and(result).isEmpty()) {
return subset; return subset;
} }
@ -309,7 +335,12 @@ public abstract class MeshRuleRouter<T> extends AbstractStateRouter<T> implement
appToVDGroup.put(appName, vsDestinationGroup); appToVDGroup.put(appName, vsDestinationGroup);
} }
} catch (Throwable t) { } catch (Throwable t) {
logger.error(CLUSTER_FAILED_RECEIVE_RULE,"failed to parse mesh route rule","","Error occurred when parsing rule component.",t); logger.error(
CLUSTER_FAILED_RECEIVE_RULE,
"failed to parse mesh route rule",
"",
"Error occurred when parsing rule component.",
t);
} }
computeSubset(appToVDGroup); computeSubset(appToVDGroup);
@ -323,7 +354,8 @@ public abstract class MeshRuleRouter<T> extends AbstractStateRouter<T> implement
} }
protected void computeSubset(Map<String, VsDestinationGroup> vsDestinationGroupMap) { protected void computeSubset(Map<String, VsDestinationGroup> vsDestinationGroupMap) {
this.meshRuleCache = MeshRuleCache.build(getUrl().getProtocolServiceKey(), this.invokerList, vsDestinationGroupMap); this.meshRuleCache =
MeshRuleCache.build(getUrl().getProtocolServiceKey(), this.invokerList, vsDestinationGroupMap);
} }
@Override @Override

View File

@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.route; package org.apache.dubbo.rpc.cluster.router.mesh.route;
import org.apache.dubbo.common.URL; import org.apache.dubbo.common.URL;
@ -22,7 +21,6 @@ import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.cluster.router.state.StateRouter; import org.apache.dubbo.rpc.cluster.router.state.StateRouter;
import org.apache.dubbo.rpc.cluster.router.state.StateRouterFactory; import org.apache.dubbo.rpc.cluster.router.state.StateRouterFactory;
@Activate(order = -50) @Activate(order = -50)
public class StandardMeshRuleRouterFactory implements StateRouterFactory { public class StandardMeshRuleRouterFactory implements StateRouterFactory {
@Override @Override

View File

@ -14,12 +14,10 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.rule; package org.apache.dubbo.rpc.cluster.router.mesh.rule;
import java.util.Map; import java.util.Map;
public class BaseRule { public class BaseRule {
private String apiVersion; private String apiVersion;
private String kind; private String kind;
@ -51,10 +49,9 @@ public class BaseRule {
@Override @Override
public String toString() { public String toString() {
return "BaseRule{" + return "BaseRule{" + "apiVersion='"
"apiVersion='" + apiVersion + '\'' + + apiVersion + '\'' + ", kind='"
", kind='" + kind + '\'' + + kind + '\'' + ", metadata="
", metadata=" + metadata + + metadata + '}';
'}';
} }
} }

View File

@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.rule; package org.apache.dubbo.rpc.cluster.router.mesh.rule;
import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.DestinationRule; import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.DestinationRule;
@ -23,7 +22,6 @@ import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.VirtualServi
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
public class VsDestinationGroup { public class VsDestinationGroup {
private String appName; private String appName;
private List<VirtualServiceRule> virtualServiceRuleList = new LinkedList<>(); private List<VirtualServiceRule> virtualServiceRuleList = new LinkedList<>();

View File

@ -14,9 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination; package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination;
public class ConnectionPoolSettings {}
public class ConnectionPoolSettings {
}

View File

@ -14,12 +14,10 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination; package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination;
import org.apache.dubbo.rpc.cluster.router.mesh.rule.BaseRule; import org.apache.dubbo.rpc.cluster.router.mesh.rule.BaseRule;
public class DestinationRule extends BaseRule { public class DestinationRule extends BaseRule {
private DestinationRuleSpec spec; private DestinationRuleSpec spec;
@ -33,9 +31,6 @@ public class DestinationRule extends BaseRule {
@Override @Override
public String toString() { public String toString() {
return "DestinationRule{" + return "DestinationRule{" + "base=" + super.toString() + ", spec=" + spec + '}';
"base=" + super.toString() +
", spec=" + spec +
'}';
} }
} }

View File

@ -14,12 +14,10 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination; package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination;
import java.util.List; import java.util.List;
public class DestinationRuleSpec { public class DestinationRuleSpec {
private String host; private String host;
private List<Subset> subsets; private List<Subset> subsets;
@ -51,10 +49,9 @@ public class DestinationRuleSpec {
@Override @Override
public String toString() { public String toString() {
return "DestinationRuleSpec{" + return "DestinationRuleSpec{" + "host='"
"host='" + host + '\'' + + host + '\'' + ", subsets="
", subsets=" + subsets + + subsets + ", trafficPolicy="
", trafficPolicy=" + trafficPolicy + + trafficPolicy + '}';
'}';
} }
} }

View File

@ -14,12 +14,10 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination; package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination;
import java.util.Map; import java.util.Map;
public class Subset { public class Subset {
private String name; private String name;
private Map<String, String> labels; private Map<String, String> labels;
@ -42,9 +40,6 @@ public class Subset {
@Override @Override
public String toString() { public String toString() {
return "Subset{" + return "Subset{" + "name='" + name + '\'' + ", labels=" + labels + '}';
"name='" + name + '\'' +
", labels=" + labels +
'}';
} }
} }

View File

@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination; package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination;
public class TCPSettings { public class TCPSettings {
private int maxConnections; private int maxConnections;
private int connectTimeout; private int connectTimeout;

View File

@ -14,13 +14,10 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination; package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination;
public class TcpKeepalive { public class TcpKeepalive {
private int probes; private int probes;
private int time; private int time;
private int interval; private int interval;
} }

View File

@ -14,12 +14,10 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination; package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination;
import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.loadbalance.LoadBalancerSettings; import org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.loadbalance.LoadBalancerSettings;
public class TrafficPolicy { public class TrafficPolicy {
private LoadBalancerSettings loadBalancer; private LoadBalancerSettings loadBalancer;
@ -33,8 +31,6 @@ public class TrafficPolicy {
@Override @Override
public String toString() { public String toString() {
return "TrafficPolicy{" + return "TrafficPolicy{" + "loadBalancer=" + loadBalancer + '}';
"loadBalancer=" + loadBalancer +
'}';
} }
} }

View File

@ -14,9 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.loadbalance; package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.loadbalance;
public class ConsistentHashLB {}
public class ConsistentHashLB {
}

View File

@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.loadbalance; package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.loadbalance;
public class LoadBalancerSettings { public class LoadBalancerSettings {
private SimpleLB simple; private SimpleLB simple;
private ConsistentHashLB consistentHash; private ConsistentHashLB consistentHash;
@ -40,9 +38,6 @@ public class LoadBalancerSettings {
@Override @Override
public String toString() { public String toString() {
return "LoadBalancerSettings{" + return "LoadBalancerSettings{" + "simple=" + simple + ", consistentHash=" + consistentHash + '}';
"simple=" + simple +
", consistentHash=" + consistentHash +
'}';
} }
} }

View File

@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.loadbalance; package org.apache.dubbo.rpc.cluster.router.mesh.rule.destination.loadbalance;
public enum SimpleLB { public enum SimpleLB {
ROUND_ROBIN, ROUND_ROBIN,
LEAST_CONN, LEAST_CONN,

View File

@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice; package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice;
import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invocation;
@ -26,7 +25,6 @@ import org.apache.dubbo.rpc.cluster.router.mesh.util.TracingContextProvider;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
public class DubboMatchRequest { public class DubboMatchRequest {
private String name; private String name;
private DubboMethodMatch method; private DubboMethodMatch method;
@ -76,16 +74,16 @@ public class DubboMatchRequest {
@Override @Override
public String toString() { public String toString() {
return "DubboMatchRequest{" + return "DubboMatchRequest{" + "name='"
"name='" + name + '\'' + + name + '\'' + ", method="
", method=" + method + + method + ", sourceLabels="
", sourceLabels=" + sourceLabels + + sourceLabels + ", attachments="
", attachments=" + attachments + + attachments + ", headers="
", headers=" + headers + + headers + '}';
'}';
} }
public boolean isMatch(Invocation invocation, Map<String, String> sourceLabels, Set<TracingContextProvider> contextProviders) { public boolean isMatch(
Invocation invocation, Map<String, String> sourceLabels, Set<TracingContextProvider> contextProviders) {
// Match method // Match method
if (getMethod() != null) { if (getMethod() != null) {
if (!getMethod().isMatch(invocation)) { if (!getMethod().isMatch(invocation)) {

View File

@ -14,14 +14,12 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice; package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice;
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.StringMatch; import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.StringMatch;
import java.util.List; import java.util.List;
public class DubboRoute { public class DubboRoute {
private String name; private String name;
private List<StringMatch> services; private List<StringMatch> services;
@ -53,10 +51,6 @@ public class DubboRoute {
@Override @Override
public String toString() { public String toString() {
return "DubboRoute{" + return "DubboRoute{" + "name='" + name + '\'' + ", services=" + services + ", routedetail=" + routedetail + '}';
"name='" + name + '\'' +
", services=" + services +
", routedetail=" + routedetail +
'}';
} }
} }

View File

@ -14,14 +14,12 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice; package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice;
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.destination.DubboRouteDestination; import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.destination.DubboRouteDestination;
import java.util.List; import java.util.List;
public class DubboRouteDetail { public class DubboRouteDetail {
private String name; private String name;
private List<DubboMatchRequest> match; private List<DubboMatchRequest> match;
@ -53,10 +51,6 @@ public class DubboRouteDetail {
@Override @Override
public String toString() { public String toString() {
return "DubboRouteDetail{" + return "DubboRouteDetail{" + "name='" + name + '\'' + ", match=" + match + ", route=" + route + '}';
"name='" + name + '\'' +
", match=" + match +
", route=" + route +
'}';
} }
} }

View File

@ -14,12 +14,10 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice; package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice;
import org.apache.dubbo.rpc.cluster.router.mesh.rule.BaseRule; import org.apache.dubbo.rpc.cluster.router.mesh.rule.BaseRule;
public class VirtualServiceRule extends BaseRule { public class VirtualServiceRule extends BaseRule {
private VirtualServiceSpec spec; private VirtualServiceSpec spec;
@ -33,9 +31,6 @@ public class VirtualServiceRule extends BaseRule {
@Override @Override
public String toString() { public String toString() {
return "VirtualServiceRule{" + return "VirtualServiceRule{" + "base=" + super.toString() + ", spec=" + spec + '}';
"base=" + super.toString() +
", spec=" + spec +
'}';
} }
} }

View File

@ -14,12 +14,10 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice; package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice;
import java.util.List; import java.util.List;
public class VirtualServiceSpec { public class VirtualServiceSpec {
private List<String> hosts; private List<String> hosts;
private List<DubboRoute> dubbo; private List<DubboRoute> dubbo;
@ -42,9 +40,6 @@ public class VirtualServiceSpec {
@Override @Override
public String toString() { public String toString() {
return "VirtualServiceSpec{" + return "VirtualServiceSpec{" + "hosts=" + hosts + ", dubbo=" + dubbo + '}';
"hosts=" + hosts +
", dubbo=" + dubbo +
'}';
} }
} }

View File

@ -14,17 +14,14 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.destination; package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.destination;
public class DubboDestination { public class DubboDestination {
private String host; private String host;
private String subset; private String subset;
private int port; private int port;
private DubboRouteDestination fallback; private DubboRouteDestination fallback;
public String getHost() { public String getHost() {
return host; return host;
} }

View File

@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.destination; package org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.destination;
public class DubboRouteDestination { public class DubboRouteDestination {
private DubboDestination destination; private DubboDestination destination;
private int weight; private int weight;

View File

@ -62,7 +62,14 @@ public class AddressMatch {
try { try {
return input.equals(getCird()) || matchIpExpression(getCird(), input); return input.equals(getCird()) || matchIpExpression(getCird(), input);
} catch (UnknownHostException e) { } 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) { if (getWildcard() != null && input != null) {

View File

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

View File

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

View File

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

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