You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by al...@apache.org on 2021/06/10 12:13:58 UTC

[dubbo] branch 3.0 updated: [3.0] Code reformat (#8019)

This is an automated email from the ASF dual-hosted git repository.

albumenj pushed a commit to branch 3.0
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/3.0 by this push:
     new 0e66de1  [3.0] Code reformat (#8019)
0e66de1 is described below

commit 0e66de1c61886c637e5ca11c1b0433bb1c25d05d
Author: Albumen Kevin <jh...@gmail.com>
AuthorDate: Thu Jun 10 20:13:39 2021 +0800

    [3.0] Code reformat (#8019)
    
    * convert files, add checker
    
    * rename id
    
    * tab to space
    
    * change git attributes auto convert
    
    * fix end new line
    
    * fix end new line
    
    * fix end new line
    
    * ignore generated files
    
    * override tomcat-embed-core version
    
    * add ignore for codestyle/checkstyle.xml
    
    * add ignore for codestyle/checkstyle.xml
    
    * add rat ignore
    
    * add suppression
    
    * force update
    
    * disable zk dynamic configurator
---
 .gitattributes                                     |   24 +-
 .github/workflows/build-and-test-3.yml             |   33 +-
 LICENSE                                            |    2 +-
 NOTICE                                             |   28 +-
 codestyle/checkstyle-suppressions.xml              |    1 +
 codestyle/checkstyle.xml                           |    4 +
 codestyle/checkstyle_unix.xml                      |   10 +
 .../org/apache/dubbo/gen/dubbo/DubboGenerator.java |    2 +-
 dubbo-build-tools/pom.xml                          |    1 +
 .../org/apache/dubbo/registry/AddressListener.java |    2 +-
 .../java/org/apache/dubbo/rpc/cluster/Cluster.java |  118 +-
 .../org/apache/dubbo/rpc/cluster/Configurator.java |  238 +-
 .../dubbo/rpc/cluster/ConfiguratorFactory.java     |   78 +-
 .../org/apache/dubbo/rpc/cluster/Directory.java    |  144 +-
 .../org/apache/dubbo/rpc/cluster/LoadBalance.java  |  100 +-
 .../java/org/apache/dubbo/rpc/cluster/Router.java  |  206 +-
 .../apache/dubbo/rpc/cluster/RouterFactory.java    |   94 +-
 .../cluster/configurator/AbstractConfigurator.java |  340 +-
 .../configurator/absent/AbsentConfigurator.java    |   74 +-
 .../absent/AbsentConfiguratorFactory.java          |   68 +-
 .../override/OverrideConfigurator.java             |   74 +-
 .../override/OverrideConfiguratorFactory.java      |   68 +-
 .../rpc/cluster/directory/StaticDirectory.java     |  228 +-
 .../cluster/loadbalance/AbstractLoadBalance.java   |  198 +-
 .../loadbalance/ConsistentHashLoadBalance.java     |  262 +-
 .../loadbalance/LeastActiveLoadBalance.java        |  230 +-
 .../cluster/loadbalance/RoundRobinLoadBalance.java |  262 +-
 .../cluster/router/condition/ConditionRouter.java  |  720 ++--
 .../router/condition/ConditionRouterFactory.java   |   72 +-
 .../rpc/cluster/router/script/ScriptRouter.java    |  354 +-
 .../cluster/router/script/ScriptRouterFactory.java |   90 +-
 .../rpc/cluster/router/state/RouterCache.java      |    2 +-
 .../rpc/cluster/router/state/StateRouter.java      |  200 +-
 .../rpc/cluster/support/AvailableCluster.java      |   74 +-
 .../rpc/cluster/support/BroadcastCluster.java      |   68 +-
 .../cluster/support/BroadcastClusterInvoker.java   |  232 +-
 .../dubbo/rpc/cluster/support/ClusterUtils.java    |  102 +-
 .../dubbo/rpc/cluster/support/FailbackCluster.java |   72 +-
 .../cluster/support/FailbackClusterInvoker.java    |  336 +-
 .../dubbo/rpc/cluster/support/FailfastCluster.java |   72 +-
 .../cluster/support/FailfastClusterInvoker.java    |  124 +-
 .../dubbo/rpc/cluster/support/FailoverCluster.java |   72 +-
 .../cluster/support/FailoverClusterInvoker.java    |  256 +-
 .../dubbo/rpc/cluster/support/FailsafeCluster.java |   72 +-
 .../cluster/support/FailsafeClusterInvoker.java    |  112 +-
 .../dubbo/rpc/cluster/support/ForkingCluster.java  |   72 +-
 .../merger/DefaultProviderURLMergeProcessor.java   |    2 +-
 .../cluster/support/registry/ZoneAwareCluster.java |    2 +-
 .../support/registry/ZoneAwareClusterInvoker.java  |    2 +-
 .../support/wrapper/MockClusterInvoker.java        |  390 +--
 .../support/wrapper/MockClusterWrapper.java        |   84 +-
 .../internal/org.apache.dubbo.rpc.cluster.Cluster  |   18 +-
 ...rg.apache.dubbo.rpc.cluster.ConfiguratorFactory |    2 +-
 .../org.apache.dubbo.rpc.cluster.LoadBalance       |    8 +-
 .../internal/org.apache.dubbo.rpc.cluster.Merger   |   22 +-
 .../org.apache.dubbo.rpc.cluster.RouterFactory     |   14 +-
 .../absent/AbsentConfiguratorTest.java             |  136 +-
 .../override/OverrideConfiguratorTest.java         |  136 +-
 .../rpc/cluster/directory/MockDirInvocation.java   |    2 +-
 .../dubbo/rpc/cluster/filter/DemoService.java      |   54 +-
 .../dubbo/rpc/cluster/filter/DemoServiceLocal.java |   86 +-
 .../dubbo/rpc/cluster/filter/DemoServiceMock.java  |   62 +-
 .../dubbo/rpc/cluster/filter/DemoServiceStub.java  |   70 +-
 .../dubbo/rpc/cluster/filter/MockService.java      |   62 +-
 .../router/condition/ConditionRouterTest.java      |  696 ++--
 .../router/mesh/route/MeshAppRuleListenerTest.java |    2 +-
 .../router/mesh/route/MeshRuleManagerTest.java     |    2 +-
 .../mesh/route/MeshRuleRouterFactoryTest.java      |    2 +-
 .../router/mesh/route/MeshRuleRouterTest.java      |    2 +-
 .../router/mesh/rule/DestinationRuleTest.java      |    2 +-
 .../router/mesh/rule/VirtualServiceRuleTest.java   |    2 +-
 .../rule/virtualservice/DubboMatchRequestTest.java |    2 +-
 .../rule/virtualservice/match/BoolMatchTest.java   |    2 +-
 .../rule/virtualservice/match/DoubleMatchTest.java |    2 +-
 .../match/DubboAttachmentMatchTest.java            |    2 +-
 .../virtualservice/match/DubboMethodMatchTest.java |    2 +-
 .../virtualservice/match/ListDoubleMatchTest.java  |    2 +-
 .../virtualservice/match/ListStringMatchTest.java  |    2 +-
 .../rule/virtualservice/match/StringMatchTest.java |    2 +-
 .../util/VsDestinationGroupRuleDispatcherTest.java |    2 +-
 .../cluster/router/script/ScriptRouterTest.java    |   18 +-
 .../support/FailSafeClusterInvokerTest.java        |  244 +-
 .../support/FailbackClusterInvokerTest.java        |  354 +-
 .../support/FailfastClusterInvokerTest.java        |    2 +-
 .../support/FailoverClusterInvokerTest.java        |  580 ++--
 .../cluster/support/ForkingClusterInvokerTest.java |    2 +-
 .../cluster/support/wrapper/MyMockException.java   |   56 +-
 .../org.apache.dubbo.rpc.cluster.RouterFactory     |    2 +-
 dubbo-cluster/src/test/resources/log4j.xml         |   58 +-
 .../alibaba/dubbo/common/extension/Activate.java   |    2 +-
 .../java/org/apache/dubbo/common/Extension.java    |  136 +-
 .../main/java/org/apache/dubbo/common/Node.java    |   86 +-
 .../java/org/apache/dubbo/common/Parameters.java   |  526 +--
 .../java/org/apache/dubbo/common/Resetable.java    |    2 +-
 .../src/main/java/org/apache/dubbo/common/URL.java | 3668 ++++++++++----------
 .../java/org/apache/dubbo/common/URLBuilder.java   |  872 ++---
 .../dubbo/common/bytecode/ClassGenerator.java      |    2 +-
 .../org/apache/dubbo/common/bytecode/Mixin.java    |  454 +--
 .../common/bytecode/NoSuchMethodException.java     |   66 +-
 .../common/bytecode/NoSuchPropertyException.java   |   66 +-
 .../org/apache/dubbo/common/bytecode/Proxy.java    |  614 ++--
 .../org/apache/dubbo/common/bytecode/Wrapper.java  |  948 ++---
 .../org/apache/dubbo/common/compiler/Compiler.java |   72 +-
 .../common/compiler/support/AbstractCompiler.java  |  138 +-
 .../common/compiler/support/AdaptiveCompiler.java  |   96 +-
 .../dubbo/common/compiler/support/ClassUtils.java  |  890 ++---
 .../common/compiler/support/CtClassBuilder.java    |  348 +-
 .../common/compiler/support/JavassistCompiler.java |  170 +-
 .../dubbo/common/compiler/support/JdkCompiler.java |  604 ++--
 .../file/FileSystemDynamicConfiguration.java       |    2 +-
 .../apache/dubbo/common/extension/Activate.java    |  188 +-
 .../apache/dubbo/common/extension/Adaptive.java    |    2 +-
 .../dubbo/common/extension/ExtensionFactory.java   |   68 +-
 .../org/apache/dubbo/common/extension/SPI.java     |  128 +-
 .../factory/AdaptiveExtensionFactory.java          |  110 +-
 .../extension/factory/SpiExtensionFactory.java     |   78 +-
 .../extension/support/ActivateComparator.java      |  292 +-
 .../extension/support/WrapperComparator.java       |    2 +-
 .../java/org/apache/dubbo/common/io/Bytes.java     |    2 +-
 .../apache/dubbo/common/io/UnsafeStringWriter.java |    2 +-
 .../org/apache/dubbo/common/json/J2oVisitor.java   |  778 ++---
 .../java/org/apache/dubbo/common/json/JSON.java    | 1422 ++++----
 .../org/apache/dubbo/common/json/JSONArray.java    |  368 +-
 .../apache/dubbo/common/json/JSONConverter.java    |    2 +-
 .../org/apache/dubbo/common/json/JSONNode.java     |   68 +-
 .../org/apache/dubbo/common/json/JSONObject.java   |  418 +--
 .../org/apache/dubbo/common/json/JSONReader.java   |    2 +-
 .../org/apache/dubbo/common/json/JSONToken.java    |  144 +-
 .../org/apache/dubbo/common/json/JSONVisitor.java  |  214 +-
 .../org/apache/dubbo/common/json/JSONWriter.java   |  610 ++--
 .../apache/dubbo/common/json/ParseException.java   |   66 +-
 .../java/org/apache/dubbo/common/json/Yylex.java   |    2 +-
 .../dubbo/common/lang/ShutdownHookCallbacks.java   |    2 +-
 .../java/org/apache/dubbo/common/logger/Level.java |  118 +-
 .../org/apache/dubbo/common/logger/Logger.java     |    2 +-
 .../apache/dubbo/common/logger/LoggerAdapter.java  |    2 +-
 .../apache/dubbo/common/logger/jcl/JclLogger.java  |  278 +-
 .../dubbo/common/logger/jcl/JclLoggerAdapter.java  |  124 +-
 .../dubbo/common/logger/slf4j/Slf4jLogger.java     |  410 +--
 .../common/logger/slf4j/Slf4jLoggerAdapter.java    |  120 +-
 .../org/apache/dubbo/common/status/Status.java     |  158 +-
 .../apache/dubbo/common/status/StatusChecker.java  |   68 +-
 .../common/status/support/LoadStatusChecker.java   |  106 +-
 .../common/status/support/MemoryStatusChecker.java |   82 +-
 .../dubbo/common/status/support/StatusUtils.java   |  110 +-
 .../threadpool/support/AbortPolicyWithReport.java  |  340 +-
 .../support/cached/CachedThreadPool.java           |  122 +-
 .../threadpool/support/fixed/FixedThreadPool.java  |  112 +-
 .../dubbo/common/timer/HashedWheelTimer.java       |    2 +-
 .../org/apache/dubbo/common/timer/Timeout.java     |    2 +-
 .../java/org/apache/dubbo/common/timer/Timer.java  |    2 +-
 .../org/apache/dubbo/common/timer/TimerTask.java   |    2 +-
 .../dubbo/common/utils/AtomicPositiveInteger.java  |  308 +-
 .../apache/dubbo/common/utils/CollectionUtils.java |  752 ++--
 .../dubbo/common/utils/CompatibleTypeUtils.java    |  460 +--
 .../dubbo/common/utils/ConcurrentHashSet.java      |  260 +-
 .../org/apache/dubbo/common/utils/ConfigUtils.java |  790 ++---
 .../apache/dubbo/common/utils/DubboAppender.java   |  136 +-
 .../java/org/apache/dubbo/common/utils/Holder.java |    2 +-
 .../org/apache/dubbo/common/utils/IOUtils.java     |  540 +--
 .../org/apache/dubbo/common/utils/LFUCache.java    |    2 +-
 .../org/apache/dubbo/common/utils/LRUCache.java    |    2 +-
 .../java/org/apache/dubbo/common/utils/Log.java    |  232 +-
 .../org/apache/dubbo/common/utils/LogUtil.java     |  262 +-
 .../org/apache/dubbo/common/utils/MemberUtils.java |    2 +-
 .../dubbo/common/utils/NamedThreadFactory.java     |  126 +-
 .../org/apache/dubbo/common/utils/NetUtils.java    | 1306 +++----
 .../org/apache/dubbo/common/utils/PojoUtils.java   | 1370 ++++----
 .../java/org/apache/dubbo/common/utils/Stack.java  |    2 +-
 .../org/apache/dubbo/common/utils/StringUtils.java | 2454 ++++++-------
 .../org/apache/dubbo/common/utils/UrlUtils.java    | 1316 +++----
 .../dubbo/config/AbstractInterfaceConfig.java      |    2 +-
 .../org/apache/dubbo/config/ServiceConfigBase.java |    2 +-
 .../org/apache/dubbo/config/support/Parameter.java |    2 +-
 .../dubbo/rpc/model/ApplicationInitListener.java   |    2 +-
 .../org/apache/dubbo/rpc/service/EchoService.java  |    2 +-
 .../apache/dubbo/rpc/service/GenericException.java |    2 +-
 .../apache/dubbo/rpc/service/GenericService.java   |    2 +-
 .../org.apache.dubbo.common.compiler.Compiler      |    4 +-
 ....apache.dubbo.common.extension.ExtensionFactory |    2 +-
 .../org.apache.dubbo.common.logger.LoggerAdapter   |   10 +-
 .../org.apache.dubbo.common.status.StatusChecker   |    2 +-
 .../org/apache/dubbo/common/URLBuilderTest.java    |  288 +-
 .../dubbo/common/bytecode/ClassGeneratorTest.java  |    2 +-
 .../apache/dubbo/common/bytecode/MixinTest.java    |    2 +-
 .../apache/dubbo/common/bytecode/ProxyTest.java    |    2 +-
 .../apache/dubbo/common/bytecode/WrapperTest.java  |  492 +--
 .../concurrent/CompletableFutureTaskTest.java      |    2 +-
 .../config/EnvironmentConfigurationTest.java       |    2 +-
 .../common/config/InmemoryConfigurationTest.java   |    2 +-
 .../common/config/SystemConfigurationTest.java     |    2 +-
 ...tensionLoader_Adaptive_UseJdkCompiler_Test.java |    2 +-
 .../extension/ExtensionLoader_Compatible_Test.java |    2 +-
 .../apache/dubbo/common/extension/NoSpiExt.java    |    2 +-
 .../activate/impl/ActivateWrapperExt1Impl1.java    |    2 +-
 .../activate/impl/ActivateWrapperExt1Impl2.java    |    2 +-
 .../activate/impl/ActivateWrapperExt1Wrapper.java  |    2 +-
 .../adaptive/impl/HasAdaptiveExtImpl1.java         |    2 +-
 .../impl/HasAdaptiveExt_ManualAdaptive.java        |    2 +-
 .../common/extension/compatible/CompatibleExt.java |    2 +-
 .../compatible/impl/CompatibleExtImpl1.java        |    2 +-
 .../compatible/impl/CompatibleExtImpl2.java        |    2 +-
 .../extension/convert/String2DoubleConverter.java  |    2 +-
 .../dubbo/common/extension/ext1/SimpleExt.java     |    2 +-
 .../common/extension/ext1/impl/SimpleExtImpl1.java |    2 +-
 .../common/extension/ext1/impl/SimpleExtImpl2.java |    2 +-
 .../common/extension/ext1/impl/SimpleExtImpl3.java |    2 +-
 .../apache/dubbo/common/extension/ext2/Ext2.java   |    2 +-
 .../dubbo/common/extension/ext2/UrlHolder.java     |    2 +-
 .../common/extension/ext2/impl/Ext2Impl1.java      |    2 +-
 .../common/extension/ext2/impl/Ext2Impl2.java      |    2 +-
 .../common/extension/ext2/impl/Ext2Impl3.java      |    2 +-
 .../common/extension/ext3/UseProtocolKeyExt.java   |    2 +-
 .../ext3/impl/UseProtocolKeyExtImpl1.java          |    2 +-
 .../ext3/impl/UseProtocolKeyExtImpl2.java          |    2 +-
 .../ext3/impl/UseProtocolKeyExtImpl3.java          |    2 +-
 .../dubbo/common/extension/ext4/NoUrlParamExt.java |    2 +-
 .../common/extension/ext4/impl/Ext4Impl1.java      |    2 +-
 .../common/extension/ext4/impl/Ext4Impl2.java      |    2 +-
 .../common/extension/ext5/NoAdaptiveMethodExt.java |    2 +-
 .../common/extension/ext5/impl/Ext5Impl1.java      |    2 +-
 .../common/extension/ext5/impl/Ext5Impl2.java      |    2 +-
 .../dubbo/common/extension/ext6_inject/Ext6.java   |    2 +-
 .../extension/ext6_inject/impl/Ext6Impl1.java      |    2 +-
 .../extension/ext6_inject/impl/Ext6Impl2.java      |    2 +-
 .../common/extension/ext6_wrap/WrappedExt.java     |    2 +-
 .../common/extension/ext6_wrap/impl/Ext5Impl1.java |    2 +-
 .../common/extension/ext6_wrap/impl/Ext5Impl2.java |    2 +-
 .../extension/ext6_wrap/impl/Ext5Wrapper1.java     |    2 +-
 .../extension/ext6_wrap/impl/Ext5Wrapper2.java     |    2 +-
 .../dubbo/common/extension/ext7/InitErrorExt.java  |    2 +-
 .../dubbo/common/extension/ext7/impl/Ext7Impl.java |    2 +-
 .../extension/ext7/impl/Ext7InitErrorImpl.java     |    2 +-
 .../dubbo/common/extension/ext8_add/AddExt1.java   |    2 +-
 .../dubbo/common/extension/ext8_add/AddExt2.java   |    2 +-
 .../dubbo/common/extension/ext8_add/AddExt3.java   |    2 +-
 .../dubbo/common/extension/ext8_add/AddExt4.java   |    2 +-
 .../extension/ext8_add/impl/AddExt1Impl1.java      |    2 +-
 .../ext8_add/impl/AddExt1_ManualAdaptive.java      |    2 +-
 .../ext8_add/impl/AddExt1_ManualAdd1.java          |    2 +-
 .../ext8_add/impl/AddExt1_ManualAdd2.java          |    2 +-
 .../extension/ext8_add/impl/AddExt2Impl1.java      |    2 +-
 .../ext8_add/impl/AddExt2_ManualAdaptive.java      |    2 +-
 .../ext8_add/impl/AddExt3_ManualAdaptive.java      |    2 +-
 .../ext8_add/impl/AddExt4_ManualAdaptive.java      |    2 +-
 .../common/extension/support/Order0Filter0.java    |    2 +-
 .../common/extension/support/Order0Filter1.java    |    2 +-
 .../java/org/apache/dubbo/common/io/BytesTest.java |    2 +-
 .../apache/dubbo/common/io/StreamUtilsTest.java    |    2 +-
 .../common/io/UnsafeByteArrayInputStreamTest.java  |    2 +-
 .../common/io/UnsafeByteArrayOutputStreamTest.java |    2 +-
 .../dubbo/common/io/UnsafeStringReaderTest.java    |    2 +-
 .../apache/dubbo/common/json/JSONReaderTest.java   |    2 +-
 .../org/apache/dubbo/common/json/JSONTest.java     |    2 +-
 .../apache/dubbo/common/json/JSONWriterTest.java   |    2 +-
 .../org/apache/dubbo/common/json/MyException.java  |   82 +-
 .../dubbo/common/logger/LoggerAdapterTest.java     |    2 +-
 .../org/apache/dubbo/common/logger/LoggerTest.java |    2 +-
 .../dubbo/common/logger/slf4j/Slf4jLoggerTest.java |    2 +-
 .../common/logger/support/FailsafeLoggerTest.java  |    2 +-
 .../java/org/apache/dubbo/common/model/Person.java |    2 +-
 .../org/apache/dubbo/common/model/media/Image.java |    2 +-
 .../org/apache/dubbo/common/model/media/Media.java |    2 +-
 .../dubbo/common/model/person/BigPerson.java       |    2 +-
 .../dubbo/common/model/person/FullAddress.java     |    2 +-
 .../dubbo/common/model/person/PersonStatus.java    |    2 +-
 .../apache/dubbo/common/model/person/Phone.java    |    2 +-
 .../threadlocal/InternalThreadLocalTest.java       |    2 +-
 .../NamedInternalThreadFactoryTest.java            |    2 +-
 .../support/AbortPolicyWithReportTest.java         |    2 +-
 .../support/eager/EagerThreadPoolExecutorTest.java |    2 +-
 .../dubbo/common/timer/HashedWheelTimerTest.java   |    2 +-
 .../apache/dubbo/common/utils/ArrayUtilsTest.java  |    2 +-
 .../common/utils/AtomicPositiveIntegerTest.java    |    2 +-
 .../dubbo/common/utils/CollectionUtilsTest.java    |    2 +-
 .../common/utils/CompatibleTypeUtilsTest.java      |  444 +--
 .../java/org/apache/dubbo/common/utils/MyEnum.java |   52 +-
 .../apache/dubbo/common/utils/NetUtilsTest.java    |  650 ++--
 .../apache/dubbo/common/utils/ParametersTest.java  |    2 +-
 .../dubbo/common/utils/ReflectUtilsTest.java       |    2 +-
 .../apache/dubbo/common/utils/UrlUtilsTest.java    |  758 ++--
 .../java/org/apache/dubbo/rpc/model/Person.java    |    2 +-
 .../apache/dubbo/rpc/model/SerializablePerson.java |    2 +-
 .../org/apache/dubbo/rpc/model/media/Image.java    |    2 +-
 .../org/apache/dubbo/rpc/model/media/Media.java    |    2 +-
 .../apache/dubbo/rpc/model/person/BigPerson.java   |    2 +-
 .../apache/dubbo/rpc/model/person/FullAddress.java |    2 +-
 .../dubbo/rpc/model/person/PersonStatus.java       |    2 +-
 .../org/apache/dubbo/rpc/model/person/Phone.java   |    2 +-
 ...e.dubbo.common.config.OrderedPropertiesProvider |    2 +-
 dubbo-common/src/test/resources/dubbo.properties   |    2 +-
 dubbo-common/src/test/resources/log4j.xml          |   66 +-
 .../src/test/resources/parameters.properties       |    2 +-
 dubbo-common/src/test/resources/properties.load    |    4 +-
 .../spring/context/annotation/EnableDubbo.java     |    2 +-
 .../apache/dubbo/config/ArgumentConfigTest.java    |    5 +-
 .../apache/dubbo/config/ConsumerConfigTest.java    |    5 +-
 .../org/apache/dubbo/config/ModuleConfigTest.java  |    2 +-
 .../apache/dubbo/config/ProtocolConfigTest.java    |    5 +-
 .../apache/dubbo/config/ProviderConfigTest.java    |    5 +-
 .../apache/dubbo/config/ReferenceConfigTest.java   |    2 +-
 .../dubbo/serialization/SerializationTest.java     |    4 +-
 .../org/apache/dubbo/service/CustomArgument.java   |    2 +-
 .../java/org/apache/dubbo/service/DemoService.java |    2 +-
 .../test/java/org/apache/dubbo/service/Person.java |   90 +-
 .../test/java/org/apache/dubbo/service/Type.java   |   42 +-
 .../dubbo/config/bootstrap/DubboBootstrap.java     |    8 +-
 .../bootstrap/builders/ConfigCenterBuilder.java    |    2 +-
 .../config/bootstrap/builders/package-info.java    |    2 +-
 .../test/java/org/apache/dubbo/config/api/Box.java |    2 +-
 .../org/apache/dubbo/config/api/DemoService.java   |    2 +-
 .../bootstrap/builders/AbstractBuilderTest.java    |    2 +-
 .../builders/AbstractInterfaceBuilderTest.java     |    2 +-
 .../builders/AbstractMethodBuilderTest.java        |    2 +-
 .../builders/AbstractReferenceBuilderTest.java     |    2 +-
 .../builders/AbstractServiceBuilderTest.java       |    2 +-
 .../bootstrap/builders/ApplicationBuilderTest.java |    2 +-
 .../bootstrap/builders/ArgumentBuilderTest.java    |    2 +-
 .../builders/ConfigCenterBuilderTest.java          |    2 +-
 .../bootstrap/builders/ConsumerBuilderTest.java    |    2 +-
 .../builders/MetadataReportBuilderTest.java        |    2 +-
 .../bootstrap/builders/MethodBuilderTest.java      |    2 +-
 .../bootstrap/builders/ModuleBuilderTest.java      |    2 +-
 .../bootstrap/builders/MonitorBuilderTest.java     |    2 +-
 .../bootstrap/builders/ProtocolBuilderTest.java    |    2 +-
 .../bootstrap/builders/ProviderBuilderTest.java    |    2 +-
 .../bootstrap/builders/ReferenceBuilderTest.java   |    2 +-
 .../bootstrap/builders/RegistryBuilderTest.java    |    2 +-
 .../bootstrap/builders/ServiceBuilderTest.java     |    2 +-
 .../config/provider/impl/DemoServiceImpl.java      |    2 +-
 .../config/url/ExporterSideConfigUrlTest.java      |    2 +-
 .../dubbo/config/url/RpcConfigGetSetProxy.java     |    2 +-
 .../src/test/resources/dubbo.properties            |    2 +-
 .../dubbo/config/spring/util/EnvironmentUtils.java |  298 +-
 .../org/apache/dubbo/config/spring/ConfigTest.java |    2 +-
 .../dubbo/config/spring/ServiceBeanTest.java       |    2 +-
 .../dubbo/config/spring/SimpleRegistryService.java |    2 +-
 .../spring/action/DemoActionByAnnotation.java      |    2 +-
 .../config/spring/action/DemoActionBySetter.java   |    2 +-
 .../config/spring/action/DemoInterceptor.java      |    2 +-
 .../annotation/provider/AnnotationServiceImpl.java |    2 +-
 .../org/apache/dubbo/config/spring/api/Box.java    |    2 +-
 .../dubbo/config/spring/api/DemoService.java       |    2 +-
 .../dubbo/config/spring/api/DemoServiceSon.java    |    2 +-
 .../ReferenceAnnotationBeanPostProcessorTest.java  |    2 +-
 .../ServiceAnnotationTestConfiguration.java        |    2 +-
 .../annotation/ServiceBeanNameBuilderTest.java     |    2 +-
 .../context/annotation/EnableDubboConfigTest.java  |    2 +-
 .../dubbo/config/spring/impl/DemoServiceImpl.java  |    2 +-
 .../spring/impl/DemoServiceImpl_LongWaiting.java   |    2 +-
 .../config/spring/impl/DemoServiceSonImpl.java     |    2 +-
 .../dubbo/config/spring/impl/NotifyService.java    |    2 +-
 .../config/spring/impl/UnserializableBox.java      |    2 +-
 .../impl/UnserializableBoxDemoServiceImpl.java     |    2 +-
 .../spring/issues/issue6000/adubbo/HelloDubbo.java |    2 +-
 .../issues/issue6000/dubbo/MyReferenceConfig.java  |    2 +-
 .../propertyconfigurer/consumer/app.properties     |    2 +-
 .../propertyconfigurer/consumer/dubbo-consumer.xml |   84 +-
 .../propertyconfigurer/consumer2/app.properties    |    2 +-
 .../consumer2/dubbo-consumer.xml                   |   84 +-
 .../provider/HelloServiceImpl.java                 |   77 +-
 .../propertyconfigurer/provider/app.properties     |    2 +-
 .../reference/javaconfig/consumer.properties       |    2 +-
 .../localcalla/local-call-config.properties        |    2 +-
 .../localcallam/local-call-config.properties       |    2 +-
 .../localcallmix/local-call-config.properties      |    2 +-
 .../registry/nacos/demo/service/DemoService.java   |    2 +-
 .../spring/schema/DubboNamespaceHandlerTest.java   |    2 +-
 .../config/spring/util/EnvironmentUtilsTest.java   |  176 +-
 .../src/test/resources/META-INF/config.properties  |    2 +-
 .../resources/META-INF/dubbb-consumer.properties   |    2 +-
 .../resources/META-INF/dubbb-provider.properties   |    2 +-
 .../resources/META-INF/dubbo-consumer.properties   |    2 +-
 .../resources/META-INF/dubbo-provider.properties   |    2 +-
 .../resources/META-INF/init-reference.properties   |    2 +-
 .../META-INF/issues/issue6252/config.properties    |    2 +-
 .../zookeeper-dubbb-consumer.properties            |    2 +-
 .../zookeeper-dubbb-provider.properties            |    2 +-
 .../src/test/resources/dubbo-binder.properties     |    2 +-
 .../src/test/resources/dubbo.properties            |    2 +-
 .../resources/nacos-consumer-config.properties     |    2 +-
 .../resources/nacos-provider-config.properties     |    2 +-
 .../apollo/ApolloDynamicConfigurationTest.java     |    2 +-
 .../src/test/resources/META-INF/app.properties     |    2 +-
 .../src/test/resources/mockdata-dubbo.properties   |    2 +-
 .../ZookeeperDynamicConfigurationTest.java         |    2 +
 .../java/org/apache/dubbo/container/Container.java |   74 +-
 .../main/java/org/apache/dubbo/container/Main.java |  216 +-
 .../main/resources/META-INF/assembly/bin/start.bat |   86 +-
 .../dubbo/container/spring/SpringContainer.java    |  134 +-
 .../container/spring/SpringContainerTest.java      |   76 +-
 .../src/test/resources/META-INF/spring/test.xml    |   46 +-
 .../src/test/resources/log4j.xml                   |   56 +-
 .../src/main/resources/log4j.properties            |    2 +-
 .../dubbo/demo/provider/DemoServiceImpl.java       |   86 +-
 .../src/main/resources/log4j.properties            |    2 +-
 .../src/main/resources/log4j.properties            |    2 +-
 .../src/main/resources/log4j.properties            |    2 +-
 .../src/main/resources/log4j.properties            |    2 +-
 .../java/org/apache/dubbo/demo/DemoService.java    |   58 +-
 .../src/main/resources/log4j.properties            |    2 +-
 .../src/main/resources/log4j.properties            |    2 +-
 .../src/main/resources/spring/dubbo-consumer.xml   |   80 +-
 .../src/main/resources/log4j.properties            |    2 +-
 .../dubbo/demo/provider/DemoServiceImpl.java       |  106 +-
 .../src/main/resources/log4j.properties            |    2 +-
 .../cache/support/AbstractCacheFactoryTest.java    |    2 +-
 .../support/expiring/ExpiringCacheFactoryTest.java |    2 +-
 .../cache/support/jcache/JCacheFactoryTest.java    |    2 +-
 .../cache/support/lru/LruCacheFactoryTest.java     |    2 +-
 .../threadlocal/ThreadLocalCacheFactoryTest.java   |    2 +-
 .../support/jvalidation/JValidation.java           |    2 +-
 .../validation/filter/ValidationFilterTest.java    |    2 +-
 .../support/jvalidation/JValidationTest.java       |    2 +-
 .../support/jvalidation/JValidatorTest.java        |    2 +-
 .../org/apache/dubbo/metadata/DemoService.java     |    2 +-
 .../META-INF/dubbo/service-name-mapping.properties |    2 +-
 .../builder/PrimitiveTypeDefinitionBuilder.java    |    2 +-
 .../annotation/processing/util/TypeUtils.java      |    2 +-
 .../AnnotationProcessingTestProcessor.java         |    2 +-
 .../java/org/apache/dubbo/monitor/Monitor.java     |   56 +-
 .../org/apache/dubbo/monitor/MonitorFactory.java   |   76 +-
 .../org/apache/dubbo/monitor/MonitorService.java   |  182 +-
 .../monitor/support/AbstractMonitorFactory.java    |  214 +-
 .../dubbo/monitor/support/MonitorFilter.java       |  374 +-
 .../dubbo/monitor/support/MonitorFilterTest.java   |  398 +--
 .../apache/dubbo/monitor/dubbo/DubboMonitor.java   |  432 +--
 .../org/apache/dubbo/monitor/dubbo/Statistics.java |  420 +--
 .../monitor/dubbo/DubboMonitorFactoryTest.java     |    2 +-
 .../dubbo/monitor/dubbo/DubboMonitorTest.java      |  498 +--
 .../dubbo/monitor/dubbo/MockMonitorService.java    |   88 +-
 .../dubbo/auth/AccessKeyAuthenticatorTest.java     |    3 +-
 .../dubbo/auth/DefaultAccessKeyStorageTest.java    |    3 +-
 .../dubbo/auth/filter/ConsumerSignFilterTest.java  |    3 +-
 .../dubbo/auth/filter/ProviderAuthFilterTest.java  |    2 +-
 .../apache/dubbo/qos/command/impl/BaseOffline.java |    2 +-
 .../org/apache/dubbo/qos/textui/TComponent.java    |    2 +-
 .../dubbo/qos/legacy/ChangeTelnetHandlerTest.java  |    2 +-
 .../dubbo/qos/legacy/CurrentTelnetHandlerTest.java |    2 +-
 .../dubbo/qos/legacy/LogTelnetHandlerTest.java     |    2 +-
 .../dubbo/qos/legacy/PortTelnetHandlerTest.java    |    2 +-
 .../org/apache/dubbo/qos/legacy/ProtocolUtils.java |    2 +-
 .../dubbo/qos/legacy/service/CustomArgument.java   |    2 +-
 .../dubbo/qos/legacy/service/DemoService.java      |    2 +-
 .../dubbo/qos/legacy/service/DemoServiceImpl.java  |    2 +-
 .../org/apache/dubbo/qos/legacy/service/Man.java   |    2 +-
 .../apache/dubbo/qos/legacy/service/Person.java    |    2 +-
 .../org/apache/dubbo/qos/legacy/service/Type.java  |    2 +-
 .../org/apache/dubbo/registry/NotifyListener.java  |  104 +-
 .../java/org/apache/dubbo/registry/Registry.java   |   84 +-
 .../org/apache/dubbo/registry/RegistryFactory.java |   96 +-
 .../org/apache/dubbo/registry/RegistryService.java |  188 +-
 .../registry/client/ServiceDiscoveryRegistry.java  |    2 +-
 .../client/event/ServiceInstancesChangedEvent.java |    2 +-
 .../client/migration/MigrationClusterInvoker.java  |    2 +-
 .../ServiceDiscoveryMigrationInvoker.java          |    2 +-
 .../apache/dubbo/registry/client/package-info.java |    2 +-
 .../registry/integration/RegistryDirectory.java    | 1306 +++----
 .../registry/status/RegistryStatusChecker.java     |  114 +-
 .../dubbo/registry/support/AbstractRegistry.java   | 1078 +++---
 .../registry/support/AbstractRegistryFactory.java  |  482 +--
 .../dubbo/registry/support/FailbackRegistry.java   |  902 ++---
 .../dubbo/registry/PerformanceRegistryTest.java    |  134 +-
 .../apache/dubbo/registry/PerformanceUtils.java    |  254 +-
 .../registry/client/ServiceDiscoveryTest.java      |    2 +-
 .../support/AbstractRegistryFactoryTest.java       |  252 +-
 .../registry/support/FailbackRegistryTest.java     |  486 +--
 .../src/test/resources/log4j.xml                   |   56 +-
 .../registry/multicast/MulticastRegistry.java      |  866 ++---
 .../multicast/MulticastRegistryFactory.java        |   68 +-
 .../multicast/MulticastRegistryFactoryTest.java    |    2 +-
 .../registry/multicast/MulticastRegistryTest.java  |  550 +--
 .../multiple/MultipleServiceDiscovery.java         |    2 +-
 .../multiple/MultipleServiceDiscoveryFactory.java  |    2 +-
 .../apache/dubbo/registry/nacos/NacosRegistry.java |    2 +-
 .../registry/zookeeper/ZookeeperRegistry.java      |  690 ++--
 .../zookeeper/ZookeeperRegistryFactory.java        |   90 +-
 .../registry/zookeeper/ZookeeperRegistryTest.java  |  314 +-
 .../java/org/apache/dubbo/remoting/Channel.java    |    2 +-
 .../org/apache/dubbo/remoting/ChannelHandler.java  |    2 +-
 .../java/org/apache/dubbo/remoting/Client.java     |   76 +-
 .../java/org/apache/dubbo/remoting/Constants.java  |    2 +-
 .../java/org/apache/dubbo/remoting/Endpoint.java   |  178 +-
 .../apache/dubbo/remoting/ExecutionException.java  |  136 +-
 .../apache/dubbo/remoting/RemotingException.java   |    2 +-
 .../apache/dubbo/remoting/TimeoutException.java    |    2 +-
 .../org/apache/dubbo/remoting/Transporters.java    |  164 +-
 .../dubbo/remoting/api/ConnectionHandler.java      |    2 +-
 .../dubbo/remoting/api/ConnectionManager.java      |    2 +-
 .../dubbo/remoting/exchange/ExchangeChannel.java   |  168 +-
 .../dubbo/remoting/exchange/ExchangeClient.java    |   56 +-
 .../dubbo/remoting/exchange/ExchangeHandler.java   |   80 +-
 .../dubbo/remoting/exchange/ExchangeServer.java    |   88 +-
 .../apache/dubbo/remoting/exchange/Exchanger.java  |  110 +-
 .../apache/dubbo/remoting/exchange/Exchangers.java |  242 +-
 .../apache/dubbo/remoting/exchange/Response.java   |  348 +-
 .../remoting/exchange/codec/ExchangeCodec.java     | 1014 +++---
 .../exchange/support/ExchangeHandlerAdapter.java   |   72 +-
 .../support/ExchangeHandlerDispatcher.java         |  242 +-
 .../exchange/support/ExchangeServerDelegate.java   |  264 +-
 .../dubbo/remoting/exchange/support/Replier.java   |   74 +-
 .../exchange/support/ReplierDispatcher.java        |  154 +-
 .../support/header/HeaderExchangeChannel.java      |  540 +--
 .../support/header/HeaderExchangeClient.java       |  476 +--
 .../support/header/HeaderExchangeHandler.java      |  458 +--
 .../support/header/HeaderExchangeServer.java       |  546 +--
 .../exchange/support/header/HeaderExchanger.java   |   94 +-
 .../dubbo/remoting/telnet/TelnetHandler.java       |   74 +-
 .../dubbo/remoting/telnet/codec/TelnetCodec.java   |  596 ++--
 .../apache/dubbo/remoting/telnet/support/Help.java |   78 +-
 .../telnet/support/TelnetHandlerAdapter.java       |  200 +-
 .../dubbo/remoting/telnet/support/TelnetUtils.java |  318 +-
 .../telnet/support/command/ClearTelnetHandler.java |   96 +-
 .../telnet/support/command/ExitTelnetHandler.java  |   74 +-
 .../telnet/support/command/HelpTelnetHandler.java  |  146 +-
 .../support/command/StatusTelnetHandler.java       |  202 +-
 .../dubbo/remoting/transport/AbstractChannel.java  |   94 +-
 .../dubbo/remoting/transport/AbstractPeer.java     |  308 +-
 .../dubbo/remoting/transport/ChannelDelegate.java  |  252 +-
 .../remoting/transport/ChannelHandlerDelegate.java |   46 +-
 .../transport/ChannelHandlerDispatcher.java        |  240 +-
 .../dubbo/remoting/transport/ClientDelegate.java   |  284 +-
 .../dubbo/remoting/transport/ServerDelegate.java   |  244 +-
 .../remoting/transport/codec/TransportCodec.java   |  162 +-
 .../transport/dispatcher/ChannelEventRunnable.java |  268 +-
 .../dispatcher/all/AllChannelHandler.java          |    4 +-
 .../internal/org.apache.dubbo.remoting.Dispatcher  |    8 +-
 .../org.apache.dubbo.remoting.telnet.TelnetHandler |    8 +-
 .../dubbo/remoting/PerformanceClientCloseTest.java |  210 +-
 .../dubbo/remoting/PerformanceClientFixedTest.java |  276 +-
 .../dubbo/remoting/PerformanceClientMain.java      |   58 +-
 .../dubbo/remoting/PerformanceClientTest.java      |  460 +--
 .../dubbo/remoting/PerformanceServerMain.java      |   56 +-
 .../apache/dubbo/remoting/PerformanceUtils.java    |  252 +-
 .../org/apache/dubbo/remoting/TelnetServer.java    |  100 +-
 .../apache/dubbo/remoting/api/ConnectionTest.java  |    2 +-
 .../handler/WrappedChannelHandlerTest.java         |    2 +-
 .../src/test/resources/log4j.xml                   |   56 +-
 .../apache/dubbo/remoting/http/HttpHandler.java    |    2 +-
 .../org/apache/dubbo/remoting/http/HttpServer.java |    2 +-
 .../remoting/transport/netty/NettyClient.java      |  340 +-
 .../transport/netty/NettyCodecAdapter.java         |    2 +-
 .../remoting/transport/netty/NettyHandler.java     |    2 +-
 .../remoting/transport/netty/NettyServer.java      |  332 +-
 .../remoting/transport/netty/NettyTransporter.java |   80 +-
 .../transport/netty/ClientReconnectTest.java       |  192 +-
 .../transport/netty/ClientToServerTest.java        |    2 +-
 .../remoting/transport/netty/ClientsTest.java      |  128 +-
 .../dubbo/remoting/transport/netty/Hello.java      |    2 +-
 .../remoting/transport/netty/NettyClientTest.java  |    2 +-
 .../remoting/transport/netty/NettyStringTest.java  |  132 +-
 .../transport/netty/TelnetClientHandler.java       |    2 +-
 .../transport/netty/TelnetServerHandler.java       |    2 +-
 .../dubbo/remoting/transport/netty/World.java      |    2 +-
 .../remoting/transport/netty/WorldHandler.java     |    2 +-
 .../src/test/resources/log4j.xml                   |   74 +-
 .../remoting/transport/netty4/NettyClient.java     |    6 +-
 .../remoting/transport/netty4/NettyServer.java     |    2 +-
 .../transport/netty4/ClientToServerTest.java       |    2 +-
 .../remoting/transport/netty4/DemoService.java     |   54 +-
 .../remoting/transport/netty4/DemoServiceImpl.java |    2 +-
 .../dubbo/remoting/transport/netty4/Hello.java     |    2 +-
 .../remoting/transport/netty4/MockResult.java      |    2 +-
 .../transport/netty4/ReplierDispatcherTest.java    |    2 +-
 .../remoting/transport/netty4/RpcMessage.java      |  118 +-
 .../transport/netty4/RpcMessageHandler.java        |  154 +-
 .../dubbo/remoting/transport/netty4/World.java     |    2 +-
 .../remoting/transport/netty4/WorldHandler.java    |    2 +-
 .../zookeeper/curator/CuratorZookeeperClient.java  |  876 ++---
 .../zookeeper/support/AbstractZookeeperClient.java |  514 +--
 ...e.dubbo.remoting.zookeeper.ZookeeperTransporter |    2 +-
 .../org/apache/dubbo/rpc/AttachmentsAdapter.java   |    2 +-
 .../main/java/org/apache/dubbo/rpc/Exporter.java   |   88 +-
 .../org/apache/dubbo/rpc/ExporterListener.java     |   90 +-
 .../src/main/java/org/apache/dubbo/rpc/Filter.java |  142 +-
 .../main/java/org/apache/dubbo/rpc/Invocation.java |    2 +-
 .../main/java/org/apache/dubbo/rpc/Invoker.java    |   92 +-
 .../java/org/apache/dubbo/rpc/InvokerListener.java |   88 +-
 .../main/java/org/apache/dubbo/rpc/Protocol.java   |  180 +-
 .../java/org/apache/dubbo/rpc/ProxyFactory.java    |    2 +-
 .../src/main/java/org/apache/dubbo/rpc/Result.java |    2 +-
 .../java/org/apache/dubbo/rpc/RpcConstants.java    |   74 +-
 .../java/org/apache/dubbo/rpc/RpcException.java    |    2 +-
 .../main/java/org/apache/dubbo/rpc/RpcStatus.java  |  640 ++--
 .../rpc/listener/DeprecatedInvokerListener.java    |   84 +-
 .../rpc/listener/ExporterListenerAdapter.java      |   72 +-
 .../dubbo/rpc/listener/InvokerListenerAdapter.java |   72 +-
 .../rpc/listener/ListenerExporterWrapper.java      |  184 +-
 .../dubbo/rpc/listener/ListenerInvokerWrapper.java |  210 +-
 .../dubbo/rpc/protocol/AbstractExporter.java       |  148 +-
 .../dubbo/rpc/protocol/AbstractProxyProtocol.java  |  562 +--
 .../apache/dubbo/rpc/protocol/InvokerWrapper.java  |  128 +-
 .../dubbo/rpc/protocol/dubbo/package-info.java     |    2 +-
 .../dubbo/rpc/proxy/AbstractProxyFactory.java      |  174 +-
 .../dubbo/rpc/proxy/AbstractProxyInvoker.java      |    2 +-
 .../rpc/proxy/wrapper/StubProxyFactoryWrapper.java |  252 +-
 .../org/apache/dubbo/rpc/support/MockInvoker.java  |  570 +--
 .../org/apache/dubbo/rpc/support/MockProtocol.java |   88 +-
 .../internal/org.apache.dubbo.rpc.ProxyFactory     |    4 +-
 .../java/org/apache/dubbo/rpc/CustomArgument.java  |    2 +-
 .../java/org/apache/dubbo/rpc/DemoRequest.java     |    2 +-
 .../dubbo/rpc/filter/AccessLogFilterTest.java      |    2 +-
 .../rpc/filter/CompatibleFilterFilterTest.java     |    2 +-
 .../apache/dubbo/rpc/filter/ContextFilterTest.java |    2 +-
 .../dubbo/rpc/filter/DeprecatedFilterTest.java     |    2 +-
 .../apache/dubbo/rpc/filter/EchoFilterTest.java    |    2 +-
 .../dubbo/rpc/filter/ExceptionFilterTest.java      |    2 +-
 .../apache/dubbo/rpc/filter/tps/StatItemTest.java  |   22 +-
 .../org/apache/dubbo/rpc/proxy/DemoRequest.java    |    2 +-
 .../org/apache/dubbo/rpc/proxy/DemoService.java    |    2 +-
 .../apache/dubbo/rpc/proxy/DemoServiceImpl.java    |    2 +-
 .../org/apache/dubbo/rpc/proxy/RemoteService.java  |   52 +-
 .../apache/dubbo/rpc/proxy/RemoteServiceImpl.java  |    2 +-
 .../test/java/org/apache/dubbo/rpc/proxy/Type.java |   42 +-
 .../org/apache/dubbo/rpc/support/DemoService.java  |    4 +-
 .../apache/dubbo/rpc/support/DemoServiceImpl.java  |    2 +-
 .../java/org/apache/dubbo/rpc/support/IEcho.java   |   42 +-
 .../apache/dubbo/rpc/support/MockInvocation.java   |    2 +-
 .../org/apache/dubbo/rpc/support/MyInvoker.java    |  168 +-
 .../java/org/apache/dubbo/rpc/support/Person.java  |  104 +-
 .../java/org/apache/dubbo/rpc/support/Type.java    |   42 +-
 .../dubbo/rpc/protocol/dubbo/DubboExporter.java    |    2 +-
 .../dubbo/rpc/protocol/dubbo/MultiThreadTest.java  |    2 +-
 .../dubbo/rpc/protocol/dubbo/RpcFilterTest.java    |    2 +-
 .../dubbo/decode/DubboTelnetDecodeTest.java        |    2 +-
 .../rpc/protocol/dubbo/support/CustomArgument.java |    2 +-
 .../rpc/protocol/dubbo/support/DemoRequest.java    |    2 +-
 .../rpc/protocol/dubbo/support/DemoService.java    |    2 +-
 .../protocol/dubbo/support/DemoServiceImpl.java    |    2 +-
 .../dubbo/rpc/protocol/dubbo/support/Man.java      |    2 +-
 .../dubbo/rpc/protocol/dubbo/support/Person.java   |    2 +-
 .../rpc/protocol/dubbo/support/ProtocolUtils.java  |    2 +-
 .../rpc/protocol/dubbo/support/RemoteService.java  |    2 +-
 .../protocol/dubbo/support/RemoteServiceImpl.java  |    2 +-
 .../dubbo/rpc/protocol/dubbo/support/Type.java     |    2 +-
 .../dubbo/rpc/protocol/injvm/InjvmExporter.java    |   92 +-
 .../dubbo/rpc/protocol/injvm/InjvmInvoker.java     |  222 +-
 .../dubbo/rpc/protocol/injvm/DemoRequest.java      |    2 +-
 .../dubbo/rpc/protocol/injvm/DemoService.java      |    2 +-
 .../dubbo/rpc/protocol/injvm/DemoServiceImpl.java  |    2 +-
 .../org/apache/dubbo/rpc/protocol/injvm/IEcho.java |   42 +-
 .../org/apache/dubbo/rpc/protocol/injvm/Type.java  |   42 +-
 .../swagger/DubboSwaggerApiListingResource.java    |    2 +-
 .../integration/swagger/DubboSwaggerService.java   |    2 +-
 .../rpc/protocol/rest/RpcExceptionMapperTest.java  |    2 +-
 .../apache/dubbo/rpc/protocol/tri/Metadata.java    |    2 +-
 .../dubbo/rpc/protocol/tri/GrpcStatusTest.java     |    2 +-
 .../rpc/protocol/tri/UnaryClientStreamTest.java    |    2 +-
 .../rpc/protocol/tri/UnaryServerStreamTest.java    |    2 +-
 .../apache/dubbo/common/serialize/DataInput.java   |    2 +-
 .../apache/dubbo/common/serialize/DataOutput.java  |    2 +-
 .../apache/dubbo/common/serialize/ObjectInput.java |    2 +-
 .../dubbo/common/serialize/ObjectOutput.java       |    2 +-
 .../hessian2/Hessian2SerializerFactory.java        |    2 +-
 .../serialize/java/CompactedObjectInputStream.java |    2 +-
 .../java/CompactedObjectOutputStream.java          |    2 +-
 .../dubbo-spring-boot-actuator/README.md           |  998 +++---
 .../dubbo-spring-boot-actuator/pom.xml             |  246 +-
 .../DubboEndpointAnnotationAutoConfiguration.java  |  176 +-
 .../endpoint/DubboConfigsMetadataEndpoint.java     |   86 +-
 .../actuate/endpoint/DubboMetadataEndpoint.java    |   88 +-
 .../endpoint/DubboPropertiesMetadataEndpoint.java  |   86 +-
 .../endpoint/DubboReferencesMetadataEndpoint.java  |   88 +-
 .../endpoint/DubboServicesMetadataEndpoint.java    |   88 +-
 .../actuate/endpoint/DubboShutdownEndpoint.java    |   88 +-
 .../CompatibleConditionalOnEnabledEndpoint.java    |  102 +-
 .../CompatibleOnEnabledEndpointCondition.java      |  138 +-
 .../META-INF/dubbo-endpoints-default.properties    |   42 +-
 .../src/main/resources/META-INF/spring.factories   |    2 +-
 ...bboEndpointAnnotationAutoConfigurationTest.java |  528 +--
 .../boot/actuate/endpoint/DubboEndpointTest.java   |  186 +-
 .../dubbo-spring-boot-autoconfigure/README.md      |  450 +--
 .../dubbo-spring-boot-autoconfigure/pom.xml        |  168 +-
 .../autoconfigure/BinderDubboConfigBinder.java     |  158 +-
 .../DubboRelaxedBinding2AutoConfiguration.java     |  184 +-
 .../src/main/resources/META-INF/spring.factories   |    2 +-
 .../autoconfigure/BinderDubboConfigBinderTest.java |  144 +-
 .../DubboRelaxedBinding2AutoConfigurationTest.java |  188 +-
 ...aultPropertiesEnvironmentPostProcessorTest.java |  194 +-
 .../src/test/resources/dubbo.properties            |   10 +-
 .../dubbo-spring-boot-compatible/actuator/pom.xml  |  206 +-
 .../DubboEndpointAutoConfiguration.java            |  110 +-
 .../DubboEndpointMetadataAutoConfiguration.java    |   78 +-
 .../DubboHealthIndicatorAutoConfiguration.java     |  100 +-
 ...oMvcEndpointManagementContextConfiguration.java |   98 +-
 .../boot/actuate/endpoint/DubboEndpoint.java       |   98 +-
 .../endpoint/metadata/AbstractDubboMetadata.java   |  248 +-
 .../endpoint/metadata/DubboConfigsMetadata.java    |  174 +-
 .../actuate/endpoint/metadata/DubboMetadata.java   |  124 +-
 .../endpoint/metadata/DubboPropertiesMetadata.java |   72 +-
 .../endpoint/metadata/DubboReferencesMetadata.java |  158 +-
 .../endpoint/metadata/DubboServicesMetadata.java   |  168 +-
 .../endpoint/metadata/DubboShutdownMetadata.java   |  156 +-
 .../actuate/endpoint/mvc/DubboMvcEndpoint.java     |  224 +-
 .../boot/actuate/health/DubboHealthIndicator.java  |  446 +--
 .../health/DubboHealthIndicatorProperties.java     |  198 +-
 .../src/main/resources/META-INF/spring.factories   |   10 +-
 .../DubboEndpointAutoConfigurationTest.java        |  476 +--
 .../actuate/health/DubboHealthIndicatorTest.java   |  178 +-
 .../autoconfigure/pom.xml                          |  174 +-
 .../boot/autoconfigure/DubboAutoConfiguration.java |  228 +-
 .../DubboConfigurationProperties.java              |  600 ++--
 .../DubboRelaxedBindingAutoConfiguration.java      |  146 +-
 .../autoconfigure/RelaxedDubboConfigBinder.java    |   96 +-
 .../config/ServiceBeanIdConflictProcessor.java     |  230 +-
 .../DubboApplicationContextInitializer.java        |  100 +-
 .../event/AwaitingNonWebApplicationListener.java   |  398 +--
 ...gBeanDefinitionConflictApplicationListener.java |  242 +-
 .../event/WelcomeLogoApplicationListener.java      |  189 +-
 ...oDefaultPropertiesEnvironmentPostProcessor.java |  272 +-
 .../apache/dubbo/spring/boot/util/DubboUtils.java  |  368 +-
 .../src/main/resources/META-INF/spring.factories   |   20 +-
 .../org/apache/dubbo/spring/boot/TestSuite.java    |   94 +-
 .../CompatibleDubboAutoConfigurationTest.java      |  118 +-
 ...ubboAutoConfigurationTestWithoutProperties.java |  132 +-
 ...DubboAutoConfigurationOnMultipleConfigTest.java |  559 ++-
 .../DubboAutoConfigurationOnSingleConfigTest.java  |  307 +-
 .../RelaxedDubboConfigBinderTest.java              |  180 +-
 .../AwaitingNonWebApplicationListenerTest.java     |  150 +-
 ...nDefinitionConflictApplicationListenerTest.java |  208 +-
 .../event/WelcomeLogoApplicationListenerTest.java  |   96 +-
 ...aultPropertiesEnvironmentPostProcessorTest.java |  194 +-
 .../dubbo/spring/boot/util/DubboUtilsTest.java     |  170 +-
 .../src/test/resources/META-INF/dubbo.properties   |    2 +-
 .../resources/META-INF/spring/dubbo-context.xml    |   26 +-
 .../dubbo-spring-boot-compatible/pom.xml           |  104 +-
 .../dubbo-spring-boot-starter/pom.xml              |   96 +-
 pom.xml                                            |   25 +
 728 files changed, 42287 insertions(+), 42214 deletions(-)

diff --git a/.gitattributes b/.gitattributes
index bb5d205..c8c7a66 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,4 +1,20 @@
-# Git will understand that all files specified are not text,
-# and it should not try to change them.
-# This will prevent file formatting (such as `crlf` endings to `lf` endings) while commit.
-* -text
\ No newline at end of file
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Auto detect text files and perform LF normalization
+*        text=auto
+
+*.java   text eol=lf
\ No newline at end of file
diff --git a/.github/workflows/build-and-test-3.yml b/.github/workflows/build-and-test-3.yml
index 9225474..a7a3f66 100644
--- a/.github/workflows/build-and-test-3.yml
+++ b/.github/workflows/build-and-test-3.yml
@@ -39,7 +39,25 @@ jobs:
       - name: "Build Dubbo with Maven"
         run: |
           cd ./dubbo
-          ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress clean source:jar install -Pjacoco,rat,checkstyle -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -Dmaven.test.skip=true -Dmaven.test.skip.exec=true
+          ./mvnw --batch-mode -U -e --no-transfer-progress clean source:jar install -Pjacoco,rat,checkstyle -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -Dmaven.test.skip=true -Dmaven.test.skip.exec=true
+      - name: "Pack rat file if failure"
+        if: failure()
+        run: 7z a ${{ github.workspace }}/rat.zip *rat.txt -r
+      - name: "Upload rat file if failure"
+        if: failure()
+        uses: actions/upload-artifact@v2
+        with:
+          name: "rat-file"
+          path: ${{ github.workspace }}/rat.zip
+      - name: "Pack checkstyle file if failure"
+        if: failure()
+        run: 7z a ${{ github.workspace }}/checkstyle.zip *checkstyle* -r
+      - name: "Upload checkstyle file if failure"
+        if: failure()
+        uses: actions/upload-artifact@v2
+        with:
+          name: "checkstyle-file"
+          path: ${{ github.workspace }}/checkstyle.zip
       - name: "Calculate Dubbo Version"
         id: dubbo-version
         run: |
@@ -72,22 +90,13 @@ jobs:
       - name: "Test with Maven with Integration Tests"
         timeout-minutes: 40
         if: ${{ startsWith( matrix.os, 'ubuntu') }}
-        run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress clean test verify -Pjacoco -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true
+        run: ./mvnw --batch-mode -U -e --no-transfer-progress clean test verify -Pjacoco -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Dcheckstyle_unix.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true
       - name: "Test with Maven without Integration Tests"
         env:
           DISABLE_FILE_SYSTEM_TEST: true
         timeout-minutes: 50
         if: ${{ startsWith( matrix.os, 'windows') }}
-        run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress clean test verify -Pjacoco -D"http.keepAlive=false" -D"maven.wagon.http.pool=false" -D"maven.wagon.httpconnectionManager.ttlSeconds=120" -D"maven.wagon.http.retryHandler.count=5" -DskipTests=false -DskipIntegrationTests=true -D"checkstyle.skip=false" -D"rat.skip=false" -D"maven.javadoc.skip=true"
-      - name: "Pack rat file if failure"
-        if: failure()
-        run: 7z a ${{ github.workspace }}/rat.zip *rat.txt -r
-      - name: "Upload rat file if failure"
-        if: failure()
-        uses: actions/upload-artifact@v2
-        with:
-          name: "rat-file-${{ matrix.os }}-JDK${{ matrix.jdk }}"
-          path: ${{ github.workspace }}/rat.zip
+        run: ./mvnw --batch-mode -U -e --no-transfer-progress clean test verify -Pjacoco -D"http.keepAlive=false" -D"maven.wagon.http.pool=false" -D"maven.wagon.httpconnectionManager.ttlSeconds=120" -D"maven.wagon.http.retryHandler.count=5" -DskipTests=false -DskipIntegrationTests=true -D"checkstyle.skip=false" -D"checkstyle_unix.skip=true" -D"rat.skip=false" -D"maven.javadoc.skip=true"
       - name: "Upload coverage to Codecov"
         uses: codecov/codecov-action@v1
 
diff --git a/LICENSE b/LICENSE
index 89ce3a5..4702175 100644
--- a/LICENSE
+++ b/LICENSE
@@ -279,4 +279,4 @@ https://developers.google.com/protocol-buffers/ and is licensed under the follow
     Code generated by the Protocol Buffer compiler is owned by the owner
     of the input file used when generating it.  This code is not
     standalone and requires a support library to be linked with it.  This
-    support library is itself covered by the above license.
\ No newline at end of file
+    support library is itself covered by the above license.
diff --git a/NOTICE b/NOTICE
index 9e952c6..7ea7a3b 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,14 +1,14 @@
-Apache Dubbo
-Copyright 2018-2021 The Apache Software Foundation
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-
-This product contains code form the Netty Project:
-
-The Netty Project
-=================
-Please visit the Netty web site for more information:
-  * http://netty.io/
-
-Copyright 2014 The Netty Project
+Apache Dubbo
+Copyright 2018-2021 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+This product contains code form the Netty Project:
+
+The Netty Project
+=================
+Please visit the Netty web site for more information:
+  * http://netty.io/
+
+Copyright 2014 The Netty Project
diff --git a/codestyle/checkstyle-suppressions.xml b/codestyle/checkstyle-suppressions.xml
index 1817cf7..0b2fa10 100644
--- a/codestyle/checkstyle-suppressions.xml
+++ b/codestyle/checkstyle-suppressions.xml
@@ -4,5 +4,6 @@
         "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
 <suppressions>
     <suppress files="[\\/]src[\\/]main[\\/]java[\\/]com[\\/]alibaba[\\/]com[\\/]caucho[\\/]hessian" checks=".*"/>
+    <suppress files="[\\/]build[\\/]generated[\\/]source[\\/]proto" checks=".*"/>
     <suppress files="Yylex\.java" checks="AvoidEscapedUnicodeCharacters"/>
 </suppressions>
\ No newline at end of file
diff --git a/codestyle/checkstyle.xml b/codestyle/checkstyle.xml
index 050fbed..413cc72 100644
--- a/codestyle/checkstyle.xml
+++ b/codestyle/checkstyle.xml
@@ -12,6 +12,10 @@
         <property name="fileExtensions" value="java"/>
     </module>
 
+    <module name="FileTabCharacter">
+        <property name="fileExtensions" value="java,xml"/>
+    </module>
+
     <!-- TreeWalker Checks -->
     <module name="TreeWalker">
         <module name="SuppressWarningsHolder"/>
diff --git a/codestyle/checkstyle_unix.xml b/codestyle/checkstyle_unix.xml
new file mode 100644
index 0000000..589c7d7
--- /dev/null
+++ b/codestyle/checkstyle_unix.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!DOCTYPE module PUBLIC
+        "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
+        "http://checkstyle.sourceforge.net/dtds/configuration_1_3.dtd">
+
+<module name="Checker">
+    <module name="NewlineAtEndOfFile">
+        <property name="lineSeparator" value="lf" />
+    </module>
+</module>
diff --git a/compiler/src/main/java/org/apache/dubbo/gen/dubbo/DubboGenerator.java b/compiler/src/main/java/org/apache/dubbo/gen/dubbo/DubboGenerator.java
index 1c35f0a..1abf2a0 100644
--- a/compiler/src/main/java/org/apache/dubbo/gen/dubbo/DubboGenerator.java
+++ b/compiler/src/main/java/org/apache/dubbo/gen/dubbo/DubboGenerator.java
@@ -39,4 +39,4 @@ public class DubboGenerator extends AbstractGenerator {
     protected String getClassSuffix() {
         return "Dubbo";
     }
-}
\ No newline at end of file
+}
diff --git a/dubbo-build-tools/pom.xml b/dubbo-build-tools/pom.xml
index 966218d..a1a0c60 100644
--- a/dubbo-build-tools/pom.xml
+++ b/dubbo-build-tools/pom.xml
@@ -64,6 +64,7 @@
                         <exclude>**/.classpath</exclude>
                         <exclude>**/.project</exclude>
                         <exclude>**/target/**</exclude>
+                        <exclude>**/generated/**</exclude>
                         <exclude>**/*.log</exclude>
                         <exclude>CONTRIBUTING.md</exclude>
                         <exclude>README.md</exclude>
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-cluster/src/main/java/org/apache/dubbo/registry/AddressListener.java
index 684cb64..bd1947a 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/registry/AddressListener.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/registry/AddressListener.java
@@ -38,4 +38,4 @@ public interface AddressListener {
 
     }
 
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Cluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Cluster.java
index 1fdadf8..04cc573 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Cluster.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Cluster.java
@@ -1,59 +1,59 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster;
-
-import org.apache.dubbo.common.extension.Adaptive;
-import org.apache.dubbo.common.extension.ExtensionLoader;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.RpcException;
-
-/**
- * Cluster. (SPI, Singleton, ThreadSafe)
- * <p>
- * <a href="http://en.wikipedia.org/wiki/Computer_cluster">Cluster</a>
- * <a href="http://en.wikipedia.org/wiki/Fault-tolerant_system">Fault-Tolerant</a>
- *
- */
-@SPI(Cluster.DEFAULT)
-public interface Cluster {
-
-    String DEFAULT = "failover";
-
-    /**
-     * Merge the directory invokers to a virtual invoker.
-     *
-     * @param <T>
-     * @param directory
-     * @return cluster invoker
-     * @throws RpcException
-     */
-    @Adaptive
-    <T> Invoker<T> join(Directory<T> directory) throws RpcException;
-
-    static Cluster getCluster(String name) {
-        return getCluster(name, true);
-    }
-
-    static Cluster getCluster(String name, boolean wrap) {
-        if (StringUtils.isEmpty(name)) {
-            name = Cluster.DEFAULT;
-        }
-        return ExtensionLoader.getExtensionLoader(Cluster.class).getExtension(name, wrap);
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster;
+
+import org.apache.dubbo.common.extension.Adaptive;
+import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.extension.SPI;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.RpcException;
+
+/**
+ * Cluster. (SPI, Singleton, ThreadSafe)
+ * <p>
+ * <a href="http://en.wikipedia.org/wiki/Computer_cluster">Cluster</a>
+ * <a href="http://en.wikipedia.org/wiki/Fault-tolerant_system">Fault-Tolerant</a>
+ *
+ */
+@SPI(Cluster.DEFAULT)
+public interface Cluster {
+
+    String DEFAULT = "failover";
+
+    /**
+     * Merge the directory invokers to a virtual invoker.
+     *
+     * @param <T>
+     * @param directory
+     * @return cluster invoker
+     * @throws RpcException
+     */
+    @Adaptive
+    <T> Invoker<T> join(Directory<T> directory) throws RpcException;
+
+    static Cluster getCluster(String name) {
+        return getCluster(name, true);
+    }
+
+    static Cluster getCluster(String name, boolean wrap) {
+        if (StringUtils.isEmpty(name)) {
+            name = Cluster.DEFAULT;
+        }
+        return ExtensionLoader.getExtensionLoader(Cluster.class).getExtension(name, wrap);
+    }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Configurator.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Configurator.java
index 2a69f6e..3b1d25e 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Configurator.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Configurator.java
@@ -1,119 +1,119 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.ExtensionLoader;
-import org.apache.dubbo.common.utils.CollectionUtils;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-
-import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY;
-import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL;
-import static org.apache.dubbo.rpc.cluster.Constants.PRIORITY_KEY;
-
-/**
- * Configurator. (SPI, Prototype, ThreadSafe)
- *
- */
-public interface Configurator extends Comparable<Configurator> {
-
-    /**
-     * Get the configurator url.
-     *
-     * @return configurator url.
-     */
-    URL getUrl();
-
-    /**
-     * Configure the provider url.
-     *
-     * @param url - old provider url.
-     * @return new provider 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
-     * calculated
-     *
-     * URL contract:
-     * <ol>
-     * <li>override://0.0.0.0/...( or override://ip:port...?anyhost=true)&para1=value1... means global rules
-     * (all of the providers take effect)</li>
-     * <li>override://ip:port...?anyhost=false Special rules (only for a certain provider)</li>
-     * <li>override:// rule is not supported... ,needs to be calculated by registry itself</li>
-     * <li>override://0.0.0.0/ without parameters means clearing the override</li>
-     * </ol>
-     *
-     * @param urls URL list to convert
-     * @return converted configurator list
-     */
-    static Optional<List<Configurator>> toConfigurators(List<URL> urls) {
-        if (CollectionUtils.isEmpty(urls)) {
-            return Optional.empty();
-        }
-
-        ConfiguratorFactory configuratorFactory = ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
-                .getAdaptiveExtension();
-
-        List<Configurator> configurators = new ArrayList<>(urls.size());
-        for (URL url : urls) {
-            if (EMPTY_PROTOCOL.equals(url.getProtocol())) {
-                configurators.clear();
-                break;
-            }
-            Map<String, String> override = new HashMap<>(url.getParameters());
-            //The anyhost parameter of override may be added automatically, it can't change the judgement of changing url
-            override.remove(ANYHOST_KEY);
-            if (CollectionUtils.isEmptyMap(override)) {
-                continue;
-            }
-            configurators.add(configuratorFactory.getConfigurator(url));
-        }
-        Collections.sort(configurators);
-        return Optional.of(configurators);
-    }
-
-    /**
-     * Sort by host, then by priority
-     * 1. the url with a specific host ip should have higher priority than 0.0.0.0
-     * 2. if two url has the same host, compare by priority value;
-     */
-    @Override
-    default int compareTo(Configurator o) {
-        if (o == null) {
-            return -1;
-        }
-
-        int ipCompare = getUrl().getHost().compareTo(o.getUrl().getHost());
-        // host is the same, sort by priority
-        if (ipCompare == 0) {
-            int i = getUrl().getParameter(PRIORITY_KEY, 0);
-            int j = o.getUrl().getParameter(PRIORITY_KEY, 0);
-            return Integer.compare(i, j);
-        } else {
-            return ipCompare;
-        }
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.utils.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY;
+import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL;
+import static org.apache.dubbo.rpc.cluster.Constants.PRIORITY_KEY;
+
+/**
+ * Configurator. (SPI, Prototype, ThreadSafe)
+ *
+ */
+public interface Configurator extends Comparable<Configurator> {
+
+    /**
+     * Get the configurator url.
+     *
+     * @return configurator url.
+     */
+    URL getUrl();
+
+    /**
+     * Configure the provider url.
+     *
+     * @param url - old provider url.
+     * @return new provider 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
+     * calculated
+     *
+     * URL contract:
+     * <ol>
+     * <li>override://0.0.0.0/...( or override://ip:port...?anyhost=true)&para1=value1... means global rules
+     * (all of the providers take effect)</li>
+     * <li>override://ip:port...?anyhost=false Special rules (only for a certain provider)</li>
+     * <li>override:// rule is not supported... ,needs to be calculated by registry itself</li>
+     * <li>override://0.0.0.0/ without parameters means clearing the override</li>
+     * </ol>
+     *
+     * @param urls URL list to convert
+     * @return converted configurator list
+     */
+    static Optional<List<Configurator>> toConfigurators(List<URL> urls) {
+        if (CollectionUtils.isEmpty(urls)) {
+            return Optional.empty();
+        }
+
+        ConfiguratorFactory configuratorFactory = ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
+                .getAdaptiveExtension();
+
+        List<Configurator> configurators = new ArrayList<>(urls.size());
+        for (URL url : urls) {
+            if (EMPTY_PROTOCOL.equals(url.getProtocol())) {
+                configurators.clear();
+                break;
+            }
+            Map<String, String> override = new HashMap<>(url.getParameters());
+            //The anyhost parameter of override may be added automatically, it can't change the judgement of changing url
+            override.remove(ANYHOST_KEY);
+            if (CollectionUtils.isEmptyMap(override)) {
+                continue;
+            }
+            configurators.add(configuratorFactory.getConfigurator(url));
+        }
+        Collections.sort(configurators);
+        return Optional.of(configurators);
+    }
+
+    /**
+     * Sort by host, then by priority
+     * 1. the url with a specific host ip should have higher priority than 0.0.0.0
+     * 2. if two url has the same host, compare by priority value;
+     */
+    @Override
+    default int compareTo(Configurator o) {
+        if (o == null) {
+            return -1;
+        }
+
+        int ipCompare = getUrl().getHost().compareTo(o.getUrl().getHost());
+        // host is the same, sort by priority
+        if (ipCompare == 0) {
+            int i = getUrl().getParameter(PRIORITY_KEY, 0);
+            int j = o.getUrl().getParameter(PRIORITY_KEY, 0);
+            return Integer.compare(i, j);
+        } else {
+            return ipCompare;
+        }
+    }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/ConfiguratorFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/ConfiguratorFactory.java
index 026d6f5..8b2722c 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/ConfiguratorFactory.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/ConfiguratorFactory.java
@@ -1,39 +1,39 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.Adaptive;
-import org.apache.dubbo.common.extension.SPI;
-
-/**
- * ConfiguratorFactory. (SPI, Singleton, ThreadSafe)
- *
- */
-@SPI
-public interface ConfiguratorFactory {
-
-    /**
-     * get the configurator instance.
-     *
-     * @param url - configurator url.
-     * @return configurator instance.
-     */
-    @Adaptive("protocol")
-    Configurator getConfigurator(URL url);
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.Adaptive;
+import org.apache.dubbo.common.extension.SPI;
+
+/**
+ * ConfiguratorFactory. (SPI, Singleton, ThreadSafe)
+ *
+ */
+@SPI
+public interface ConfiguratorFactory {
+
+    /**
+     * get the configurator instance.
+     *
+     * @param url - configurator url.
+     * @return configurator instance.
+     */
+    @Adaptive("protocol")
+    Configurator getConfigurator(URL url);
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Directory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Directory.java
index 5a92d97..c797218 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Directory.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Directory.java
@@ -1,72 +1,72 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster;
-
-import org.apache.dubbo.common.Node;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.utils.CollectionUtils;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.RpcException;
-
-import java.util.List;
-
-/**
- * Directory. (SPI, Prototype, ThreadSafe)
- * <p>
- * <a href="http://en.wikipedia.org/wiki/Directory_service">Directory Service</a>
- *
- * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory)
- */
-public interface Directory<T> extends Node {
-
-    /**
-     * get service type.
-     *
-     * @return service type.
-     */
-    Class<T> getInterface();
-
-    /**
-     * list invokers.
-     *
-     * @return invokers
-     */
-    List<Invoker<T>> list(Invocation invocation) throws RpcException;
-
-    List<Invoker<T>> getAllInvokers();
-
-    URL getConsumerUrl();
-
-    boolean isDestroyed();
-
-    default boolean isEmpty() {
-        return CollectionUtils.isEmpty(getAllInvokers());
-    }
-
-    default boolean isServiceDiscovery() {
-        return false;
-    }
-
-    void discordAddresses();
-
-    RouterChain<T> getRouterChain();
-
-    default boolean isNotificationReceived() {
-        return false;
-    }
-}
\ No newline at end of file
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster;
+
+import org.apache.dubbo.common.Node;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.RpcException;
+
+import java.util.List;
+
+/**
+ * Directory. (SPI, Prototype, ThreadSafe)
+ * <p>
+ * <a href="http://en.wikipedia.org/wiki/Directory_service">Directory Service</a>
+ *
+ * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory)
+ */
+public interface Directory<T> extends Node {
+
+    /**
+     * get service type.
+     *
+     * @return service type.
+     */
+    Class<T> getInterface();
+
+    /**
+     * list invokers.
+     *
+     * @return invokers
+     */
+    List<Invoker<T>> list(Invocation invocation) throws RpcException;
+
+    List<Invoker<T>> getAllInvokers();
+
+    URL getConsumerUrl();
+
+    boolean isDestroyed();
+
+    default boolean isEmpty() {
+        return CollectionUtils.isEmpty(getAllInvokers());
+    }
+
+    default boolean isServiceDiscovery() {
+        return false;
+    }
+
+    void discordAddresses();
+
+    RouterChain<T> getRouterChain();
+
+    default boolean isNotificationReceived() {
+        return false;
+    }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/LoadBalance.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/LoadBalance.java
index 4e6ced1..94b28a8 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/LoadBalance.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/LoadBalance.java
@@ -1,50 +1,50 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.Adaptive;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.cluster.loadbalance.RandomLoadBalance;
-
-import java.util.List;
-
-/**
- * LoadBalance. (SPI, Singleton, ThreadSafe)
- * <p>
- * <a href="http://en.wikipedia.org/wiki/Load_balancing_(computing)">Load-Balancing</a>
- *
- * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory)
- */
-@SPI(RandomLoadBalance.NAME)
-public interface LoadBalance {
-
-    /**
-     * select one invoker in list.
-     *
-     * @param invokers   invokers.
-     * @param url        refer url
-     * @param invocation invocation.
-     * @return selected invoker.
-     */
-    @Adaptive("loadbalance")
-    <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException;
-
-}
\ No newline at end of file
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.Adaptive;
+import org.apache.dubbo.common.extension.SPI;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.loadbalance.RandomLoadBalance;
+
+import java.util.List;
+
+/**
+ * LoadBalance. (SPI, Singleton, ThreadSafe)
+ * <p>
+ * <a href="http://en.wikipedia.org/wiki/Load_balancing_(computing)">Load-Balancing</a>
+ *
+ * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory)
+ */
+@SPI(RandomLoadBalance.NAME)
+public interface LoadBalance {
+
+    /**
+     * select one invoker in list.
+     *
+     * @param invokers   invokers.
+     * @param url        refer url
+     * @param invocation invocation.
+     * @return selected invoker.
+     */
+    @Adaptive("loadbalance")
+    <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException;
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Router.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Router.java
index c412ff8..2877012 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Router.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Router.java
@@ -1,103 +1,103 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.RpcException;
-
-import java.util.List;
-
-/**
- * Router. (SPI, Prototype, ThreadSafe)
- * <p>
- * <a href="http://en.wikipedia.org/wiki/Routing">Routing</a>
- *
- * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory)
- * @see org.apache.dubbo.rpc.cluster.Directory#list(Invocation)
- */
-public interface Router extends Comparable<Router> {
-
-    int DEFAULT_PRIORITY = Integer.MAX_VALUE;
-
-    /**
-     * Get the router url.
-     *
-     * @return url
-     */
-    URL getUrl();
-
-    /**
-     * Filter invokers with current routing rule and only return the invokers that comply with the rule.
-     *
-     * @param invokers   invoker list
-     * @param url        refer url
-     * @param invocation invocation
-     * @return routed invokers
-     * @throws RpcException
-     */
-    <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException;
-
-
-    /**
-     * Notify the router the invoker list. Invoker list may change from time to time. This method gives the router a
-     * chance to prepare before {@link Router#route(List, URL, Invocation)} gets called.
-     *
-     * @param invokers invoker list
-     * @param <T>      invoker's type
-     */
-    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
-     * rule change.
-     *
-     * @return true if the router need to execute every time.
-     */
-    boolean isRuntime();
-
-    /**
-     * To decide whether this router should take effect when none of the invoker can match the router rule, which
-     * means the {@link #route(List, URL, Invocation)} would be empty. Most of time, most router implementation would
-     * default this value to false.
-     *
-     * @return true to execute if none of invokers matches the current router
-     */
-    boolean isForce();
-
-    /**
-     * Router's priority, used to sort routers.
-     *
-     * @return router's priority
-     */
-    int getPriority();
-
-    default void stop() {
-        //do nothing by default
-    }
-
-    @Override
-    default int compareTo(Router o) {
-        if (o == null) {
-            throw new IllegalArgumentException();
-        }
-        return Integer.compare(this.getPriority(), o.getPriority());
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.RpcException;
+
+import java.util.List;
+
+/**
+ * Router. (SPI, Prototype, ThreadSafe)
+ * <p>
+ * <a href="http://en.wikipedia.org/wiki/Routing">Routing</a>
+ *
+ * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory)
+ * @see org.apache.dubbo.rpc.cluster.Directory#list(Invocation)
+ */
+public interface Router extends Comparable<Router> {
+
+    int DEFAULT_PRIORITY = Integer.MAX_VALUE;
+
+    /**
+     * Get the router url.
+     *
+     * @return url
+     */
+    URL getUrl();
+
+    /**
+     * Filter invokers with current routing rule and only return the invokers that comply with the rule.
+     *
+     * @param invokers   invoker list
+     * @param url        refer url
+     * @param invocation invocation
+     * @return routed invokers
+     * @throws RpcException
+     */
+    <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException;
+
+
+    /**
+     * Notify the router the invoker list. Invoker list may change from time to time. This method gives the router a
+     * chance to prepare before {@link Router#route(List, URL, Invocation)} gets called.
+     *
+     * @param invokers invoker list
+     * @param <T>      invoker's type
+     */
+    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
+     * rule change.
+     *
+     * @return true if the router need to execute every time.
+     */
+    boolean isRuntime();
+
+    /**
+     * To decide whether this router should take effect when none of the invoker can match the router rule, which
+     * means the {@link #route(List, URL, Invocation)} would be empty. Most of time, most router implementation would
+     * default this value to false.
+     *
+     * @return true to execute if none of invokers matches the current router
+     */
+    boolean isForce();
+
+    /**
+     * Router's priority, used to sort routers.
+     *
+     * @return router's priority
+     */
+    int getPriority();
+
+    default void stop() {
+        //do nothing by default
+    }
+
+    @Override
+    default int compareTo(Router o) {
+        if (o == null) {
+            throw new IllegalArgumentException();
+        }
+        return Integer.compare(this.getPriority(), o.getPriority());
+    }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java
index b7644b3..3a98a58 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java
@@ -1,47 +1,47 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.Adaptive;
-import org.apache.dubbo.common.extension.SPI;
-
-/**
- * RouterFactory. (SPI, Singleton, ThreadSafe)
- * <p>
- * <a href="http://en.wikipedia.org/wiki/Routing">Routing</a>
- *
- * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory)
- * @see org.apache.dubbo.rpc.cluster.Directory#list(org.apache.dubbo.rpc.Invocation)
- * <p>
- * Note Router has a different behaviour since 2.7.0, for each type of Router, there will only has one Router instance
- * for each service. See {@link CacheableRouterFactory} and {@link RouterChain} for how to extend a new Router or how
- * the Router instances are loaded.
- */
-@SPI
-public interface RouterFactory {
-
-    /**
-     * Create router.
-     * Since 2.7.0, most of the time, we will not use @Adaptive feature, so it's kept only for compatibility.
-     *
-     * @param url url
-     * @return router instance
-     */
-    @Adaptive("protocol")
-    Router getRouter(URL url);
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.Adaptive;
+import org.apache.dubbo.common.extension.SPI;
+
+/**
+ * RouterFactory. (SPI, Singleton, ThreadSafe)
+ * <p>
+ * <a href="http://en.wikipedia.org/wiki/Routing">Routing</a>
+ *
+ * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory)
+ * @see org.apache.dubbo.rpc.cluster.Directory#list(org.apache.dubbo.rpc.Invocation)
+ * <p>
+ * Note Router has a different behaviour since 2.7.0, for each type of Router, there will only has one Router instance
+ * for each service. See {@link CacheableRouterFactory} and {@link RouterChain} for how to extend a new Router or how
+ * the Router instances are loaded.
+ */
+@SPI
+public interface RouterFactory {
+
+    /**
+     * Create router.
+     * Since 2.7.0, most of the time, we will not use @Adaptive feature, so it's kept only for compatibility.
+     *
+     * @param url url
+     * @return router instance
+     */
+    @Adaptive("protocol")
+    Router getRouter(URL url);
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/AbstractConfigurator.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/AbstractConfigurator.java
index 751d284..a612889 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/AbstractConfigurator.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/AbstractConfigurator.java
@@ -1,170 +1,170 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.configurator;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.utils.NetUtils;
-import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.remoting.Constants;
-import org.apache.dubbo.rpc.cluster.Configurator;
-
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
-import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE;
-import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
-import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.INTERFACES;
-import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER;
-import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
-import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY;
-import static org.apache.dubbo.common.constants.RegistryConstants.COMPATIBLE_CONFIG_KEY;
-import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_KEY;
-import static org.apache.dubbo.rpc.cluster.Constants.CONFIG_VERSION_KEY;
-import static org.apache.dubbo.rpc.cluster.Constants.OVERRIDE_PROVIDERS_KEY;
-
-/**
- * AbstractOverrideConfigurator
- */
-public abstract class AbstractConfigurator implements Configurator {
-
-    private static final String TILDE = "~";
-
-    private final URL configuratorUrl;
-
-    public AbstractConfigurator(URL url) {
-        if (url == null) {
-            throw new IllegalArgumentException("configurator url == null");
-        }
-        this.configuratorUrl = url;
-    }
-
-    @Override
-    public URL getUrl() {
-        return configuratorUrl;
-    }
-
-    @Override
-    public URL configure(URL url) {
-        // If override url is not enabled or is invalid, just return.
-        if (!configuratorUrl.getParameter(ENABLED_KEY, true) || configuratorUrl.getHost() == null || url == null || url.getHost() == null) {
-            return url;
-        }
-        /*
-         * This if branch is created since 2.7.0.
-         */
-        String apiVersion = configuratorUrl.getParameter(CONFIG_VERSION_KEY);
-        if (StringUtils.isNotEmpty(apiVersion)) {
-            String currentSide = url.getSide();
-            String configuratorSide = configuratorUrl.getSide();
-            if (currentSide.equals(configuratorSide) && CONSUMER.equals(configuratorSide) && 0 == configuratorUrl.getPort()) {
-                url = configureIfMatch(NetUtils.getLocalHost(), url);
-            } else if (currentSide.equals(configuratorSide) && PROVIDER.equals(configuratorSide) &&
-                    url.getPort() == configuratorUrl.getPort()) {
-                url = configureIfMatch(url.getHost(), url);
-            }
-        }
-        /*
-         * This else branch is deprecated and is left only to keep compatibility with versions before 2.7.0
-         */
-        else {
-            url = configureDeprecated(url);
-        }
-        return url;
-    }
-
-    @Deprecated
-    private URL configureDeprecated(URL url) {
-        // If override url has port, means it is a provider address. We want to control a specific provider with this override url, it may take effect on the specific provider instance or on consumers holding this provider instance.
-        if (configuratorUrl.getPort() != 0) {
-            if (url.getPort() == configuratorUrl.getPort()) {
-                return configureIfMatch(url.getHost(), url);
-            }
-        } else {
-            /*
-             *  override url don't have a port, means the ip override url specify is a consumer address or 0.0.0.0.
-             *  1.If it is a consumer ip address, the intention is to control a specific consumer instance, it must takes effect at the consumer side, any provider received this override url should ignore.
-             *  2.If the ip is 0.0.0.0, this override url can be used on consumer, and also can be used on provider.
-             */
-            if (url.getSide(PROVIDER).equals(CONSUMER)) {
-                // NetUtils.getLocalHost is the ip address consumer registered to registry.
-                return configureIfMatch(NetUtils.getLocalHost(), url);
-            } else if (url.getSide(CONSUMER).equals(PROVIDER)) {
-                // take effect on all providers, so address must be 0.0.0.0, otherwise it won't flow to this if branch
-                return configureIfMatch(ANYHOST_VALUE, url);
-            }
-        }
-        return url;
-    }
-
-    private URL configureIfMatch(String host, URL url) {
-        if (ANYHOST_VALUE.equals(configuratorUrl.getHost()) || host.equals(configuratorUrl.getHost())) {
-            // TODO, to support wildcards
-            String providers = configuratorUrl.getParameter(OVERRIDE_PROVIDERS_KEY);
-            if (StringUtils.isEmpty(providers) || providers.contains(url.getAddress()) || providers.contains(ANYHOST_VALUE)) {
-                String configApplication = configuratorUrl.getApplication(configuratorUrl.getUsername());
-                String currentApplication = url.getApplication(url.getUsername());
-                if (configApplication == null || ANY_VALUE.equals(configApplication)
-                        || configApplication.equals(currentApplication)) {
-                    Set<String> conditionKeys = new HashSet<String>();
-                    conditionKeys.add(CATEGORY_KEY);
-                    conditionKeys.add(Constants.CHECK_KEY);
-                    conditionKeys.add(DYNAMIC_KEY);
-                    conditionKeys.add(ENABLED_KEY);
-                    conditionKeys.add(GROUP_KEY);
-                    conditionKeys.add(VERSION_KEY);
-                    conditionKeys.add(APPLICATION_KEY);
-                    conditionKeys.add(SIDE_KEY);
-                    conditionKeys.add(CONFIG_VERSION_KEY);
-                    conditionKeys.add(COMPATIBLE_CONFIG_KEY);
-                    conditionKeys.add(INTERFACES);
-                    for (Map.Entry<String, String> entry : configuratorUrl.getParameters().entrySet()) {
-                        String key = entry.getKey();
-                        String value = entry.getValue();
-                        boolean startWithTilde = startWithTilde(key);
-                        if (startWithTilde || APPLICATION_KEY.equals(key) || SIDE_KEY.equals(key)) {
-                            if (startWithTilde) {
-                                conditionKeys.add(key);
-                            }
-                            if (value != null && !ANY_VALUE.equals(value)
-                                    && !value.equals(url.getParameter(startWithTilde ? key.substring(1) : key))) {
-                                return url;
-                            }
-                        }
-                    }
-                    return doConfigure(url, configuratorUrl.removeParameters(conditionKeys));
-                }
-            }
-        }
-        return url;
-    }
-
-    private boolean startWithTilde(String key) {
-        if (StringUtils.isNotEmpty(key) && key.startsWith(TILDE)) {
-            return true;
-        }
-        return false;
-    }
-
-    protected abstract URL doConfigure(URL currentUrl, URL configUrl);
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.configurator;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.remoting.Constants;
+import org.apache.dubbo.rpc.cluster.Configurator;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
+import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE;
+import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
+import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.INTERFACES;
+import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER;
+import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
+import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY;
+import static org.apache.dubbo.common.constants.RegistryConstants.COMPATIBLE_CONFIG_KEY;
+import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_KEY;
+import static org.apache.dubbo.rpc.cluster.Constants.CONFIG_VERSION_KEY;
+import static org.apache.dubbo.rpc.cluster.Constants.OVERRIDE_PROVIDERS_KEY;
+
+/**
+ * AbstractOverrideConfigurator
+ */
+public abstract class AbstractConfigurator implements Configurator {
+
+    private static final String TILDE = "~";
+
+    private final URL configuratorUrl;
+
+    public AbstractConfigurator(URL url) {
+        if (url == null) {
+            throw new IllegalArgumentException("configurator url == null");
+        }
+        this.configuratorUrl = url;
+    }
+
+    @Override
+    public URL getUrl() {
+        return configuratorUrl;
+    }
+
+    @Override
+    public URL configure(URL url) {
+        // If override url is not enabled or is invalid, just return.
+        if (!configuratorUrl.getParameter(ENABLED_KEY, true) || configuratorUrl.getHost() == null || url == null || url.getHost() == null) {
+            return url;
+        }
+        /*
+         * This if branch is created since 2.7.0.
+         */
+        String apiVersion = configuratorUrl.getParameter(CONFIG_VERSION_KEY);
+        if (StringUtils.isNotEmpty(apiVersion)) {
+            String currentSide = url.getSide();
+            String configuratorSide = configuratorUrl.getSide();
+            if (currentSide.equals(configuratorSide) && CONSUMER.equals(configuratorSide) && 0 == configuratorUrl.getPort()) {
+                url = configureIfMatch(NetUtils.getLocalHost(), url);
+            } else if (currentSide.equals(configuratorSide) && PROVIDER.equals(configuratorSide) &&
+                    url.getPort() == configuratorUrl.getPort()) {
+                url = configureIfMatch(url.getHost(), url);
+            }
+        }
+        /*
+         * This else branch is deprecated and is left only to keep compatibility with versions before 2.7.0
+         */
+        else {
+            url = configureDeprecated(url);
+        }
+        return url;
+    }
+
+    @Deprecated
+    private URL configureDeprecated(URL url) {
+        // If override url has port, means it is a provider address. We want to control a specific provider with this override url, it may take effect on the specific provider instance or on consumers holding this provider instance.
+        if (configuratorUrl.getPort() != 0) {
+            if (url.getPort() == configuratorUrl.getPort()) {
+                return configureIfMatch(url.getHost(), url);
+            }
+        } else {
+            /*
+             *  override url don't have a port, means the ip override url specify is a consumer address or 0.0.0.0.
+             *  1.If it is a consumer ip address, the intention is to control a specific consumer instance, it must takes effect at the consumer side, any provider received this override url should ignore.
+             *  2.If the ip is 0.0.0.0, this override url can be used on consumer, and also can be used on provider.
+             */
+            if (url.getSide(PROVIDER).equals(CONSUMER)) {
+                // NetUtils.getLocalHost is the ip address consumer registered to registry.
+                return configureIfMatch(NetUtils.getLocalHost(), url);
+            } else if (url.getSide(CONSUMER).equals(PROVIDER)) {
+                // take effect on all providers, so address must be 0.0.0.0, otherwise it won't flow to this if branch
+                return configureIfMatch(ANYHOST_VALUE, url);
+            }
+        }
+        return url;
+    }
+
+    private URL configureIfMatch(String host, URL url) {
+        if (ANYHOST_VALUE.equals(configuratorUrl.getHost()) || host.equals(configuratorUrl.getHost())) {
+            // TODO, to support wildcards
+            String providers = configuratorUrl.getParameter(OVERRIDE_PROVIDERS_KEY);
+            if (StringUtils.isEmpty(providers) || providers.contains(url.getAddress()) || providers.contains(ANYHOST_VALUE)) {
+                String configApplication = configuratorUrl.getApplication(configuratorUrl.getUsername());
+                String currentApplication = url.getApplication(url.getUsername());
+                if (configApplication == null || ANY_VALUE.equals(configApplication)
+                        || configApplication.equals(currentApplication)) {
+                    Set<String> conditionKeys = new HashSet<String>();
+                    conditionKeys.add(CATEGORY_KEY);
+                    conditionKeys.add(Constants.CHECK_KEY);
+                    conditionKeys.add(DYNAMIC_KEY);
+                    conditionKeys.add(ENABLED_KEY);
+                    conditionKeys.add(GROUP_KEY);
+                    conditionKeys.add(VERSION_KEY);
+                    conditionKeys.add(APPLICATION_KEY);
+                    conditionKeys.add(SIDE_KEY);
+                    conditionKeys.add(CONFIG_VERSION_KEY);
+                    conditionKeys.add(COMPATIBLE_CONFIG_KEY);
+                    conditionKeys.add(INTERFACES);
+                    for (Map.Entry<String, String> entry : configuratorUrl.getParameters().entrySet()) {
+                        String key = entry.getKey();
+                        String value = entry.getValue();
+                        boolean startWithTilde = startWithTilde(key);
+                        if (startWithTilde || APPLICATION_KEY.equals(key) || SIDE_KEY.equals(key)) {
+                            if (startWithTilde) {
+                                conditionKeys.add(key);
+                            }
+                            if (value != null && !ANY_VALUE.equals(value)
+                                    && !value.equals(url.getParameter(startWithTilde ? key.substring(1) : key))) {
+                                return url;
+                            }
+                        }
+                    }
+                    return doConfigure(url, configuratorUrl.removeParameters(conditionKeys));
+                }
+            }
+        }
+        return url;
+    }
+
+    private boolean startWithTilde(String key) {
+        if (StringUtils.isNotEmpty(key) && key.startsWith(TILDE)) {
+            return true;
+        }
+        return false;
+    }
+
+    protected abstract URL doConfigure(URL currentUrl, URL configUrl);
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfigurator.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfigurator.java
index c81d9b8..cb83b8b 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfigurator.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfigurator.java
@@ -1,37 +1,37 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.configurator.absent;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.rpc.cluster.configurator.AbstractConfigurator;
-
-/**
- * AbsentConfigurator
- *
- */
-public class AbsentConfigurator extends AbstractConfigurator {
-
-    public AbsentConfigurator(URL url) {
-        super(url);
-    }
-
-    @Override
-    public URL doConfigure(URL currentUrl, URL configUrl) {
-        return currentUrl.addParametersIfAbsent(configUrl.getParameters());
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.configurator.absent;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.cluster.configurator.AbstractConfigurator;
+
+/**
+ * AbsentConfigurator
+ *
+ */
+public class AbsentConfigurator extends AbstractConfigurator {
+
+    public AbsentConfigurator(URL url) {
+        super(url);
+    }
+
+    @Override
+    public URL doConfigure(URL currentUrl, URL configUrl) {
+        return currentUrl.addParametersIfAbsent(configUrl.getParameters());
+    }
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfiguratorFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfiguratorFactory.java
index 86b0e70..479eb50 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfiguratorFactory.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfiguratorFactory.java
@@ -1,34 +1,34 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.configurator.absent;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.rpc.cluster.Configurator;
-import org.apache.dubbo.rpc.cluster.ConfiguratorFactory;
-
-/**
- * AbsentConfiguratorFactory
- *
- */
-public class AbsentConfiguratorFactory implements ConfiguratorFactory {
-
-    @Override
-    public Configurator getConfigurator(URL url) {
-        return new AbsentConfigurator(url);
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.configurator.absent;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.cluster.Configurator;
+import org.apache.dubbo.rpc.cluster.ConfiguratorFactory;
+
+/**
+ * AbsentConfiguratorFactory
+ *
+ */
+public class AbsentConfiguratorFactory implements ConfiguratorFactory {
+
+    @Override
+    public Configurator getConfigurator(URL url) {
+        return new AbsentConfigurator(url);
+    }
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfigurator.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfigurator.java
index bc9beb4..23f0a8d 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfigurator.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfigurator.java
@@ -1,37 +1,37 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.configurator.override;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.rpc.cluster.configurator.AbstractConfigurator;
-
-/**
- * OverrideConfigurator
- *
- */
-public class OverrideConfigurator extends AbstractConfigurator {
-
-    public OverrideConfigurator(URL url) {
-        super(url);
-    }
-
-    @Override
-    public URL doConfigure(URL currentUrl, URL configUrl) {
-        return currentUrl.addParameters(configUrl.getParameters());
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.configurator.override;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.cluster.configurator.AbstractConfigurator;
+
+/**
+ * OverrideConfigurator
+ *
+ */
+public class OverrideConfigurator extends AbstractConfigurator {
+
+    public OverrideConfigurator(URL url) {
+        super(url);
+    }
+
+    @Override
+    public URL doConfigure(URL currentUrl, URL configUrl) {
+        return currentUrl.addParameters(configUrl.getParameters());
+    }
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfiguratorFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfiguratorFactory.java
index a63aa55..504ae3b 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfiguratorFactory.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfiguratorFactory.java
@@ -1,34 +1,34 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.configurator.override;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.rpc.cluster.Configurator;
-import org.apache.dubbo.rpc.cluster.ConfiguratorFactory;
-
-/**
- * OverrideConfiguratorFactory
- *
- */
-public class OverrideConfiguratorFactory implements ConfiguratorFactory {
-
-    @Override
-    public Configurator getConfigurator(URL url) {
-        return new OverrideConfigurator(url);
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.configurator.override;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.cluster.Configurator;
+import org.apache.dubbo.rpc.cluster.ConfiguratorFactory;
+
+/**
+ * OverrideConfiguratorFactory
+ *
+ */
+public class OverrideConfiguratorFactory implements ConfiguratorFactory {
+
+    @Override
+    public Configurator getConfigurator(URL url) {
+        return new OverrideConfigurator(url);
+    }
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectory.java
index 50110aa..2b1a3d7 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectory.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectory.java
@@ -1,114 +1,114 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.directory;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.logger.Logger;
-import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.utils.CollectionUtils;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.cluster.RouterChain;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * StaticDirectory
- */
-public class StaticDirectory<T> extends AbstractDirectory<T> {
-    private static final Logger logger = LoggerFactory.getLogger(StaticDirectory.class);
-
-    private final List<Invoker<T>> invokers;
-
-    public StaticDirectory(List<Invoker<T>> invokers) {
-        this(null, invokers, null);
-    }
-
-    public StaticDirectory(List<Invoker<T>> invokers, RouterChain<T> routerChain) {
-        this(null, invokers, routerChain);
-    }
-
-    public StaticDirectory(URL url, List<Invoker<T>> invokers) {
-        this(url, invokers, null);
-    }
-
-    public StaticDirectory(URL url, List<Invoker<T>> invokers, RouterChain<T> routerChain) {
-        super(url == null && CollectionUtils.isNotEmpty(invokers) ? invokers.get(0).getUrl() : url, routerChain, false);
-        if (CollectionUtils.isEmpty(invokers)) {
-            throw new IllegalArgumentException("invokers == null");
-        }
-        this.invokers = invokers;
-    }
-
-    @Override
-    public Class<T> getInterface() {
-        return invokers.get(0).getInterface();
-    }
-
-    @Override
-    public List<Invoker<T>> getAllInvokers() {
-        return invokers;
-    }
-
-    @Override
-    public boolean isAvailable() {
-        if (isDestroyed()) {
-            return false;
-        }
-        for (Invoker<T> invoker : invokers) {
-            if (invoker.isAvailable()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public void destroy() {
-        if (isDestroyed()) {
-            return;
-        }
-        super.destroy();
-        for (Invoker<T> invoker : invokers) {
-            invoker.destroy();
-        }
-        invokers.clear();
-    }
-
-    public void buildRouterChain() {
-        RouterChain<T> routerChain = RouterChain.buildChain(getUrl());
-        routerChain.setInvokers(invokers);
-        routerChain.loop(true);
-        this.setRouterChain(routerChain);
-    }
-
-    @Override
-    protected List<Invoker<T>> doList(Invocation invocation) throws RpcException {
-        List<Invoker<T>> finalInvokers = invokers;
-        if (routerChain != null) {
-            try {
-                finalInvokers = routerChain.route(getConsumerUrl(), invocation);
-            } catch (Throwable t) {
-                logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t);
-            }
-        }
-        return finalInvokers == null ? Collections.emptyList() : finalInvokers;
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.directory;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.RouterChain;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * StaticDirectory
+ */
+public class StaticDirectory<T> extends AbstractDirectory<T> {
+    private static final Logger logger = LoggerFactory.getLogger(StaticDirectory.class);
+
+    private final List<Invoker<T>> invokers;
+
+    public StaticDirectory(List<Invoker<T>> invokers) {
+        this(null, invokers, null);
+    }
+
+    public StaticDirectory(List<Invoker<T>> invokers, RouterChain<T> routerChain) {
+        this(null, invokers, routerChain);
+    }
+
+    public StaticDirectory(URL url, List<Invoker<T>> invokers) {
+        this(url, invokers, null);
+    }
+
+    public StaticDirectory(URL url, List<Invoker<T>> invokers, RouterChain<T> routerChain) {
+        super(url == null && CollectionUtils.isNotEmpty(invokers) ? invokers.get(0).getUrl() : url, routerChain, false);
+        if (CollectionUtils.isEmpty(invokers)) {
+            throw new IllegalArgumentException("invokers == null");
+        }
+        this.invokers = invokers;
+    }
+
+    @Override
+    public Class<T> getInterface() {
+        return invokers.get(0).getInterface();
+    }
+
+    @Override
+    public List<Invoker<T>> getAllInvokers() {
+        return invokers;
+    }
+
+    @Override
+    public boolean isAvailable() {
+        if (isDestroyed()) {
+            return false;
+        }
+        for (Invoker<T> invoker : invokers) {
+            if (invoker.isAvailable()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public void destroy() {
+        if (isDestroyed()) {
+            return;
+        }
+        super.destroy();
+        for (Invoker<T> invoker : invokers) {
+            invoker.destroy();
+        }
+        invokers.clear();
+    }
+
+    public void buildRouterChain() {
+        RouterChain<T> routerChain = RouterChain.buildChain(getUrl());
+        routerChain.setInvokers(invokers);
+        routerChain.loop(true);
+        this.setRouterChain(routerChain);
+    }
+
+    @Override
+    protected List<Invoker<T>> doList(Invocation invocation) throws RpcException {
+        List<Invoker<T>> finalInvokers = invokers;
+        if (routerChain != null) {
+            try {
+                finalInvokers = routerChain.route(getConsumerUrl(), invocation);
+            } catch (Throwable t) {
+                logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t);
+            }
+        }
+        return finalInvokers == null ? Collections.emptyList() : finalInvokers;
+    }
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/AbstractLoadBalance.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/AbstractLoadBalance.java
index e2c2a6f..31024be 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/AbstractLoadBalance.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/AbstractLoadBalance.java
@@ -1,99 +1,99 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.loadbalance;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.utils.CollectionUtils;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.cluster.LoadBalance;
-
-import java.util.List;
-
-import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY;
-import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_KEY;
-import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_SERVICE_REFERENCE_PATH;
-import static org.apache.dubbo.rpc.cluster.Constants.DEFAULT_WARMUP;
-import static org.apache.dubbo.rpc.cluster.Constants.DEFAULT_WEIGHT;
-import static org.apache.dubbo.rpc.cluster.Constants.WARMUP_KEY;
-import static org.apache.dubbo.rpc.cluster.Constants.WEIGHT_KEY;
-
-/**
- * AbstractLoadBalance
- */
-public abstract class AbstractLoadBalance implements LoadBalance {
-    /**
-     * Calculate the weight according to the uptime proportion of warmup time
-     * the new weight will be within 1(inclusive) to weight(inclusive)
-     *
-     * @param uptime the uptime in milliseconds
-     * @param warmup the warmup time in milliseconds
-     * @param weight the weight of an invoker
-     * @return weight which takes warmup into account
-     */
-    static int calculateWarmupWeight(int uptime, int warmup, int weight) {
-        int ww = (int) ( uptime / ((float) warmup / weight));
-        return ww < 1 ? 1 : (Math.min(ww, weight));
-    }
-
-    @Override
-    public <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) {
-        if (CollectionUtils.isEmpty(invokers)) {
-            return null;
-        }
-        if (invokers.size() == 1) {
-            return invokers.get(0);
-        }
-        return doSelect(invokers, url, 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
-     * if the uptime is within the warmup time, the weight will be reduce proportionally
-     *
-     * @param invoker    the invoker
-     * @param invocation the invocation of this invoker
-     * @return weight
-     */
-    int getWeight(Invoker<?> invoker, Invocation invocation) {
-        int weight;
-        URL url = invoker.getUrl();
-        // Multiple registry scenario, load balance among multiple registries.
-        if (REGISTRY_SERVICE_REFERENCE_PATH.equals(url.getServiceInterface())) {
-            weight = url.getParameter(REGISTRY_KEY + "." + WEIGHT_KEY, DEFAULT_WEIGHT);
-        } else {
-            weight = url.getMethodParameter(invocation.getMethodName(), WEIGHT_KEY, DEFAULT_WEIGHT);
-            if (weight > 0) {
-                long timestamp = invoker.getUrl().getParameter(TIMESTAMP_KEY, 0L);
-                if (timestamp > 0L) {
-                    long uptime = System.currentTimeMillis() - timestamp;
-                    if (uptime < 0) {
-                        return 1;
-                    }
-                    int warmup = invoker.getUrl().getParameter(WARMUP_KEY, DEFAULT_WARMUP);
-                    if (uptime > 0 && uptime < warmup) {
-                        weight = calculateWarmupWeight((int)uptime, warmup, weight);
-                    }
-                }
-            }
-        }
-        return Math.max(weight, 0);
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.loadbalance;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.cluster.LoadBalance;
+
+import java.util.List;
+
+import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY;
+import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_KEY;
+import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_SERVICE_REFERENCE_PATH;
+import static org.apache.dubbo.rpc.cluster.Constants.DEFAULT_WARMUP;
+import static org.apache.dubbo.rpc.cluster.Constants.DEFAULT_WEIGHT;
+import static org.apache.dubbo.rpc.cluster.Constants.WARMUP_KEY;
+import static org.apache.dubbo.rpc.cluster.Constants.WEIGHT_KEY;
+
+/**
+ * AbstractLoadBalance
+ */
+public abstract class AbstractLoadBalance implements LoadBalance {
+    /**
+     * Calculate the weight according to the uptime proportion of warmup time
+     * the new weight will be within 1(inclusive) to weight(inclusive)
+     *
+     * @param uptime the uptime in milliseconds
+     * @param warmup the warmup time in milliseconds
+     * @param weight the weight of an invoker
+     * @return weight which takes warmup into account
+     */
+    static int calculateWarmupWeight(int uptime, int warmup, int weight) {
+        int ww = (int) ( uptime / ((float) warmup / weight));
+        return ww < 1 ? 1 : (Math.min(ww, weight));
+    }
+
+    @Override
+    public <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) {
+        if (CollectionUtils.isEmpty(invokers)) {
+            return null;
+        }
+        if (invokers.size() == 1) {
+            return invokers.get(0);
+        }
+        return doSelect(invokers, url, 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
+     * if the uptime is within the warmup time, the weight will be reduce proportionally
+     *
+     * @param invoker    the invoker
+     * @param invocation the invocation of this invoker
+     * @return weight
+     */
+    int getWeight(Invoker<?> invoker, Invocation invocation) {
+        int weight;
+        URL url = invoker.getUrl();
+        // Multiple registry scenario, load balance among multiple registries.
+        if (REGISTRY_SERVICE_REFERENCE_PATH.equals(url.getServiceInterface())) {
+            weight = url.getParameter(REGISTRY_KEY + "." + WEIGHT_KEY, DEFAULT_WEIGHT);
+        } else {
+            weight = url.getMethodParameter(invocation.getMethodName(), WEIGHT_KEY, DEFAULT_WEIGHT);
+            if (weight > 0) {
+                long timestamp = invoker.getUrl().getParameter(TIMESTAMP_KEY, 0L);
+                if (timestamp > 0L) {
+                    long uptime = System.currentTimeMillis() - timestamp;
+                    if (uptime < 0) {
+                        return 1;
+                    }
+                    int warmup = invoker.getUrl().getParameter(WARMUP_KEY, DEFAULT_WARMUP);
+                    if (uptime > 0 && uptime < warmup) {
+                        weight = calculateWarmupWeight((int)uptime, warmup, weight);
+                    }
+                }
+            }
+        }
+        return Math.max(weight, 0);
+    }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalance.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalance.java
index 4f5859d..15c7066 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalance.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalance.java
@@ -1,131 +1,131 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.loadbalance;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.io.Bytes;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.support.RpcUtils;
-
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
-
-/**
- * ConsistentHashLoadBalance
- */
-public class ConsistentHashLoadBalance extends AbstractLoadBalance {
-    public static final String NAME = "consistenthash";
-
-    /**
-     * Hash nodes name
-     */
-    public static final String HASH_NODES = "hash.nodes";
-
-    /**
-     * Hash arguments name
-     */
-    public static final String HASH_ARGUMENTS = "hash.arguments";
-
-    private final ConcurrentMap<String, ConsistentHashSelector<?>> selectors = new ConcurrentHashMap<String, ConsistentHashSelector<?>>();
-
-    @SuppressWarnings("unchecked")
-    @Override
-    protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
-        String methodName = RpcUtils.getMethodName(invocation);
-        String key = invokers.get(0).getUrl().getServiceKey() + "." + methodName;
-        // using the hashcode of list to compute the hash only pay attention to the elements in the list
-        int invokersHashCode = invokers.hashCode();
-        ConsistentHashSelector<T> selector = (ConsistentHashSelector<T>) selectors.get(key);
-        if (selector == null || selector.identityHashCode != invokersHashCode) {
-            selectors.put(key, new ConsistentHashSelector<T>(invokers, methodName, invokersHashCode));
-            selector = (ConsistentHashSelector<T>) selectors.get(key);
-        }
-        return selector.select(invocation);
-    }
-
-    private static final class ConsistentHashSelector<T> {
-
-        private final TreeMap<Long, Invoker<T>> virtualInvokers;
-
-        private final int replicaNumber;
-
-        private final int identityHashCode;
-
-        private final int[] argumentIndex;
-
-        ConsistentHashSelector(List<Invoker<T>> invokers, String methodName, int identityHashCode) {
-            this.virtualInvokers = new TreeMap<Long, Invoker<T>>();
-            this.identityHashCode = identityHashCode;
-            URL url = invokers.get(0).getUrl();
-            this.replicaNumber = url.getMethodParameter(methodName, HASH_NODES, 160);
-            String[] index = COMMA_SPLIT_PATTERN.split(url.getMethodParameter(methodName, HASH_ARGUMENTS, "0"));
-            argumentIndex = new int[index.length];
-            for (int i = 0; i < index.length; i++) {
-                argumentIndex[i] = Integer.parseInt(index[i]);
-            }
-            for (Invoker<T> invoker : invokers) {
-                String address = invoker.getUrl().getAddress();
-                for (int i = 0; i < replicaNumber / 4; i++) {
-                    byte[] digest = Bytes.getMD5(address + i);
-                    for (int h = 0; h < 4; h++) {
-                        long m = hash(digest, h);
-                        virtualInvokers.put(m, invoker);
-                    }
-                }
-            }
-        }
-
-        public Invoker<T> select(Invocation invocation) {
-            String key = toKey(invocation.getArguments());
-            byte[] digest = Bytes.getMD5(key);
-            return selectForKey(hash(digest, 0));
-        }
-
-        private String toKey(Object[] args) {
-            StringBuilder buf = new StringBuilder();
-            for (int i : argumentIndex) {
-                if (i >= 0 && i < args.length) {
-                    buf.append(args[i]);
-                }
-            }
-            return buf.toString();
-        }
-
-        private Invoker<T> selectForKey(long hash) {
-            Map.Entry<Long, Invoker<T>> entry = virtualInvokers.ceilingEntry(hash);
-            if (entry == null) {
-                entry = virtualInvokers.firstEntry();
-            }
-            return entry.getValue();
-        }
-
-        private long hash(byte[] digest, int number) {
-            return (((long) (digest[3 + number * 4] & 0xFF) << 24)
-                    | ((long) (digest[2 + number * 4] & 0xFF) << 16)
-                    | ((long) (digest[1 + number * 4] & 0xFF) << 8)
-                    | (digest[number * 4] & 0xFF))
-                    & 0xFFFFFFFFL;
-        }
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.loadbalance;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.io.Bytes;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.support.RpcUtils;
+
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
+
+/**
+ * ConsistentHashLoadBalance
+ */
+public class ConsistentHashLoadBalance extends AbstractLoadBalance {
+    public static final String NAME = "consistenthash";
+
+    /**
+     * Hash nodes name
+     */
+    public static final String HASH_NODES = "hash.nodes";
+
+    /**
+     * Hash arguments name
+     */
+    public static final String HASH_ARGUMENTS = "hash.arguments";
+
+    private final ConcurrentMap<String, ConsistentHashSelector<?>> selectors = new ConcurrentHashMap<String, ConsistentHashSelector<?>>();
+
+    @SuppressWarnings("unchecked")
+    @Override
+    protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
+        String methodName = RpcUtils.getMethodName(invocation);
+        String key = invokers.get(0).getUrl().getServiceKey() + "." + methodName;
+        // using the hashcode of list to compute the hash only pay attention to the elements in the list
+        int invokersHashCode = invokers.hashCode();
+        ConsistentHashSelector<T> selector = (ConsistentHashSelector<T>) selectors.get(key);
+        if (selector == null || selector.identityHashCode != invokersHashCode) {
+            selectors.put(key, new ConsistentHashSelector<T>(invokers, methodName, invokersHashCode));
+            selector = (ConsistentHashSelector<T>) selectors.get(key);
+        }
+        return selector.select(invocation);
+    }
+
+    private static final class ConsistentHashSelector<T> {
+
+        private final TreeMap<Long, Invoker<T>> virtualInvokers;
+
+        private final int replicaNumber;
+
+        private final int identityHashCode;
+
+        private final int[] argumentIndex;
+
+        ConsistentHashSelector(List<Invoker<T>> invokers, String methodName, int identityHashCode) {
+            this.virtualInvokers = new TreeMap<Long, Invoker<T>>();
+            this.identityHashCode = identityHashCode;
+            URL url = invokers.get(0).getUrl();
+            this.replicaNumber = url.getMethodParameter(methodName, HASH_NODES, 160);
+            String[] index = COMMA_SPLIT_PATTERN.split(url.getMethodParameter(methodName, HASH_ARGUMENTS, "0"));
+            argumentIndex = new int[index.length];
+            for (int i = 0; i < index.length; i++) {
+                argumentIndex[i] = Integer.parseInt(index[i]);
+            }
+            for (Invoker<T> invoker : invokers) {
+                String address = invoker.getUrl().getAddress();
+                for (int i = 0; i < replicaNumber / 4; i++) {
+                    byte[] digest = Bytes.getMD5(address + i);
+                    for (int h = 0; h < 4; h++) {
+                        long m = hash(digest, h);
+                        virtualInvokers.put(m, invoker);
+                    }
+                }
+            }
+        }
+
+        public Invoker<T> select(Invocation invocation) {
+            String key = toKey(invocation.getArguments());
+            byte[] digest = Bytes.getMD5(key);
+            return selectForKey(hash(digest, 0));
+        }
+
+        private String toKey(Object[] args) {
+            StringBuilder buf = new StringBuilder();
+            for (int i : argumentIndex) {
+                if (i >= 0 && i < args.length) {
+                    buf.append(args[i]);
+                }
+            }
+            return buf.toString();
+        }
+
+        private Invoker<T> selectForKey(long hash) {
+            Map.Entry<Long, Invoker<T>> entry = virtualInvokers.ceilingEntry(hash);
+            if (entry == null) {
+                entry = virtualInvokers.firstEntry();
+            }
+            return entry.getValue();
+        }
+
+        private long hash(byte[] digest, int number) {
+            return (((long) (digest[3 + number * 4] & 0xFF) << 24)
+                    | ((long) (digest[2 + number * 4] & 0xFF) << 16)
+                    | ((long) (digest[1 + number * 4] & 0xFF) << 8)
+                    | (digest[number * 4] & 0xFF))
+                    & 0xFFFFFFFFL;
+        }
+    }
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java
index 6b1ac64..41c1bab 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/LeastActiveLoadBalance.java
@@ -1,115 +1,115 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.loadbalance;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.RpcStatus;
-
-import java.util.List;
-import java.util.concurrent.ThreadLocalRandom;
-
-/**
- * LeastActiveLoadBalance
- * <p>
- * Filter the number of invokers with the least number of active calls and count the weights and quantities of these invokers.
- * If there is only one invoker, use the invoker directly;
- * if there are multiple invokers and the weights are not the same, then random according to the total weight;
- * if there are multiple invokers and the same weight, then randomly called.
- */
-public class LeastActiveLoadBalance extends AbstractLoadBalance {
-
-    public static final String NAME = "leastactive";
-
-    @Override
-    protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
-        // Number of invokers
-        int length = invokers.size();
-        // The least active value of all invokers
-        int leastActive = -1;
-        // The number of invokers having the same least active value (leastActive)
-        int leastCount = 0;
-        // The index of invokers having the same least active value (leastActive)
-        int[] leastIndexes = new int[length];
-        // the weight of every invokers
-        int[] weights = new int[length];
-        // The sum of the warmup weights of all the least active invokers
-        int totalWeight = 0;
-        // The weight of the first least active invoker
-        int firstWeight = 0;
-        // Every least active invoker has the same weight value?
-        boolean sameWeight = true;
-
-
-        // Filter out all the least active invokers
-        for (int i = 0; i < length; i++) {
-            Invoker<T> invoker = invokers.get(i);
-            // Get the active number of the invoker
-            int active = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName()).getActive();
-            // Get the weight of the invoker's configuration. The default value is 100.
-            int afterWarmup = getWeight(invoker, invocation);
-            // save for later use
-            weights[i] = afterWarmup;
-            // If it is the first invoker or the active number of the invoker is less than the current least active number
-            if (leastActive == -1 || active < leastActive) {
-                // Reset the active number of the current invoker to the least active number
-                leastActive = active;
-                // Reset the number of least active invokers
-                leastCount = 1;
-                // Put the first least active invoker first in leastIndexes
-                leastIndexes[0] = i;
-                // Reset totalWeight
-                totalWeight = afterWarmup;
-                // Record the weight the first least active invoker
-                firstWeight = afterWarmup;
-                // Each invoke has the same weight (only one invoker here)
-                sameWeight = true;
-                // If current invoker's active value equals with leaseActive, then accumulating.
-            } else if (active == leastActive) {
-                // Record the index of the least active invoker in leastIndexes order
-                leastIndexes[leastCount++] = i;
-                // Accumulate the total weight of the least active invoker
-                totalWeight += afterWarmup;
-                // If every invoker has the same weight?
-                if (sameWeight && afterWarmup != firstWeight) {
-                    sameWeight = false;
-                }
-            }
-        }
-        // Choose an invoker from all the least active invokers
-        if (leastCount == 1) {
-            // If we got exactly one invoker having the least active value, return this invoker directly.
-            return invokers.get(leastIndexes[0]);
-        }
-        if (!sameWeight && totalWeight > 0) {
-            // If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on 
-            // totalWeight.
-            int offsetWeight = ThreadLocalRandom.current().nextInt(totalWeight);
-            // Return a invoker based on the random value.
-            for (int i = 0; i < leastCount; i++) {
-                int leastIndex = leastIndexes[i];
-                offsetWeight -= weights[leastIndex];
-                if (offsetWeight < 0) {
-                    return invokers.get(leastIndex);
-                }
-            }
-        }
-        // If all invokers have the same weight value or totalWeight=0, return evenly.
-        return invokers.get(leastIndexes[ThreadLocalRandom.current().nextInt(leastCount)]);
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.loadbalance;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.RpcStatus;
+
+import java.util.List;
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * LeastActiveLoadBalance
+ * <p>
+ * Filter the number of invokers with the least number of active calls and count the weights and quantities of these invokers.
+ * If there is only one invoker, use the invoker directly;
+ * if there are multiple invokers and the weights are not the same, then random according to the total weight;
+ * if there are multiple invokers and the same weight, then randomly called.
+ */
+public class LeastActiveLoadBalance extends AbstractLoadBalance {
+
+    public static final String NAME = "leastactive";
+
+    @Override
+    protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
+        // Number of invokers
+        int length = invokers.size();
+        // The least active value of all invokers
+        int leastActive = -1;
+        // The number of invokers having the same least active value (leastActive)
+        int leastCount = 0;
+        // The index of invokers having the same least active value (leastActive)
+        int[] leastIndexes = new int[length];
+        // the weight of every invokers
+        int[] weights = new int[length];
+        // The sum of the warmup weights of all the least active invokers
+        int totalWeight = 0;
+        // The weight of the first least active invoker
+        int firstWeight = 0;
+        // Every least active invoker has the same weight value?
+        boolean sameWeight = true;
+
+
+        // Filter out all the least active invokers
+        for (int i = 0; i < length; i++) {
+            Invoker<T> invoker = invokers.get(i);
+            // Get the active number of the invoker
+            int active = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName()).getActive();
+            // Get the weight of the invoker's configuration. The default value is 100.
+            int afterWarmup = getWeight(invoker, invocation);
+            // save for later use
+            weights[i] = afterWarmup;
+            // If it is the first invoker or the active number of the invoker is less than the current least active number
+            if (leastActive == -1 || active < leastActive) {
+                // Reset the active number of the current invoker to the least active number
+                leastActive = active;
+                // Reset the number of least active invokers
+                leastCount = 1;
+                // Put the first least active invoker first in leastIndexes
+                leastIndexes[0] = i;
+                // Reset totalWeight
+                totalWeight = afterWarmup;
+                // Record the weight the first least active invoker
+                firstWeight = afterWarmup;
+                // Each invoke has the same weight (only one invoker here)
+                sameWeight = true;
+                // If current invoker's active value equals with leaseActive, then accumulating.
+            } else if (active == leastActive) {
+                // Record the index of the least active invoker in leastIndexes order
+                leastIndexes[leastCount++] = i;
+                // Accumulate the total weight of the least active invoker
+                totalWeight += afterWarmup;
+                // If every invoker has the same weight?
+                if (sameWeight && afterWarmup != firstWeight) {
+                    sameWeight = false;
+                }
+            }
+        }
+        // Choose an invoker from all the least active invokers
+        if (leastCount == 1) {
+            // If we got exactly one invoker having the least active value, return this invoker directly.
+            return invokers.get(leastIndexes[0]);
+        }
+        if (!sameWeight && totalWeight > 0) {
+            // If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on 
+            // totalWeight.
+            int offsetWeight = ThreadLocalRandom.current().nextInt(totalWeight);
+            // Return a invoker based on the random value.
+            for (int i = 0; i < leastCount; i++) {
+                int leastIndex = leastIndexes[i];
+                offsetWeight -= weights[leastIndex];
+                if (offsetWeight < 0) {
+                    return invokers.get(leastIndex);
+                }
+            }
+        }
+        // If all invokers have the same weight value or totalWeight=0, return evenly.
+        return invokers.get(leastIndexes[ThreadLocalRandom.current().nextInt(leastCount)]);
+    }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalance.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalance.java
index ddb87fb..b3e5adb 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalance.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalance.java
@@ -1,131 +1,131 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.loadbalance;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * Round robin load balance.
- */
-public class RoundRobinLoadBalance extends AbstractLoadBalance {
-    public static final String NAME = "roundrobin";
-
-    private static final int RECYCLE_PERIOD = 60000;
-
-    protected static class WeightedRoundRobin {
-        private int weight;
-        private AtomicLong current = new AtomicLong(0);
-        private long lastUpdate;
-
-        public int getWeight() {
-            return weight;
-        }
-
-        public void setWeight(int weight) {
-            this.weight = weight;
-            current.set(0);
-        }
-
-        public long increaseCurrent() {
-            return current.addAndGet(weight);
-        }
-
-        public void sel(int total) {
-            current.addAndGet(-1 * total);
-        }
-
-        public long getLastUpdate() {
-            return lastUpdate;
-        }
-
-        public void setLastUpdate(long lastUpdate) {
-            this.lastUpdate = lastUpdate;
-        }
-    }
-
-    private ConcurrentMap<String, ConcurrentMap<String, WeightedRoundRobin>> methodWeightMap = new ConcurrentHashMap<String, ConcurrentMap<String, WeightedRoundRobin>>();
-
-    /**
-     * get invoker addr list cached for specified invocation
-     * <p>
-     * <b>for unit test only</b>
-     *
-     * @param invokers
-     * @param invocation
-     * @return
-     */
-    protected <T> Collection<String> getInvokerAddrList(List<Invoker<T>> invokers, Invocation invocation) {
-        String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName();
-        Map<String, WeightedRoundRobin> map = methodWeightMap.get(key);
-        if (map != null) {
-            return map.keySet();
-        }
-        return null;
-    }
-
-    @Override
-    protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
-        String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName();
-        ConcurrentMap<String, WeightedRoundRobin> map = methodWeightMap.computeIfAbsent(key, k -> new ConcurrentHashMap<>());
-        int totalWeight = 0;
-        long maxCurrent = Long.MIN_VALUE;
-        long now = System.currentTimeMillis();
-        Invoker<T> selectedInvoker = null;
-        WeightedRoundRobin selectedWRR = null;
-        for (Invoker<T> invoker : invokers) {
-            String identifyString = invoker.getUrl().toIdentityString();
-            int weight = getWeight(invoker, invocation);
-            WeightedRoundRobin weightedRoundRobin = map.computeIfAbsent(identifyString, k -> {
-                WeightedRoundRobin wrr = new WeightedRoundRobin();
-                wrr.setWeight(weight);
-                return wrr;
-            });
-
-            if (weight != weightedRoundRobin.getWeight()) {
-                //weight changed
-                weightedRoundRobin.setWeight(weight);
-            }
-            long cur = weightedRoundRobin.increaseCurrent();
-            weightedRoundRobin.setLastUpdate(now);
-            if (cur > maxCurrent) {
-                maxCurrent = cur;
-                selectedInvoker = invoker;
-                selectedWRR = weightedRoundRobin;
-            }
-            totalWeight += weight;
-        }
-        if (invokers.size() != map.size()) {
-            map.entrySet().removeIf(item -> now - item.getValue().getLastUpdate() > RECYCLE_PERIOD);
-        }
-        if (selectedInvoker != null) {
-            selectedWRR.sel(totalWeight);
-            return selectedInvoker;
-        }
-        // should not happen here
-        return invokers.get(0);
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.loadbalance;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * Round robin load balance.
+ */
+public class RoundRobinLoadBalance extends AbstractLoadBalance {
+    public static final String NAME = "roundrobin";
+
+    private static final int RECYCLE_PERIOD = 60000;
+
+    protected static class WeightedRoundRobin {
+        private int weight;
+        private AtomicLong current = new AtomicLong(0);
+        private long lastUpdate;
+
+        public int getWeight() {
+            return weight;
+        }
+
+        public void setWeight(int weight) {
+            this.weight = weight;
+            current.set(0);
+        }
+
+        public long increaseCurrent() {
+            return current.addAndGet(weight);
+        }
+
+        public void sel(int total) {
+            current.addAndGet(-1 * total);
+        }
+
+        public long getLastUpdate() {
+            return lastUpdate;
+        }
+
+        public void setLastUpdate(long lastUpdate) {
+            this.lastUpdate = lastUpdate;
+        }
+    }
+
+    private ConcurrentMap<String, ConcurrentMap<String, WeightedRoundRobin>> methodWeightMap = new ConcurrentHashMap<String, ConcurrentMap<String, WeightedRoundRobin>>();
+
+    /**
+     * get invoker addr list cached for specified invocation
+     * <p>
+     * <b>for unit test only</b>
+     *
+     * @param invokers
+     * @param invocation
+     * @return
+     */
+    protected <T> Collection<String> getInvokerAddrList(List<Invoker<T>> invokers, Invocation invocation) {
+        String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName();
+        Map<String, WeightedRoundRobin> map = methodWeightMap.get(key);
+        if (map != null) {
+            return map.keySet();
+        }
+        return null;
+    }
+
+    @Override
+    protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
+        String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName();
+        ConcurrentMap<String, WeightedRoundRobin> map = methodWeightMap.computeIfAbsent(key, k -> new ConcurrentHashMap<>());
+        int totalWeight = 0;
+        long maxCurrent = Long.MIN_VALUE;
+        long now = System.currentTimeMillis();
+        Invoker<T> selectedInvoker = null;
+        WeightedRoundRobin selectedWRR = null;
+        for (Invoker<T> invoker : invokers) {
+            String identifyString = invoker.getUrl().toIdentityString();
+            int weight = getWeight(invoker, invocation);
+            WeightedRoundRobin weightedRoundRobin = map.computeIfAbsent(identifyString, k -> {
+                WeightedRoundRobin wrr = new WeightedRoundRobin();
+                wrr.setWeight(weight);
+                return wrr;
+            });
+
+            if (weight != weightedRoundRobin.getWeight()) {
+                //weight changed
+                weightedRoundRobin.setWeight(weight);
+            }
+            long cur = weightedRoundRobin.increaseCurrent();
+            weightedRoundRobin.setLastUpdate(now);
+            if (cur > maxCurrent) {
+                maxCurrent = cur;
+                selectedInvoker = invoker;
+                selectedWRR = weightedRoundRobin;
+            }
+            totalWeight += weight;
+        }
+        if (invokers.size() != map.size()) {
+            map.entrySet().removeIf(item -> now - item.getValue().getLastUpdate() > RECYCLE_PERIOD);
+        }
+        if (selectedInvoker != null) {
+            selectedWRR.sel(totalWeight);
+            return selectedInvoker;
+        }
+        // should not happen here
+        return invokers.get(0);
+    }
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java
index f6cfec2..8a35645 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java
@@ -1,360 +1,360 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.router.condition;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.logger.Logger;
-import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.utils.CollectionUtils;
-import org.apache.dubbo.common.utils.NetUtils;
-import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.common.utils.UrlUtils;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.cluster.Constants;
-import org.apache.dubbo.rpc.cluster.router.AbstractRouter;
-
-import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.HOST_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.METHOD_KEY;
-import static org.apache.dubbo.rpc.cluster.Constants.ADDRESS_KEY;
-import static org.apache.dubbo.rpc.cluster.Constants.FORCE_KEY;
-import static org.apache.dubbo.rpc.cluster.Constants.PRIORITY_KEY;
-import static org.apache.dubbo.rpc.cluster.Constants.RULE_KEY;
-import static org.apache.dubbo.rpc.cluster.Constants.RUNTIME_KEY;
-
-/**
- * ConditionRouter
- * It supports the conditional routing configured by "override://", in 2.6.x,
- * refer to https://dubbo.apache.org/en/docs/v2.7/user/examples/routing-rule/ .
- * For 2.7.x and later, please refer to {@link org.apache.dubbo.rpc.cluster.router.condition.config.ServiceRouter}
- * and {@link org.apache.dubbo.rpc.cluster.router.condition.config.AppRouter}
- * refer to https://dubbo.apache.org/zh/docs/v2.7/user/examples/routing-rule/ .
- */
-public class ConditionRouter extends AbstractRouter {
-    public static final String NAME = "condition";
-
-    private static final Logger logger = LoggerFactory.getLogger(ConditionRouter.class);
-    protected static final Pattern ROUTE_PATTERN = Pattern.compile("([&!=,]*)\\s*([^&!=,\\s]+)");
-    protected static Pattern ARGUMENTS_PATTERN = Pattern.compile("arguments\\[([0-9]+)\\]");
-    protected Map<String, MatchPair> whenCondition;
-    protected Map<String, MatchPair> thenCondition;
-
-    private boolean enabled;
-
-    public ConditionRouter(String rule, boolean force, boolean enabled) {
-        this.force = force;
-        this.enabled = enabled;
-        if (enabled) {
-            this.init(rule);
-        }
-    }
-
-    public ConditionRouter(URL url) {
-        this.url = url;
-        this.priority = url.getParameter(PRIORITY_KEY, 0);
-        this.force = url.getParameter(FORCE_KEY, false);
-        this.enabled = url.getParameter(ENABLED_KEY, true);
-        if (enabled) {
-            init(url.getParameterAndDecoded(RULE_KEY));
-        }
-    }
-
-    public void init(String rule) {
-        try {
-            if (rule == null || rule.trim().length() == 0) {
-                throw new IllegalArgumentException("Illegal route rule!");
-            }
-            rule = rule.replace("consumer.", "").replace("provider.", "");
-            int i = rule.indexOf("=>");
-            String whenRule = i < 0 ? null : rule.substring(0, i).trim();
-            String thenRule = i < 0 ? rule.trim() : rule.substring(i + 2).trim();
-            Map<String, MatchPair> when = StringUtils.isBlank(whenRule) || "true".equals(whenRule) ? new HashMap<String, MatchPair>() : parseRule(whenRule);
-            Map<String, MatchPair> 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.
-            this.whenCondition = when;
-            this.thenCondition = then;
-        } catch (ParseException e) {
-            throw new IllegalStateException(e.getMessage(), e);
-        }
-    }
-
-    private static Map<String, MatchPair> parseRule(String rule)
-            throws ParseException {
-        Map<String, MatchPair> condition = new HashMap<String, MatchPair>();
-        if (StringUtils.isBlank(rule)) {
-            return condition;
-        }
-        // Key-Value pair, stores both match and mismatch conditions
-        MatchPair pair = null;
-        // Multiple values
-        Set<String> values = null;
-        final Matcher matcher = ROUTE_PATTERN.matcher(rule);
-        while (matcher.find()) { // Try to match one by one
-            String separator = matcher.group(1);
-            String content = matcher.group(2);
-            // Start part of the condition expression.
-            if (StringUtils.isEmpty(separator)) {
-                pair = new MatchPair();
-                condition.put(content, pair);
-            }
-            // The KV part of the condition expression
-            else if ("&".equals(separator)) {
-                if (condition.get(content) == null) {
-                    pair = new MatchPair();
-                    condition.put(content, pair);
-                } else {
-                    pair = condition.get(content);
-                }
-            }
-            // The Value in the KV part.
-            else if ("=".equals(separator)) {
-                if (pair == null) {
-                    throw new ParseException("Illegal route rule \""
-                            + rule + "\", The error char '" + separator
-                            + "' at index " + matcher.start() + " before \""
-                            + content + "\".", matcher.start());
-                }
-
-                values = pair.matches;
-                values.add(content);
-            }
-            // The Value in the KV part.
-            else if ("!=".equals(separator)) {
-                if (pair == null) {
-                    throw new ParseException("Illegal route rule \""
-                            + rule + "\", The error char '" + separator
-                            + "' at index " + matcher.start() + " before \""
-                            + content + "\".", matcher.start());
-                }
-
-                values = pair.mismatches;
-                values.add(content);
-            }
-            // The Value in the KV part, if Value have more than one items.
-            else if (",".equals(separator)) { // Should be separated by ','
-                if (values == null || values.isEmpty()) {
-                    throw new ParseException("Illegal route rule \""
-                            + rule + "\", The error char '" + separator
-                            + "' at index " + matcher.start() + " before \""
-                            + content + "\".", matcher.start());
-                }
-                values.add(content);
-            } else {
-                throw new ParseException("Illegal route rule \"" + rule
-                        + "\", The error char '" + separator + "' at index "
-                        + matcher.start() + " before \"" + content + "\".", matcher.start());
-            }
-        }
-        return condition;
-    }
-
-    @Override
-    public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation)
-            throws RpcException {
-        if (!enabled) {
-            return invokers;
-        }
-
-        if (CollectionUtils.isEmpty(invokers)) {
-            return invokers;
-        }
-        try {
-            if (!matchWhen(url, invocation)) {
-                return invokers;
-            }
-            List<Invoker<T>> result = new ArrayList<Invoker<T>>();
-            if (thenCondition == null) {
-                logger.warn("The current consumer in the service blacklist. consumer: " + NetUtils.getLocalHost() + ", service: " + url.getServiceKey());
-                return result;
-            }
-            for (Invoker<T> invoker : invokers) {
-                if (matchThen(invoker.getUrl(), url)) {
-                    result.add(invoker);
-                }
-            }
-            if (!result.isEmpty()) {
-                return result;
-            } else if (force) {
-                logger.warn("The route result is empty and force execute. consumer: " + NetUtils.getLocalHost() + ", service: " + url.getServiceKey() + ", router: " + url.getParameterAndDecoded(RULE_KEY));
-                return result;
-            }
-        } catch (Throwable t) {
-            logger.error("Failed to execute condition router rule: " + getUrl() + ", invokers: " + invokers + ", cause: " + t.getMessage(), t);
-        }
-        return invokers;
-    }
-
-    @Override
-    public boolean isRuntime() {
-        // We always return true for previously defined Router, that is, old Router doesn't support cache anymore.
-//        return true;
-        return this.url.getParameter(RUNTIME_KEY, false);
-    }
-
-    @Override
-    public URL getUrl() {
-        return url;
-    }
-
-    boolean matchWhen(URL url, Invocation invocation) {
-        return CollectionUtils.isEmptyMap(whenCondition) || matchCondition(whenCondition, url, null, invocation);
-    }
-
-    private boolean matchThen(URL url, URL param) {
-        return CollectionUtils.isNotEmptyMap(thenCondition) && matchCondition(thenCondition, url, param, null);
-    }
-
-    private boolean matchCondition(Map<String, MatchPair> condition, URL url, URL param, Invocation invocation) {
-        Map<String, String> sample = url.toMap();
-        boolean result = false;
-        for (Map.Entry<String, MatchPair> matchPair : condition.entrySet()) {
-            String key = matchPair.getKey();
-
-            if (key.startsWith(Constants.ARGUMENTS)) {
-                if (!matchArguments(matchPair, invocation)) {
-                    return false;
-                } else {
-                    result = true;
-                    continue;
-                }
-            }
-
-            String sampleValue;
-            //get real invoked method name from invocation
-            if (invocation != null && (METHOD_KEY.equals(key) || METHODS_KEY.equals(key))) {
-                sampleValue = invocation.getMethodName();
-            } else if (ADDRESS_KEY.equals(key)) {
-                sampleValue = url.getAddress();
-            } else if (HOST_KEY.equals(key)) {
-                sampleValue = url.getHost();
-            } else {
-                sampleValue = sample.get(key);
-                if (sampleValue == null) {
-                    sampleValue = sample.get(key);
-                }
-            }
-            if (sampleValue != null) {
-                if (!matchPair.getValue().isMatch(sampleValue, param)) {
-                    return false;
-                } else {
-                    result = true;
-                }
-            } else {
-                //not pass the condition
-                if (!matchPair.getValue().matches.isEmpty()) {
-                    return false;
-                } else {
-                    result = true;
-                }
-            }
-        }
-        return result;
-    }
-
-    /**
-     * analysis the arguments in the rule.
-     * Examples would be like this:
-     * "arguments[0]=1", whenCondition is that the first argument is equal to '1'.
-     * "arguments[1]=a", whenCondition is that the second argument is equal to 'a'.
-     * @param matchPair
-     * @param invocation
-     * @return
-     */
-    public boolean matchArguments(Map.Entry<String, MatchPair> matchPair, Invocation invocation) {
-        try {
-            // split the rule
-            String key = matchPair.getKey();
-            String[] expressArray = key.split("\\.");
-            String argumentExpress = expressArray[0];
-            final Matcher matcher = ARGUMENTS_PATTERN.matcher(argumentExpress);
-            if (!matcher.find()) {
-                return false;
-            }
-
-            //extract the argument index
-            int index = Integer.parseInt(matcher.group(1));
-            if (index < 0 || index > invocation.getArguments().length) {
-                return false;
-            }
-
-            //extract the argument value
-            Object object = invocation.getArguments()[index];
-
-            if (matchPair.getValue().isMatch(String.valueOf(object), null)) {
-                return true;
-            }
-        } catch (Exception e) {
-            logger.warn("Arguments match failed, matchPair[]" + matchPair + "] invocation[" + invocation + "]", e);
-        }
-
-        return false;
-    }
-
-    protected static final class MatchPair {
-        final Set<String> matches = new HashSet<String>();
-        final Set<String> mismatches = new HashSet<String>();
-
-        private boolean isMatch(String value, URL param) {
-            if (!matches.isEmpty() && mismatches.isEmpty()) {
-                for (String match : matches) {
-                    if (UrlUtils.isMatchGlobPattern(match, value, param)) {
-                        return true;
-                    }
-                }
-                return false;
-            }
-
-            if (!mismatches.isEmpty() && matches.isEmpty()) {
-                for (String mismatch : mismatches) {
-                    if (UrlUtils.isMatchGlobPattern(mismatch, value, param)) {
-                        return false;
-                    }
-                }
-                return true;
-            }
-
-            if (!matches.isEmpty() && !mismatches.isEmpty()) {
-                //when both mismatches and matches contain the same value, then using mismatches first
-                for (String mismatch : mismatches) {
-                    if (UrlUtils.isMatchGlobPattern(mismatch, value, param)) {
-                        return false;
-                    }
-                }
-                for (String match : matches) {
-                    if (UrlUtils.isMatchGlobPattern(match, value, param)) {
-                        return true;
-                    }
-                }
-                return false;
-            }
-            return false;
-        }
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.router.condition;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.common.utils.UrlUtils;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.Constants;
+import org.apache.dubbo.rpc.cluster.router.AbstractRouter;
+
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.HOST_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.METHOD_KEY;
+import static org.apache.dubbo.rpc.cluster.Constants.ADDRESS_KEY;
+import static org.apache.dubbo.rpc.cluster.Constants.FORCE_KEY;
+import static org.apache.dubbo.rpc.cluster.Constants.PRIORITY_KEY;
+import static org.apache.dubbo.rpc.cluster.Constants.RULE_KEY;
+import static org.apache.dubbo.rpc.cluster.Constants.RUNTIME_KEY;
+
+/**
+ * ConditionRouter
+ * It supports the conditional routing configured by "override://", in 2.6.x,
+ * refer to https://dubbo.apache.org/en/docs/v2.7/user/examples/routing-rule/ .
+ * For 2.7.x and later, please refer to {@link org.apache.dubbo.rpc.cluster.router.condition.config.ServiceRouter}
+ * and {@link org.apache.dubbo.rpc.cluster.router.condition.config.AppRouter}
+ * refer to https://dubbo.apache.org/zh/docs/v2.7/user/examples/routing-rule/ .
+ */
+public class ConditionRouter extends AbstractRouter {
+    public static final String NAME = "condition";
+
+    private static final Logger logger = LoggerFactory.getLogger(ConditionRouter.class);
+    protected static final Pattern ROUTE_PATTERN = Pattern.compile("([&!=,]*)\\s*([^&!=,\\s]+)");
+    protected static Pattern ARGUMENTS_PATTERN = Pattern.compile("arguments\\[([0-9]+)\\]");
+    protected Map<String, MatchPair> whenCondition;
+    protected Map<String, MatchPair> thenCondition;
+
+    private boolean enabled;
+
+    public ConditionRouter(String rule, boolean force, boolean enabled) {
+        this.force = force;
+        this.enabled = enabled;
+        if (enabled) {
+            this.init(rule);
+        }
+    }
+
+    public ConditionRouter(URL url) {
+        this.url = url;
+        this.priority = url.getParameter(PRIORITY_KEY, 0);
+        this.force = url.getParameter(FORCE_KEY, false);
+        this.enabled = url.getParameter(ENABLED_KEY, true);
+        if (enabled) {
+            init(url.getParameterAndDecoded(RULE_KEY));
+        }
+    }
+
+    public void init(String rule) {
+        try {
+            if (rule == null || rule.trim().length() == 0) {
+                throw new IllegalArgumentException("Illegal route rule!");
+            }
+            rule = rule.replace("consumer.", "").replace("provider.", "");
+            int i = rule.indexOf("=>");
+            String whenRule = i < 0 ? null : rule.substring(0, i).trim();
+            String thenRule = i < 0 ? rule.trim() : rule.substring(i + 2).trim();
+            Map<String, MatchPair> when = StringUtils.isBlank(whenRule) || "true".equals(whenRule) ? new HashMap<String, MatchPair>() : parseRule(whenRule);
+            Map<String, MatchPair> 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.
+            this.whenCondition = when;
+            this.thenCondition = then;
+        } catch (ParseException e) {
+            throw new IllegalStateException(e.getMessage(), e);
+        }
+    }
+
+    private static Map<String, MatchPair> parseRule(String rule)
+            throws ParseException {
+        Map<String, MatchPair> condition = new HashMap<String, MatchPair>();
+        if (StringUtils.isBlank(rule)) {
+            return condition;
+        }
+        // Key-Value pair, stores both match and mismatch conditions
+        MatchPair pair = null;
+        // Multiple values
+        Set<String> values = null;
+        final Matcher matcher = ROUTE_PATTERN.matcher(rule);
+        while (matcher.find()) { // Try to match one by one
+            String separator = matcher.group(1);
+            String content = matcher.group(2);
+            // Start part of the condition expression.
+            if (StringUtils.isEmpty(separator)) {
+                pair = new MatchPair();
+                condition.put(content, pair);
+            }
+            // The KV part of the condition expression
+            else if ("&".equals(separator)) {
+                if (condition.get(content) == null) {
+                    pair = new MatchPair();
+                    condition.put(content, pair);
+                } else {
+                    pair = condition.get(content);
+                }
+            }
+            // The Value in the KV part.
+            else if ("=".equals(separator)) {
+                if (pair == null) {
+                    throw new ParseException("Illegal route rule \""
+                            + rule + "\", The error char '" + separator
+                            + "' at index " + matcher.start() + " before \""
+                            + content + "\".", matcher.start());
+                }
+
+                values = pair.matches;
+                values.add(content);
+            }
+            // The Value in the KV part.
+            else if ("!=".equals(separator)) {
+                if (pair == null) {
+                    throw new ParseException("Illegal route rule \""
+                            + rule + "\", The error char '" + separator
+                            + "' at index " + matcher.start() + " before \""
+                            + content + "\".", matcher.start());
+                }
+
+                values = pair.mismatches;
+                values.add(content);
+            }
+            // The Value in the KV part, if Value have more than one items.
+            else if (",".equals(separator)) { // Should be separated by ','
+                if (values == null || values.isEmpty()) {
+                    throw new ParseException("Illegal route rule \""
+                            + rule + "\", The error char '" + separator
+                            + "' at index " + matcher.start() + " before \""
+                            + content + "\".", matcher.start());
+                }
+                values.add(content);
+            } else {
+                throw new ParseException("Illegal route rule \"" + rule
+                        + "\", The error char '" + separator + "' at index "
+                        + matcher.start() + " before \"" + content + "\".", matcher.start());
+            }
+        }
+        return condition;
+    }
+
+    @Override
+    public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation)
+            throws RpcException {
+        if (!enabled) {
+            return invokers;
+        }
+
+        if (CollectionUtils.isEmpty(invokers)) {
+            return invokers;
+        }
+        try {
+            if (!matchWhen(url, invocation)) {
+                return invokers;
+            }
+            List<Invoker<T>> result = new ArrayList<Invoker<T>>();
+            if (thenCondition == null) {
+                logger.warn("The current consumer in the service blacklist. consumer: " + NetUtils.getLocalHost() + ", service: " + url.getServiceKey());
+                return result;
+            }
+            for (Invoker<T> invoker : invokers) {
+                if (matchThen(invoker.getUrl(), url)) {
+                    result.add(invoker);
+                }
+            }
+            if (!result.isEmpty()) {
+                return result;
+            } else if (force) {
+                logger.warn("The route result is empty and force execute. consumer: " + NetUtils.getLocalHost() + ", service: " + url.getServiceKey() + ", router: " + url.getParameterAndDecoded(RULE_KEY));
+                return result;
+            }
+        } catch (Throwable t) {
+            logger.error("Failed to execute condition router rule: " + getUrl() + ", invokers: " + invokers + ", cause: " + t.getMessage(), t);
+        }
+        return invokers;
+    }
+
+    @Override
+    public boolean isRuntime() {
+        // We always return true for previously defined Router, that is, old Router doesn't support cache anymore.
+//        return true;
+        return this.url.getParameter(RUNTIME_KEY, false);
+    }
+
+    @Override
+    public URL getUrl() {
+        return url;
+    }
+
+    boolean matchWhen(URL url, Invocation invocation) {
+        return CollectionUtils.isEmptyMap(whenCondition) || matchCondition(whenCondition, url, null, invocation);
+    }
+
+    private boolean matchThen(URL url, URL param) {
+        return CollectionUtils.isNotEmptyMap(thenCondition) && matchCondition(thenCondition, url, param, null);
+    }
+
+    private boolean matchCondition(Map<String, MatchPair> condition, URL url, URL param, Invocation invocation) {
+        Map<String, String> sample = url.toMap();
+        boolean result = false;
+        for (Map.Entry<String, MatchPair> matchPair : condition.entrySet()) {
+            String key = matchPair.getKey();
+
+            if (key.startsWith(Constants.ARGUMENTS)) {
+                if (!matchArguments(matchPair, invocation)) {
+                    return false;
+                } else {
+                    result = true;
+                    continue;
+                }
+            }
+
+            String sampleValue;
+            //get real invoked method name from invocation
+            if (invocation != null && (METHOD_KEY.equals(key) || METHODS_KEY.equals(key))) {
+                sampleValue = invocation.getMethodName();
+            } else if (ADDRESS_KEY.equals(key)) {
+                sampleValue = url.getAddress();
+            } else if (HOST_KEY.equals(key)) {
+                sampleValue = url.getHost();
+            } else {
+                sampleValue = sample.get(key);
+                if (sampleValue == null) {
+                    sampleValue = sample.get(key);
+                }
+            }
+            if (sampleValue != null) {
+                if (!matchPair.getValue().isMatch(sampleValue, param)) {
+                    return false;
+                } else {
+                    result = true;
+                }
+            } else {
+                //not pass the condition
+                if (!matchPair.getValue().matches.isEmpty()) {
+                    return false;
+                } else {
+                    result = true;
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * analysis the arguments in the rule.
+     * Examples would be like this:
+     * "arguments[0]=1", whenCondition is that the first argument is equal to '1'.
+     * "arguments[1]=a", whenCondition is that the second argument is equal to 'a'.
+     * @param matchPair
+     * @param invocation
+     * @return
+     */
+    public boolean matchArguments(Map.Entry<String, MatchPair> matchPair, Invocation invocation) {
+        try {
+            // split the rule
+            String key = matchPair.getKey();
+            String[] expressArray = key.split("\\.");
+            String argumentExpress = expressArray[0];
+            final Matcher matcher = ARGUMENTS_PATTERN.matcher(argumentExpress);
+            if (!matcher.find()) {
+                return false;
+            }
+
+            //extract the argument index
+            int index = Integer.parseInt(matcher.group(1));
+            if (index < 0 || index > invocation.getArguments().length) {
+                return false;
+            }
+
+            //extract the argument value
+            Object object = invocation.getArguments()[index];
+
+            if (matchPair.getValue().isMatch(String.valueOf(object), null)) {
+                return true;
+            }
+        } catch (Exception e) {
+            logger.warn("Arguments match failed, matchPair[]" + matchPair + "] invocation[" + invocation + "]", e);
+        }
+
+        return false;
+    }
+
+    protected static final class MatchPair {
+        final Set<String> matches = new HashSet<String>();
+        final Set<String> mismatches = new HashSet<String>();
+
+        private boolean isMatch(String value, URL param) {
+            if (!matches.isEmpty() && mismatches.isEmpty()) {
+                for (String match : matches) {
+                    if (UrlUtils.isMatchGlobPattern(match, value, param)) {
+                        return true;
+                    }
+                }
+                return false;
+            }
+
+            if (!mismatches.isEmpty() && matches.isEmpty()) {
+                for (String mismatch : mismatches) {
+                    if (UrlUtils.isMatchGlobPattern(mismatch, value, param)) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+
+            if (!matches.isEmpty() && !mismatches.isEmpty()) {
+                //when both mismatches and matches contain the same value, then using mismatches first
+                for (String mismatch : mismatches) {
+                    if (UrlUtils.isMatchGlobPattern(mismatch, value, param)) {
+                        return false;
+                    }
+                }
+                for (String match : matches) {
+                    if (UrlUtils.isMatchGlobPattern(match, value, param)) {
+                        return true;
+                    }
+                }
+                return false;
+            }
+            return false;
+        }
+    }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterFactory.java
index 7701c4c..71df97c 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterFactory.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterFactory.java
@@ -1,36 +1,36 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.router.condition;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.rpc.cluster.Router;
-import org.apache.dubbo.rpc.cluster.RouterFactory;
-
-/**
- * ConditionRouterFactory
- * Load when "override://" is configured {@link ConditionRouter}
- */
-public class ConditionRouterFactory implements RouterFactory {
-
-    public static final String NAME = "condition";
-
-    @Override
-    public Router getRouter(URL url) {
-        return new ConditionRouter(url);
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.router.condition;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.cluster.Router;
+import org.apache.dubbo.rpc.cluster.RouterFactory;
+
+/**
+ * ConditionRouterFactory
+ * Load when "override://" is configured {@link ConditionRouter}
+ */
+public class ConditionRouterFactory implements RouterFactory {
+
+    public static final String NAME = "condition";
+
+    @Override
+    public Router getRouter(URL url) {
+        return new ConditionRouter(url);
+    }
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouter.java
index 4c27596..f7b1a6e 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouter.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouter.java
@@ -1,177 +1,177 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.router.script;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.logger.Logger;
-import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.RpcContext;
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.cluster.router.AbstractRouter;
-
-import javax.script.Bindings;
-import javax.script.Compilable;
-import javax.script.CompiledScript;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import javax.script.ScriptException;
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.CodeSource;
-import java.security.Permissions;
-import java.security.PrivilegedAction;
-import java.security.ProtectionDomain;
-import java.security.cert.Certificate;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.stream.Collectors;
-
-import static org.apache.dubbo.rpc.cluster.Constants.DEFAULT_SCRIPT_TYPE_KEY;
-import static org.apache.dubbo.rpc.cluster.Constants.FORCE_KEY;
-import static org.apache.dubbo.rpc.cluster.Constants.PRIORITY_KEY;
-import static org.apache.dubbo.rpc.cluster.Constants.RULE_KEY;
-import static org.apache.dubbo.rpc.cluster.Constants.RUNTIME_KEY;
-import static org.apache.dubbo.rpc.cluster.Constants.TYPE_KEY;
-
-/**
- * ScriptRouter
- */
-public class ScriptRouter extends AbstractRouter {
-    public static final String NAME = "SCRIPT_ROUTER";
-    private static final int SCRIPT_ROUTER_DEFAULT_PRIORITY = 0;
-    private static final Logger logger = LoggerFactory.getLogger(ScriptRouter.class);
-
-    private static final Map<String, ScriptEngine> ENGINES = new ConcurrentHashMap<>();
-
-    private final ScriptEngine engine;
-
-    private final String rule;
-
-    private CompiledScript function;
-
-    private AccessControlContext accessControlContext;
-
-    {
-        //Just give permission of reflect to access member.
-        Permissions perms = new Permissions();
-        perms.add(new RuntimePermission("accessDeclaredMembers"));
-        // Cast to Certificate[] required because of ambiguity:
-        ProtectionDomain domain = new ProtectionDomain(new CodeSource(null, (Certificate[]) null), perms);
-        accessControlContext = new AccessControlContext(new ProtectionDomain[]{domain});
-    }
-
-    public ScriptRouter(URL url) {
-        this.url = url;
-        this.priority = url.getParameter(PRIORITY_KEY, SCRIPT_ROUTER_DEFAULT_PRIORITY);
-
-        engine = getEngine(url);
-        rule = getRule(url);
-        try {
-            Compilable compilable = (Compilable) engine;
-            function = compilable.compile(rule);
-        } catch (ScriptException e) {
-            logger.error("route error, rule has been ignored. rule: " + rule +
-                    ", url: " + RpcContext.getServiceContext().getUrl(), e);
-        }
-    }
-
-    /**
-     * get rule from url parameters.
-     */
-    private String getRule(URL url) {
-        String vRule = url.getParameterAndDecoded(RULE_KEY);
-        if (StringUtils.isEmpty(vRule)) {
-            throw new IllegalStateException("route rule can not be empty.");
-        }
-        return vRule;
-    }
-
-    /**
-     * create ScriptEngine instance by type from url parameters, then cache it
-     */
-    private ScriptEngine getEngine(URL url) {
-        String type = url.getParameter(TYPE_KEY, DEFAULT_SCRIPT_TYPE_KEY);
-
-        return ENGINES.computeIfAbsent(type, t -> {
-            ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName(type);
-            if (scriptEngine == null) {
-                throw new IllegalStateException("unsupported route engine type: " + type);
-            }
-            return scriptEngine;
-        });
-    }
-
-    @Override
-    public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException {
-        if (engine == null || function == null) {
-            return invokers;
-        }
-        Bindings bindings = createBindings(invokers, invocation);
-        return getRoutedInvokers(AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
-            try {
-                return function.eval(bindings);
-            } catch (ScriptException e) {
-                logger.error("route error, rule has been ignored. rule: " + rule + ", method:" +
-                        invocation.getMethodName() + ", url: " + RpcContext.getContext().getUrl(), e);
-                return invokers;
-            }
-        }, accessControlContext));
-    }
-
-    /**
-     * get routed invokers from result of script rule evaluation
-     */
-    @SuppressWarnings("unchecked")
-    protected <T> List<Invoker<T>> getRoutedInvokers(Object obj) {
-        if (obj instanceof Invoker[]) {
-            return Arrays.asList((Invoker<T>[]) obj);
-        } else if (obj instanceof Object[]) {
-            return Arrays.stream((Object[]) obj).map(item -> (Invoker<T>) item).collect(Collectors.toList());
-        } else {
-            return (List<Invoker<T>>) obj;
-        }
-    }
-
-    /**
-     * create bindings for script engine
-     */
-    private <T> Bindings createBindings(List<Invoker<T>> invokers, Invocation invocation) {
-        Bindings bindings = engine.createBindings();
-        // create a new List of invokers
-        bindings.put("invokers", new ArrayList<>(invokers));
-        bindings.put("invocation", invocation);
-        bindings.put("context", RpcContext.getClientAttachment());
-        return bindings;
-    }
-
-    @Override
-    public boolean isRuntime() {
-        return this.url.getParameter(RUNTIME_KEY, false);
-    }
-
-    @Override
-    public boolean isForce() {
-        return url.getParameter(FORCE_KEY, false);
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.router.script;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.RpcContext;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.router.AbstractRouter;
+
+import javax.script.Bindings;
+import javax.script.Compilable;
+import javax.script.CompiledScript;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.CodeSource;
+import java.security.Permissions;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.security.cert.Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+
+import static org.apache.dubbo.rpc.cluster.Constants.DEFAULT_SCRIPT_TYPE_KEY;
+import static org.apache.dubbo.rpc.cluster.Constants.FORCE_KEY;
+import static org.apache.dubbo.rpc.cluster.Constants.PRIORITY_KEY;
+import static org.apache.dubbo.rpc.cluster.Constants.RULE_KEY;
+import static org.apache.dubbo.rpc.cluster.Constants.RUNTIME_KEY;
+import static org.apache.dubbo.rpc.cluster.Constants.TYPE_KEY;
+
+/**
+ * ScriptRouter
+ */
+public class ScriptRouter extends AbstractRouter {
+    public static final String NAME = "SCRIPT_ROUTER";
+    private static final int SCRIPT_ROUTER_DEFAULT_PRIORITY = 0;
+    private static final Logger logger = LoggerFactory.getLogger(ScriptRouter.class);
+
+    private static final Map<String, ScriptEngine> ENGINES = new ConcurrentHashMap<>();
+
+    private final ScriptEngine engine;
+
+    private final String rule;
+
+    private CompiledScript function;
+
+    private AccessControlContext accessControlContext;
+
+    {
+        //Just give permission of reflect to access member.
+        Permissions perms = new Permissions();
+        perms.add(new RuntimePermission("accessDeclaredMembers"));
+        // Cast to Certificate[] required because of ambiguity:
+        ProtectionDomain domain = new ProtectionDomain(new CodeSource(null, (Certificate[]) null), perms);
+        accessControlContext = new AccessControlContext(new ProtectionDomain[]{domain});
+    }
+
+    public ScriptRouter(URL url) {
+        this.url = url;
+        this.priority = url.getParameter(PRIORITY_KEY, SCRIPT_ROUTER_DEFAULT_PRIORITY);
+
+        engine = getEngine(url);
+        rule = getRule(url);
+        try {
+            Compilable compilable = (Compilable) engine;
+            function = compilable.compile(rule);
+        } catch (ScriptException e) {
+            logger.error("route error, rule has been ignored. rule: " + rule +
+                    ", url: " + RpcContext.getServiceContext().getUrl(), e);
+        }
+    }
+
+    /**
+     * get rule from url parameters.
+     */
+    private String getRule(URL url) {
+        String vRule = url.getParameterAndDecoded(RULE_KEY);
+        if (StringUtils.isEmpty(vRule)) {
+            throw new IllegalStateException("route rule can not be empty.");
+        }
+        return vRule;
+    }
+
+    /**
+     * create ScriptEngine instance by type from url parameters, then cache it
+     */
+    private ScriptEngine getEngine(URL url) {
+        String type = url.getParameter(TYPE_KEY, DEFAULT_SCRIPT_TYPE_KEY);
+
+        return ENGINES.computeIfAbsent(type, t -> {
+            ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName(type);
+            if (scriptEngine == null) {
+                throw new IllegalStateException("unsupported route engine type: " + type);
+            }
+            return scriptEngine;
+        });
+    }
+
+    @Override
+    public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException {
+        if (engine == null || function == null) {
+            return invokers;
+        }
+        Bindings bindings = createBindings(invokers, invocation);
+        return getRoutedInvokers(AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
+            try {
+                return function.eval(bindings);
+            } catch (ScriptException e) {
+                logger.error("route error, rule has been ignored. rule: " + rule + ", method:" +
+                        invocation.getMethodName() + ", url: " + RpcContext.getContext().getUrl(), e);
+                return invokers;
+            }
+        }, accessControlContext));
+    }
+
+    /**
+     * get routed invokers from result of script rule evaluation
+     */
+    @SuppressWarnings("unchecked")
+    protected <T> List<Invoker<T>> getRoutedInvokers(Object obj) {
+        if (obj instanceof Invoker[]) {
+            return Arrays.asList((Invoker<T>[]) obj);
+        } else if (obj instanceof Object[]) {
+            return Arrays.stream((Object[]) obj).map(item -> (Invoker<T>) item).collect(Collectors.toList());
+        } else {
+            return (List<Invoker<T>>) obj;
+        }
+    }
+
+    /**
+     * create bindings for script engine
+     */
+    private <T> Bindings createBindings(List<Invoker<T>> invokers, Invocation invocation) {
+        Bindings bindings = engine.createBindings();
+        // create a new List of invokers
+        bindings.put("invokers", new ArrayList<>(invokers));
+        bindings.put("invocation", invocation);
+        bindings.put("context", RpcContext.getClientAttachment());
+        return bindings;
+    }
+
+    @Override
+    public boolean isRuntime() {
+        return this.url.getParameter(RUNTIME_KEY, false);
+    }
+
+    @Override
+    public boolean isForce() {
+        return url.getParameter(FORCE_KEY, false);
+    }
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouterFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouterFactory.java
index b29f25e..6621f05 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouterFactory.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouterFactory.java
@@ -1,45 +1,45 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.router.script;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.rpc.cluster.Router;
-import org.apache.dubbo.rpc.cluster.RouterFactory;
-
-/**
- * ScriptRouterFactory
- * <p>
- * Example URLS used by Script Router Factory:
- * <ol>
- * <li> script://registryAddress?type=js&rule=xxxx
- * <li> script:///path/to/routerfile.js?type=js&rule=xxxx
- * <li> script://D:\path\to\routerfile.js?type=js&rule=xxxx
- * <li> script://C:/path/to/routerfile.js?type=js&rule=xxxx
- * </ol>
- * The host value in URL points out the address of the source content of the Script Router,Registry、File etc
- *
- */
-public class ScriptRouterFactory implements RouterFactory {
-
-    public static final String NAME = "script";
-
-    @Override
-    public Router getRouter(URL url) {
-        return new ScriptRouter(url);
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.router.script;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.cluster.Router;
+import org.apache.dubbo.rpc.cluster.RouterFactory;
+
+/**
+ * ScriptRouterFactory
+ * <p>
+ * Example URLS used by Script Router Factory:
+ * <ol>
+ * <li> script://registryAddress?type=js&rule=xxxx
+ * <li> script:///path/to/routerfile.js?type=js&rule=xxxx
+ * <li> script://D:\path\to\routerfile.js?type=js&rule=xxxx
+ * <li> script://C:/path/to/routerfile.js?type=js&rule=xxxx
+ * </ol>
+ * The host value in URL points out the address of the source content of the Script Router,Registry、File etc
+ *
+ */
+public class ScriptRouterFactory implements RouterFactory {
+
+    public static final String NAME = "script";
+
+    @Override
+    public Router getRouter(URL url) {
+        return new ScriptRouter(url);
+    }
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/state/RouterCache.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/state/RouterCache.java
index 0b7b499..82ccf58 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/state/RouterCache.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/state/RouterCache.java
@@ -46,4 +46,4 @@ public class RouterCache<T> {
     public void setAddrMetadata(Object addrMetadata) {
         this.addrMetadata = addrMetadata;
     }
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/state/StateRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/state/StateRouter.java
index ee28459..cf479b0 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/state/StateRouter.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/state/StateRouter.java
@@ -1,100 +1,100 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.router.state;
-
-import java.util.List;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.cluster.Directory;
-
-/**
- * State Router. (SPI, Prototype, ThreadSafe)
- * <p>
- * <a href="http://en.wikipedia.org/wiki/Routing">Routing</a>
- *
- * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory)
- * @see Directory#list(Invocation)
- * @since 3.0
- */
-public interface StateRouter extends Comparable<StateRouter> {
-
-    int DEFAULT_PRIORITY = Integer.MAX_VALUE;
-
-    /**
-     * Get the router url.
-     *
-     * @return url
-     */
-    URL getUrl();
-
-    /***
-     * Filter invokers with current routing rule and only return the invokers that comply with the rule.
-     * Caching address lists in BitMap mode improves routing performance.
-     * @param invokers  invoker bit list
-     * @param cache      router address cache
-     * @param url        refer url
-     * @param invocation invocation
-     * @param <T>
-     * @return routed invokers
-     * @throws RpcException
-     * @Since 3.0
-     */
-    <T> BitList<Invoker<T>> route(BitList<Invoker<T>> invokers, RouterCache<T> cache, URL url, Invocation invocation)
-        throws
-        RpcException;
-
-    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
-     * rule change.
-     *
-     * @return true if the router need to execute every time.
-     */
-    boolean isRuntime();
-
-    boolean isEnable();
-
-    boolean isForce();
-
-    int getPriority();
-
-    @Override
-    default int compareTo(StateRouter o) {
-        if (o == null) {
-            throw new IllegalArgumentException();
-        }
-        return Integer.compare(this.getPriority(), o.getPriority());
-    }
-
-    String getName();
-
-    boolean shouldRePool();
-
-    <T> RouterCache<T> pool(List<Invoker<T>> invokers);
-
-    void pool();
-
-    default void stop() {
-        //do nothing by default
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.router.state;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.Directory;
+
+import java.util.List;
+
+/**
+ * State Router. (SPI, Prototype, ThreadSafe)
+ * <p>
+ * <a href="http://en.wikipedia.org/wiki/Routing">Routing</a>
+ *
+ * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory)
+ * @see Directory#list(Invocation)
+ * @since 3.0
+ */
+public interface StateRouter extends Comparable<StateRouter> {
+
+    int DEFAULT_PRIORITY = Integer.MAX_VALUE;
+
+    /**
+     * Get the router url.
+     *
+     * @return url
+     */
+    URL getUrl();
+
+    /***
+     * Filter invokers with current routing rule and only return the invokers that comply with the rule.
+     * Caching address lists in BitMap mode improves routing performance.
+     * @param invokers  invoker bit list
+     * @param cache      router address cache
+     * @param url        refer url
+     * @param invocation invocation
+     * @param <T>
+     * @return routed invokers
+     * @throws RpcException
+     * @Since 3.0
+     */
+    <T> BitList<Invoker<T>> route(BitList<Invoker<T>> invokers, RouterCache<T> cache, URL url, Invocation invocation)
+        throws
+        RpcException;
+
+    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
+     * rule change.
+     *
+     * @return true if the router need to execute every time.
+     */
+    boolean isRuntime();
+
+    boolean isEnable();
+
+    boolean isForce();
+
+    int getPriority();
+
+    @Override
+    default int compareTo(StateRouter o) {
+        if (o == null) {
+            throw new IllegalArgumentException();
+        }
+        return Integer.compare(this.getPriority(), o.getPriority());
+    }
+
+    String getName();
+
+    boolean shouldRePool();
+
+    <T> RouterCache<T> pool(List<Invoker<T>> invokers);
+
+    void pool();
+
+    default void stop() {
+        //do nothing by default
+    }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AvailableCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AvailableCluster.java
index a2e353b..6fcc03c 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AvailableCluster.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AvailableCluster.java
@@ -1,37 +1,37 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.support;
-
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.cluster.Cluster;
-import org.apache.dubbo.rpc.cluster.Directory;
-
-/**
- * AvailableCluster
- *
- */
-public class AvailableCluster implements Cluster {
-
-    public static final String NAME = "available";
-
-    @Override
-    public <T> Invoker<T> join(Directory<T> directory) throws RpcException {
-        return new AvailableClusterInvoker<>(directory);
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.support;
+
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.Cluster;
+import org.apache.dubbo.rpc.cluster.Directory;
+
+/**
+ * AvailableCluster
+ *
+ */
+public class AvailableCluster implements Cluster {
+
+    public static final String NAME = "available";
+
+    @Override
+    public <T> Invoker<T> join(Directory<T> directory) throws RpcException {
+        return new AvailableClusterInvoker<>(directory);
+    }
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastCluster.java
index f5cab05..c9798de 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastCluster.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastCluster.java
@@ -1,34 +1,34 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.support;
-
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.cluster.Directory;
-import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster;
-
-/**
- * BroadcastCluster
- *
- */
-public class BroadcastCluster extends AbstractCluster {
-
-    @Override
-    public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
-        return new BroadcastClusterInvoker<>(directory);
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.support;
+
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.Directory;
+import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster;
+
+/**
+ * BroadcastCluster
+ *
+ */
+public class BroadcastCluster extends AbstractCluster {
+
+    @Override
+    public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
+        return new BroadcastClusterInvoker<>(directory);
+    }
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastClusterInvoker.java
index 268140a..af58847 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastClusterInvoker.java
@@ -1,116 +1,116 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.support;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.logger.Logger;
-import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.Result;
-import org.apache.dubbo.rpc.RpcContext;
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.cluster.Directory;
-import org.apache.dubbo.rpc.cluster.LoadBalance;
-
-import java.util.List;
-
-/**
- * BroadcastClusterInvoker
- */
-public class BroadcastClusterInvoker<T> extends AbstractClusterInvoker<T> {
-
-    private static final Logger logger = LoggerFactory.getLogger(BroadcastClusterInvoker.class);
-    private static final String BROADCAST_FAIL_PERCENT_KEY = "broadcast.fail.percent";
-    private static final int MAX_BROADCAST_FAIL_PERCENT = 100;
-    private static final int MIN_BROADCAST_FAIL_PERCENT = 0;
-
-    public BroadcastClusterInvoker(Directory<T> directory) {
-        super(directory);
-    }
-
-    @Override
-    @SuppressWarnings({"unchecked", "rawtypes"})
-    public Result doInvoke(final Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
-        checkInvokers(invokers, invocation);
-        RpcContext.getServiceContext().setInvokers((List) invokers);
-        RpcException exception = null;
-        Result result = null;
-        URL url = getUrl();
-        // The value range of broadcast.fail.threshold must be 0~100.
-        // 100 means that an exception will be thrown last, and 0 means that as long as an exception occurs, it will be thrown.
-        // see https://github.com/apache/dubbo/pull/7174
-        int broadcastFailPercent = url.getParameter(BROADCAST_FAIL_PERCENT_KEY, MAX_BROADCAST_FAIL_PERCENT);
-
-        if (broadcastFailPercent < MIN_BROADCAST_FAIL_PERCENT || broadcastFailPercent > MAX_BROADCAST_FAIL_PERCENT) {
-            logger.info(String.format("The value corresponding to the broadcast.fail.percent parameter must be between 0 and 100. " +
-                    "The current setting is %s, which is reset to 100.", broadcastFailPercent));
-            broadcastFailPercent = MAX_BROADCAST_FAIL_PERCENT;
-        }
-
-        int failThresholdIndex = invokers.size() * broadcastFailPercent / MAX_BROADCAST_FAIL_PERCENT;
-        int failIndex = 0;
-        for (Invoker<T> invoker : invokers) {
-            try {
-                result = invokeWithContext(invoker, invocation);
-                if (null != result && result.hasException()) {
-                    Throwable resultException = result.getException();
-                    if (null != resultException) {
-                        exception = getRpcException(result.getException());
-                        logger.warn(exception.getMessage(), exception);
-                        if (failIndex == failThresholdIndex) {
-                            break;
-                        } else {
-                            failIndex++;
-                        }
-                    }
-                }
-            } catch (Throwable e) {
-                exception = getRpcException(e);
-                logger.warn(exception.getMessage(), exception);
-                if (failIndex == failThresholdIndex) {
-                    break;
-                } else {
-                    failIndex++;
-                }
-            }
-        }
-
-        if (exception != null) {
-            if (failIndex == failThresholdIndex) {
-                logger.debug(
-                        String.format("The number of BroadcastCluster call failures has reached the threshold %s", failThresholdIndex));
-            } else {
-                logger.debug(String.format("The number of BroadcastCluster call failures has not reached the threshold %s, fail size is %s",
-                        failIndex));
-            }
-            throw exception;
-        }
-
-        return result;
-    }
-
-    private RpcException getRpcException(Throwable throwable) {
-        RpcException rpcException = null;
-        if (throwable instanceof RpcException) {
-            rpcException = (RpcException) throwable;
-        } else {
-            rpcException = new RpcException(throwable.getMessage(), throwable);
-        }
-        return rpcException;
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.support;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcContext;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.Directory;
+import org.apache.dubbo.rpc.cluster.LoadBalance;
+
+import java.util.List;
+
+/**
+ * BroadcastClusterInvoker
+ */
+public class BroadcastClusterInvoker<T> extends AbstractClusterInvoker<T> {
+
+    private static final Logger logger = LoggerFactory.getLogger(BroadcastClusterInvoker.class);
+    private static final String BROADCAST_FAIL_PERCENT_KEY = "broadcast.fail.percent";
+    private static final int MAX_BROADCAST_FAIL_PERCENT = 100;
+    private static final int MIN_BROADCAST_FAIL_PERCENT = 0;
+
+    public BroadcastClusterInvoker(Directory<T> directory) {
+        super(directory);
+    }
+
+    @Override
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    public Result doInvoke(final Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
+        checkInvokers(invokers, invocation);
+        RpcContext.getServiceContext().setInvokers((List) invokers);
+        RpcException exception = null;
+        Result result = null;
+        URL url = getUrl();
+        // The value range of broadcast.fail.threshold must be 0~100.
+        // 100 means that an exception will be thrown last, and 0 means that as long as an exception occurs, it will be thrown.
+        // see https://github.com/apache/dubbo/pull/7174
+        int broadcastFailPercent = url.getParameter(BROADCAST_FAIL_PERCENT_KEY, MAX_BROADCAST_FAIL_PERCENT);
+
+        if (broadcastFailPercent < MIN_BROADCAST_FAIL_PERCENT || broadcastFailPercent > MAX_BROADCAST_FAIL_PERCENT) {
+            logger.info(String.format("The value corresponding to the broadcast.fail.percent parameter must be between 0 and 100. " +
+                    "The current setting is %s, which is reset to 100.", broadcastFailPercent));
+            broadcastFailPercent = MAX_BROADCAST_FAIL_PERCENT;
+        }
+
+        int failThresholdIndex = invokers.size() * broadcastFailPercent / MAX_BROADCAST_FAIL_PERCENT;
+        int failIndex = 0;
+        for (Invoker<T> invoker : invokers) {
+            try {
+                result = invokeWithContext(invoker, invocation);
+                if (null != result && result.hasException()) {
+                    Throwable resultException = result.getException();
+                    if (null != resultException) {
+                        exception = getRpcException(result.getException());
+                        logger.warn(exception.getMessage(), exception);
+                        if (failIndex == failThresholdIndex) {
+                            break;
+                        } else {
+                            failIndex++;
+                        }
+                    }
+                }
+            } catch (Throwable e) {
+                exception = getRpcException(e);
+                logger.warn(exception.getMessage(), exception);
+                if (failIndex == failThresholdIndex) {
+                    break;
+                } else {
+                    failIndex++;
+                }
+            }
+        }
+
+        if (exception != null) {
+            if (failIndex == failThresholdIndex) {
+                logger.debug(
+                        String.format("The number of BroadcastCluster call failures has reached the threshold %s", failThresholdIndex));
+            } else {
+                logger.debug(String.format("The number of BroadcastCluster call failures has not reached the threshold %s, fail size is %s",
+                        failIndex));
+            }
+            throw exception;
+        }
+
+        return result;
+    }
+
+    private RpcException getRpcException(Throwable throwable) {
+        RpcException rpcException = null;
+        if (throwable instanceof RpcException) {
+            rpcException = (RpcException) throwable;
+        } else {
+            rpcException = new RpcException(throwable.getMessage(), throwable);
+        }
+        return rpcException;
+    }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ClusterUtils.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ClusterUtils.java
index 55aff3e..0ff3255 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ClusterUtils.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ClusterUtils.java
@@ -1,51 +1,51 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.support;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.ExtensionLoader;
-import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.rpc.cluster.ProviderURLMergeProcessor;
-
-import java.util.Map;
-
-import static org.apache.dubbo.common.constants.CommonConstants.URL_MERGE_PROCESSOR_KEY;
-
-
-/**
- * ClusterUtils
- */
-public class ClusterUtils {
-
-    private ClusterUtils() {
-    }
-
-    public static URL mergeUrl(URL remoteUrl, Map<String, String> localMap) {
-
-        String ump = localMap.get(URL_MERGE_PROCESSOR_KEY);
-        ProviderURLMergeProcessor providerURLMergeProcessor;
-
-        if (StringUtils.isNotEmpty(ump)) {
-            providerURLMergeProcessor = ExtensionLoader.getExtensionLoader(ProviderURLMergeProcessor.class).getExtension(ump);
-        } else {
-            providerURLMergeProcessor = ExtensionLoader.getExtensionLoader(ProviderURLMergeProcessor.class).getExtension("default");
-        }
-
-        return providerURLMergeProcessor.mergeUrl(remoteUrl, localMap);
-    }
-
-}
\ No newline at end of file
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.support;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.rpc.cluster.ProviderURLMergeProcessor;
+
+import java.util.Map;
+
+import static org.apache.dubbo.common.constants.CommonConstants.URL_MERGE_PROCESSOR_KEY;
+
+
+/**
+ * ClusterUtils
+ */
+public class ClusterUtils {
+
+    private ClusterUtils() {
+    }
+
+    public static URL mergeUrl(URL remoteUrl, Map<String, String> localMap) {
+
+        String ump = localMap.get(URL_MERGE_PROCESSOR_KEY);
+        ProviderURLMergeProcessor providerURLMergeProcessor;
+
+        if (StringUtils.isNotEmpty(ump)) {
+            providerURLMergeProcessor = ExtensionLoader.getExtensionLoader(ProviderURLMergeProcessor.class).getExtension(ump);
+        } else {
+            providerURLMergeProcessor = ExtensionLoader.getExtensionLoader(ProviderURLMergeProcessor.class).getExtension("default");
+        }
+
+        return providerURLMergeProcessor.mergeUrl(remoteUrl, localMap);
+    }
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackCluster.java
index 4f4400b..0916f72 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackCluster.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackCluster.java
@@ -1,36 +1,36 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.support;
-
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.cluster.Directory;
-import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster;
-
-/**
- * {@link FailbackClusterInvoker}
- *
- */
-public class FailbackCluster extends AbstractCluster {
-
-    public final static String NAME = "failback";
-
-    @Override
-    public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
-        return new FailbackClusterInvoker<>(directory);
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.support;
+
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.Directory;
+import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster;
+
+/**
+ * {@link FailbackClusterInvoker}
+ *
+ */
+public class FailbackCluster extends AbstractCluster {
+
+    public final static String NAME = "failback";
+
+    @Override
+    public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
+        return new FailbackClusterInvoker<>(directory);
+    }
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvoker.java
index 8bc4b13..72d5d30 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvoker.java
@@ -1,168 +1,168 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.support;
-
-import org.apache.dubbo.common.logger.Logger;
-import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.timer.HashedWheelTimer;
-import org.apache.dubbo.common.timer.Timeout;
-import org.apache.dubbo.common.timer.Timer;
-import org.apache.dubbo.common.timer.TimerTask;
-import org.apache.dubbo.common.utils.NamedThreadFactory;
-import org.apache.dubbo.rpc.AsyncRpcResult;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.Result;
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.cluster.Directory;
-import org.apache.dubbo.rpc.cluster.LoadBalance;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_FAILBACK_TIMES;
-import static org.apache.dubbo.common.constants.CommonConstants.RETRIES_KEY;
-import static org.apache.dubbo.rpc.cluster.Constants.DEFAULT_FAILBACK_TASKS;
-import static org.apache.dubbo.rpc.cluster.Constants.FAIL_BACK_TASKS_KEY;
-
-/**
- * When fails, record failure requests and schedule for retry on a regular interval.
- * Especially useful for services of notification.
- *
- * <a href="http://en.wikipedia.org/wiki/Failback">Failback</a>
- */
-public class FailbackClusterInvoker<T> extends AbstractClusterInvoker<T> {
-
-    private static final Logger logger = LoggerFactory.getLogger(FailbackClusterInvoker.class);
-
-    private static final long RETRY_FAILED_PERIOD = 5;
-
-    private final int retries;
-
-    private final int failbackTasks;
-
-    private volatile Timer failTimer;
-
-    public FailbackClusterInvoker(Directory<T> directory) {
-        super(directory);
-
-        int retriesConfig = getUrl().getParameter(RETRIES_KEY, DEFAULT_FAILBACK_TIMES);
-        if (retriesConfig <= 0) {
-            retriesConfig = DEFAULT_FAILBACK_TIMES;
-        }
-        int failbackTasksConfig = getUrl().getParameter(FAIL_BACK_TASKS_KEY, DEFAULT_FAILBACK_TASKS);
-        if (failbackTasksConfig <= 0) {
-            failbackTasksConfig = DEFAULT_FAILBACK_TASKS;
-        }
-        retries = retriesConfig;
-        failbackTasks = failbackTasksConfig;
-    }
-
-    private void addFailed(LoadBalance loadbalance, Invocation invocation, List<Invoker<T>> invokers, Invoker<T> lastInvoker) {
-        if (failTimer == null) {
-            synchronized (this) {
-                if (failTimer == null) {
-                    failTimer = new HashedWheelTimer(
-                            new NamedThreadFactory("failback-cluster-timer", true),
-                            1,
-                            TimeUnit.SECONDS, 32, failbackTasks);
-                }
-            }
-        }
-        RetryTimerTask retryTimerTask = new RetryTimerTask(loadbalance, invocation, invokers, lastInvoker, retries, RETRY_FAILED_PERIOD);
-        try {
-            failTimer.newTimeout(retryTimerTask, RETRY_FAILED_PERIOD, TimeUnit.SECONDS);
-        } catch (Throwable e) {
-            logger.error("Failback background works error,invocation->" + invocation + ", exception: " + e.getMessage());
-        }
-    }
-
-    @Override
-    protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
-        Invoker<T> invoker = null;
-        try {
-            checkInvokers(invokers, invocation);
-            invoker = select(loadbalance, invocation, invokers, null);
-            return invokeWithContext(invoker, invocation);
-        } catch (Throwable e) {
-            logger.error("Failback to invoke method " + invocation.getMethodName() + ", wait for retry in background. Ignored exception: "
-                    + e.getMessage() + ", ", e);
-            addFailed(loadbalance, invocation, invokers, invoker);
-            return AsyncRpcResult.newDefaultAsyncResult(null, null, invocation); // ignore
-        }
-    }
-
-    @Override
-    public void destroy() {
-        super.destroy();
-        if (failTimer != null) {
-            failTimer.stop();
-        }
-    }
-
-    /**
-     * RetryTimerTask
-     */
-    private class RetryTimerTask implements TimerTask {
-        private final Invocation invocation;
-        private final LoadBalance loadbalance;
-        private final List<Invoker<T>> invokers;
-        private final int retries;
-        private final long tick;
-        private Invoker<T> lastInvoker;
-        private int retryTimes = 0;
-
-        RetryTimerTask(LoadBalance loadbalance, Invocation invocation, List<Invoker<T>> invokers, Invoker<T> lastInvoker, int retries, long tick) {
-            this.loadbalance = loadbalance;
-            this.invocation = invocation;
-            this.invokers = invokers;
-            this.retries = retries;
-            this.tick = tick;
-            this.lastInvoker=lastInvoker;
-        }
-
-        @Override
-        public void run(Timeout timeout) {
-            try {
-                Invoker<T> retryInvoker = select(loadbalance, invocation, invokers, Collections.singletonList(lastInvoker));
-                lastInvoker = retryInvoker;
-                invokeWithContext(retryInvoker, invocation);
-            } catch (Throwable e) {
-                logger.error("Failed retry to invoke method " + invocation.getMethodName() + ", waiting again.", e);
-                if ((++retryTimes) >= retries) {
-                    logger.error("Failed retry times exceed threshold (" + retries + "), We have to abandon, invocation->" + invocation);
-                } else {
-                    rePut(timeout);
-                }
-            }
-        }
-
-        private void rePut(Timeout timeout) {
-            if (timeout == null) {
-                return;
-            }
-
-            Timer timer = timeout.timer();
-            if (timer.isStop() || timeout.isCancelled()) {
-                return;
-            }
-
-            timer.newTimeout(timeout.task(), tick, TimeUnit.SECONDS);
-        }
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.support;
+
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.timer.HashedWheelTimer;
+import org.apache.dubbo.common.timer.Timeout;
+import org.apache.dubbo.common.timer.Timer;
+import org.apache.dubbo.common.timer.TimerTask;
+import org.apache.dubbo.common.utils.NamedThreadFactory;
+import org.apache.dubbo.rpc.AsyncRpcResult;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.Directory;
+import org.apache.dubbo.rpc.cluster.LoadBalance;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_FAILBACK_TIMES;
+import static org.apache.dubbo.common.constants.CommonConstants.RETRIES_KEY;
+import static org.apache.dubbo.rpc.cluster.Constants.DEFAULT_FAILBACK_TASKS;
+import static org.apache.dubbo.rpc.cluster.Constants.FAIL_BACK_TASKS_KEY;
+
+/**
+ * When fails, record failure requests and schedule for retry on a regular interval.
+ * Especially useful for services of notification.
+ *
+ * <a href="http://en.wikipedia.org/wiki/Failback">Failback</a>
+ */
+public class FailbackClusterInvoker<T> extends AbstractClusterInvoker<T> {
+
+    private static final Logger logger = LoggerFactory.getLogger(FailbackClusterInvoker.class);
+
+    private static final long RETRY_FAILED_PERIOD = 5;
+
+    private final int retries;
+
+    private final int failbackTasks;
+
+    private volatile Timer failTimer;
+
+    public FailbackClusterInvoker(Directory<T> directory) {
+        super(directory);
+
+        int retriesConfig = getUrl().getParameter(RETRIES_KEY, DEFAULT_FAILBACK_TIMES);
+        if (retriesConfig <= 0) {
+            retriesConfig = DEFAULT_FAILBACK_TIMES;
+        }
+        int failbackTasksConfig = getUrl().getParameter(FAIL_BACK_TASKS_KEY, DEFAULT_FAILBACK_TASKS);
+        if (failbackTasksConfig <= 0) {
+            failbackTasksConfig = DEFAULT_FAILBACK_TASKS;
+        }
+        retries = retriesConfig;
+        failbackTasks = failbackTasksConfig;
+    }
+
+    private void addFailed(LoadBalance loadbalance, Invocation invocation, List<Invoker<T>> invokers, Invoker<T> lastInvoker) {
+        if (failTimer == null) {
+            synchronized (this) {
+                if (failTimer == null) {
+                    failTimer = new HashedWheelTimer(
+                            new NamedThreadFactory("failback-cluster-timer", true),
+                            1,
+                            TimeUnit.SECONDS, 32, failbackTasks);
+                }
+            }
+        }
+        RetryTimerTask retryTimerTask = new RetryTimerTask(loadbalance, invocation, invokers, lastInvoker, retries, RETRY_FAILED_PERIOD);
+        try {
+            failTimer.newTimeout(retryTimerTask, RETRY_FAILED_PERIOD, TimeUnit.SECONDS);
+        } catch (Throwable e) {
+            logger.error("Failback background works error,invocation->" + invocation + ", exception: " + e.getMessage());
+        }
+    }
+
+    @Override
+    protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
+        Invoker<T> invoker = null;
+        try {
+            checkInvokers(invokers, invocation);
+            invoker = select(loadbalance, invocation, invokers, null);
+            return invokeWithContext(invoker, invocation);
+        } catch (Throwable e) {
+            logger.error("Failback to invoke method " + invocation.getMethodName() + ", wait for retry in background. Ignored exception: "
+                    + e.getMessage() + ", ", e);
+            addFailed(loadbalance, invocation, invokers, invoker);
+            return AsyncRpcResult.newDefaultAsyncResult(null, null, invocation); // ignore
+        }
+    }
+
+    @Override
+    public void destroy() {
+        super.destroy();
+        if (failTimer != null) {
+            failTimer.stop();
+        }
+    }
+
+    /**
+     * RetryTimerTask
+     */
+    private class RetryTimerTask implements TimerTask {
+        private final Invocation invocation;
+        private final LoadBalance loadbalance;
+        private final List<Invoker<T>> invokers;
+        private final int retries;
+        private final long tick;
+        private Invoker<T> lastInvoker;
+        private int retryTimes = 0;
+
+        RetryTimerTask(LoadBalance loadbalance, Invocation invocation, List<Invoker<T>> invokers, Invoker<T> lastInvoker, int retries, long tick) {
+            this.loadbalance = loadbalance;
+            this.invocation = invocation;
+            this.invokers = invokers;
+            this.retries = retries;
+            this.tick = tick;
+            this.lastInvoker=lastInvoker;
+        }
+
+        @Override
+        public void run(Timeout timeout) {
+            try {
+                Invoker<T> retryInvoker = select(loadbalance, invocation, invokers, Collections.singletonList(lastInvoker));
+                lastInvoker = retryInvoker;
+                invokeWithContext(retryInvoker, invocation);
+            } catch (Throwable e) {
+                logger.error("Failed retry to invoke method " + invocation.getMethodName() + ", waiting again.", e);
+                if ((++retryTimes) >= retries) {
+                    logger.error("Failed retry times exceed threshold (" + retries + "), We have to abandon, invocation->" + invocation);
+                } else {
+                    rePut(timeout);
+                }
+            }
+        }
+
+        private void rePut(Timeout timeout) {
+            if (timeout == null) {
+                return;
+            }
+
+            Timer timer = timeout.timer();
+            if (timer.isStop() || timeout.isCancelled()) {
+                return;
+            }
+
+            timer.newTimeout(timeout.task(), tick, TimeUnit.SECONDS);
+        }
+    }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastCluster.java
index 14a8565..2a04a15 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastCluster.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastCluster.java
@@ -1,36 +1,36 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.support;
-
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.cluster.Directory;
-import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster;
-
-/**
- * {@link FailfastClusterInvoker}
- *
- */
-public class FailfastCluster extends AbstractCluster {
-
-    public final static String NAME = "failfast";
-
-    @Override
-    public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
-        return new FailfastClusterInvoker<>(directory);
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.support;
+
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.Directory;
+import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster;
+
+/**
+ * {@link FailfastClusterInvoker}
+ *
+ */
+public class FailfastCluster extends AbstractCluster {
+
+    public final static String NAME = "failfast";
+
+    @Override
+    public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
+        return new FailfastClusterInvoker<>(directory);
+    }
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvoker.java
index d349808..60490ca 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvoker.java
@@ -1,62 +1,62 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.support;
-
-import org.apache.dubbo.common.Version;
-import org.apache.dubbo.common.utils.NetUtils;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.Result;
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.cluster.Directory;
-import org.apache.dubbo.rpc.cluster.LoadBalance;
-
-import java.util.List;
-
-/**
- * Execute exactly once, which means this policy will throw an exception immediately in case of an invocation error.
- * Usually used for non-idempotent write operations
- *
- * <a href="http://en.wikipedia.org/wiki/Fail-fast">Fail-fast</a>
- *
- */
-public class FailfastClusterInvoker<T> extends AbstractClusterInvoker<T> {
-
-    public FailfastClusterInvoker(Directory<T> directory) {
-        super(directory);
-    }
-
-    @Override
-    public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
-        checkInvokers(invokers, invocation);
-        Invoker<T> invoker = select(loadbalance, invocation, invokers, null);
-        try {
-            return invokeWithContext(invoker, invocation);
-        } catch (Throwable e) {
-            if (e instanceof RpcException && ((RpcException) e).isBiz()) { // biz exception.
-                throw (RpcException) e;
-            }
-            throw new RpcException(e instanceof RpcException ? ((RpcException) e).getCode() : 0,
-                    "Failfast invoke providers " + invoker.getUrl() + " " + loadbalance.getClass().getSimpleName()
-                            + " select from all providers " + invokers + " for service " + getInterface().getName()
-                            + " method " + invocation.getMethodName() + " on consumer " + NetUtils.getLocalHost()
-                            + " use dubbo version " + Version.getVersion()
-                            + ", but no luck to perform the invocation. Last error is: " + e.getMessage(),
-                    e.getCause() != null ? e.getCause() : e);
-        }
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.support;
+
+import org.apache.dubbo.common.Version;
+import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.Directory;
+import org.apache.dubbo.rpc.cluster.LoadBalance;
+
+import java.util.List;
+
+/**
+ * Execute exactly once, which means this policy will throw an exception immediately in case of an invocation error.
+ * Usually used for non-idempotent write operations
+ *
+ * <a href="http://en.wikipedia.org/wiki/Fail-fast">Fail-fast</a>
+ *
+ */
+public class FailfastClusterInvoker<T> extends AbstractClusterInvoker<T> {
+
+    public FailfastClusterInvoker(Directory<T> directory) {
+        super(directory);
+    }
+
+    @Override
+    public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
+        checkInvokers(invokers, invocation);
+        Invoker<T> invoker = select(loadbalance, invocation, invokers, null);
+        try {
+            return invokeWithContext(invoker, invocation);
+        } catch (Throwable e) {
+            if (e instanceof RpcException && ((RpcException) e).isBiz()) { // biz exception.
+                throw (RpcException) e;
+            }
+            throw new RpcException(e instanceof RpcException ? ((RpcException) e).getCode() : 0,
+                    "Failfast invoke providers " + invoker.getUrl() + " " + loadbalance.getClass().getSimpleName()
+                            + " select from all providers " + invokers + " for service " + getInterface().getName()
+                            + " method " + invocation.getMethodName() + " on consumer " + NetUtils.getLocalHost()
+                            + " use dubbo version " + Version.getVersion()
+                            + ", but no luck to perform the invocation. Last error is: " + e.getMessage(),
+                    e.getCause() != null ? e.getCause() : e);
+        }
+    }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverCluster.java
index 7f1bc54..e9e6101 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverCluster.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverCluster.java
@@ -1,36 +1,36 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.support;
-
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.cluster.Directory;
-import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster;
-
-/**
- * {@link FailoverClusterInvoker}
- *
- */
-public class FailoverCluster extends AbstractCluster {
-
-    public final static String NAME = "failover";
-
-    @Override
-    public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
-        return new FailoverClusterInvoker<>(directory);
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.support;
+
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.Directory;
+import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster;
+
+/**
+ * {@link FailoverClusterInvoker}
+ *
+ */
+public class FailoverCluster extends AbstractCluster {
+
+    public final static String NAME = "failover";
+
+    @Override
+    public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
+        return new FailoverClusterInvoker<>(directory);
+    }
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvoker.java
index a445d36..d3abeb2 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvoker.java
@@ -1,128 +1,128 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.support;
-
-import org.apache.dubbo.common.Version;
-import org.apache.dubbo.common.logger.Logger;
-import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.utils.NetUtils;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.Result;
-import org.apache.dubbo.rpc.RpcContext;
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.cluster.Directory;
-import org.apache.dubbo.rpc.cluster.LoadBalance;
-import org.apache.dubbo.rpc.support.RpcUtils;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_RETRIES;
-import static org.apache.dubbo.common.constants.CommonConstants.RETRIES_KEY;
-
-/**
- * When invoke fails, log the initial error and retry other invokers (retry n times, which means at most n different invokers will be invoked)
- * Note that retry causes latency.
- * <p>
- * <a href="http://en.wikipedia.org/wiki/Failover">Failover</a>
- *
- */
-public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
-
-    private static final Logger logger = LoggerFactory.getLogger(FailoverClusterInvoker.class);
-
-    public FailoverClusterInvoker(Directory<T> directory) {
-        super(directory);
-    }
-
-    @Override
-    @SuppressWarnings({"unchecked", "rawtypes"})
-    public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
-        List<Invoker<T>> copyInvokers = invokers;
-        checkInvokers(copyInvokers, invocation);
-        String methodName = RpcUtils.getMethodName(invocation);
-        int len = calculateInvokeTimes(methodName);
-        // retry loop.
-        RpcException le = null; // last exception.
-        List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyInvokers.size()); // invoked invokers.
-        Set<String> providers = new HashSet<String>(len);
-        for (int i = 0; i < len; i++) {
-            //Reselect before retry to avoid a change of candidate `invokers`.
-            //NOTE: if `invokers` changed, then `invoked` also lose accuracy.
-            if (i > 0) {
-                checkWhetherDestroyed();
-                copyInvokers = list(invocation);
-                // check again
-                checkInvokers(copyInvokers, invocation);
-            }
-            Invoker<T> invoker = select(loadbalance, invocation, copyInvokers, invoked);
-            invoked.add(invoker);
-            RpcContext.getServiceContext().setInvokers((List) invoked);
-            try {
-                Result result = invokeWithContext(invoker, invocation);
-                if (le != null && logger.isWarnEnabled()) {
-                    logger.warn("Although retry the method " + methodName
-                            + " in the service " + getInterface().getName()
-                            + " was successful by the provider " + invoker.getUrl().getAddress()
-                            + ", but there have been failed providers " + providers
-                            + " (" + providers.size() + "/" + copyInvokers.size()
-                            + ") from the registry " + directory.getUrl().getAddress()
-                            + " on the consumer " + NetUtils.getLocalHost()
-                            + " using the dubbo version " + Version.getVersion() + ". Last error is: "
-                            + le.getMessage(), le);
-                }
-                return result;
-            } catch (RpcException e) {
-                if (e.isBiz()) { // biz exception.
-                    throw e;
-                }
-                le = e;
-            } catch (Throwable e) {
-                le = new RpcException(e.getMessage(), e);
-            } finally {
-                providers.add(invoker.getUrl().getAddress());
-            }
-        }
-        throw new RpcException(le.getCode(), "Failed to invoke the method "
-                + methodName + " in the service " + getInterface().getName()
-                + ". Tried " + len + " times of the providers " + providers
-                + " (" + providers.size() + "/" + copyInvokers.size()
-                + ") from the registry " + directory.getUrl().getAddress()
-                + " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version "
-                + Version.getVersion() + ". Last error is: "
-                + le.getMessage(), le.getCause() != null ? le.getCause() : le);
-    }
-
-    private int calculateInvokeTimes(String methodName) {
-        int len = getUrl().getMethodParameter(methodName, RETRIES_KEY, DEFAULT_RETRIES) + 1;
-        RpcContext rpcContext = RpcContext.getClientAttachment();
-        Object retry = rpcContext.getObjectAttachment(RETRIES_KEY);
-        if (retry instanceof Number) {
-            len = ((Number) retry).intValue() + 1;
-            rpcContext.removeAttachment(RETRIES_KEY);
-        }
-        if (len <= 0) {
-            len = 1;
-        }
-
-        return len;
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.support;
+
+import org.apache.dubbo.common.Version;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcContext;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.Directory;
+import org.apache.dubbo.rpc.cluster.LoadBalance;
+import org.apache.dubbo.rpc.support.RpcUtils;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_RETRIES;
+import static org.apache.dubbo.common.constants.CommonConstants.RETRIES_KEY;
+
+/**
+ * When invoke fails, log the initial error and retry other invokers (retry n times, which means at most n different invokers will be invoked)
+ * Note that retry causes latency.
+ * <p>
+ * <a href="http://en.wikipedia.org/wiki/Failover">Failover</a>
+ *
+ */
+public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
+
+    private static final Logger logger = LoggerFactory.getLogger(FailoverClusterInvoker.class);
+
+    public FailoverClusterInvoker(Directory<T> directory) {
+        super(directory);
+    }
+
+    @Override
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
+        List<Invoker<T>> copyInvokers = invokers;
+        checkInvokers(copyInvokers, invocation);
+        String methodName = RpcUtils.getMethodName(invocation);
+        int len = calculateInvokeTimes(methodName);
+        // retry loop.
+        RpcException le = null; // last exception.
+        List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyInvokers.size()); // invoked invokers.
+        Set<String> providers = new HashSet<String>(len);
+        for (int i = 0; i < len; i++) {
+            //Reselect before retry to avoid a change of candidate `invokers`.
+            //NOTE: if `invokers` changed, then `invoked` also lose accuracy.
+            if (i > 0) {
+                checkWhetherDestroyed();
+                copyInvokers = list(invocation);
+                // check again
+                checkInvokers(copyInvokers, invocation);
+            }
+            Invoker<T> invoker = select(loadbalance, invocation, copyInvokers, invoked);
+            invoked.add(invoker);
+            RpcContext.getServiceContext().setInvokers((List) invoked);
+            try {
+                Result result = invokeWithContext(invoker, invocation);
+                if (le != null && logger.isWarnEnabled()) {
+                    logger.warn("Although retry the method " + methodName
+                            + " in the service " + getInterface().getName()
+                            + " was successful by the provider " + invoker.getUrl().getAddress()
+                            + ", but there have been failed providers " + providers
+                            + " (" + providers.size() + "/" + copyInvokers.size()
+                            + ") from the registry " + directory.getUrl().getAddress()
+                            + " on the consumer " + NetUtils.getLocalHost()
+                            + " using the dubbo version " + Version.getVersion() + ". Last error is: "
+                            + le.getMessage(), le);
+                }
+                return result;
+            } catch (RpcException e) {
+                if (e.isBiz()) { // biz exception.
+                    throw e;
+                }
+                le = e;
+            } catch (Throwable e) {
+                le = new RpcException(e.getMessage(), e);
+            } finally {
+                providers.add(invoker.getUrl().getAddress());
+            }
+        }
+        throw new RpcException(le.getCode(), "Failed to invoke the method "
+                + methodName + " in the service " + getInterface().getName()
+                + ". Tried " + len + " times of the providers " + providers
+                + " (" + providers.size() + "/" + copyInvokers.size()
+                + ") from the registry " + directory.getUrl().getAddress()
+                + " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version "
+                + Version.getVersion() + ". Last error is: "
+                + le.getMessage(), le.getCause() != null ? le.getCause() : le);
+    }
+
+    private int calculateInvokeTimes(String methodName) {
+        int len = getUrl().getMethodParameter(methodName, RETRIES_KEY, DEFAULT_RETRIES) + 1;
+        RpcContext rpcContext = RpcContext.getClientAttachment();
+        Object retry = rpcContext.getObjectAttachment(RETRIES_KEY);
+        if (retry instanceof Number) {
+            len = ((Number) retry).intValue() + 1;
+            rpcContext.removeAttachment(RETRIES_KEY);
+        }
+        if (len <= 0) {
+            len = 1;
+        }
+
+        return len;
+    }
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeCluster.java
index 767ab31..7064950 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeCluster.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeCluster.java
@@ -1,36 +1,36 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.support;
-
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.cluster.Directory;
-import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster;
-
-/**
- * {@link FailsafeClusterInvoker}
- *
- */
-public class FailsafeCluster extends AbstractCluster {
-
-    public final static String NAME = "failsafe";
-
-    @Override
-    public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
-        return new FailsafeClusterInvoker<>(directory);
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.support;
+
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.Directory;
+import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster;
+
+/**
+ * {@link FailsafeClusterInvoker}
+ *
+ */
+public class FailsafeCluster extends AbstractCluster {
+
+    public final static String NAME = "failsafe";
+
+    @Override
+    public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
+        return new FailsafeClusterInvoker<>(directory);
+    }
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeClusterInvoker.java
index 3548a67..edc9ec5 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeClusterInvoker.java
@@ -1,56 +1,56 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.support;
-
-import org.apache.dubbo.common.logger.Logger;
-import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.rpc.AsyncRpcResult;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.Result;
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.cluster.Directory;
-import org.apache.dubbo.rpc.cluster.LoadBalance;
-
-import java.util.List;
-
-/**
- * When invoke fails, log the error message and ignore this error by returning an empty Result.
- * Usually used to write audit logs and other operations
- *
- * <a href="http://en.wikipedia.org/wiki/Fail-safe">Fail-safe</a>
- *
- */
-public class FailsafeClusterInvoker<T> extends AbstractClusterInvoker<T> {
-    private static final Logger logger = LoggerFactory.getLogger(FailsafeClusterInvoker.class);
-
-    public FailsafeClusterInvoker(Directory<T> directory) {
-        super(directory);
-    }
-
-    @Override
-    public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
-        try {
-            checkInvokers(invokers, invocation);
-            Invoker<T> invoker = select(loadbalance, invocation, invokers, null);
-            return invokeWithContext(invoker, invocation);
-        } catch (Throwable e) {
-            logger.error("Failsafe ignore exception: " + e.getMessage(), e);
-            return AsyncRpcResult.newDefaultAsyncResult(null, null, invocation); // ignore
-        }
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.support;
+
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.rpc.AsyncRpcResult;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.Directory;
+import org.apache.dubbo.rpc.cluster.LoadBalance;
+
+import java.util.List;
+
+/**
+ * When invoke fails, log the error message and ignore this error by returning an empty Result.
+ * Usually used to write audit logs and other operations
+ *
+ * <a href="http://en.wikipedia.org/wiki/Fail-safe">Fail-safe</a>
+ *
+ */
+public class FailsafeClusterInvoker<T> extends AbstractClusterInvoker<T> {
+    private static final Logger logger = LoggerFactory.getLogger(FailsafeClusterInvoker.class);
+
+    public FailsafeClusterInvoker(Directory<T> directory) {
+        super(directory);
+    }
+
+    @Override
+    public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
+        try {
+            checkInvokers(invokers, invocation);
+            Invoker<T> invoker = select(loadbalance, invocation, invokers, null);
+            return invokeWithContext(invoker, invocation);
+        } catch (Throwable e) {
+            logger.error("Failsafe ignore exception: " + e.getMessage(), e);
+            return AsyncRpcResult.newDefaultAsyncResult(null, null, invocation); // ignore
+        }
+    }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ForkingCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ForkingCluster.java
index b28cffd..83ecbb8 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ForkingCluster.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ForkingCluster.java
@@ -1,36 +1,36 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.support;
-
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.cluster.Directory;
-import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster;
-
-/**
- * {@link ForkingClusterInvoker}
- *
- */
-public class ForkingCluster extends AbstractCluster {
-
-    public final static String NAME = "forking";
-
-    @Override
-    public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
-        return new ForkingClusterInvoker<>(directory);
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.support;
+
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.Directory;
+import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster;
+
+/**
+ * {@link ForkingClusterInvoker}
+ *
+ */
+public class ForkingCluster extends AbstractCluster {
+
+    public final static String NAME = "forking";
+
+    @Override
+    public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {
+        return new ForkingClusterInvoker<>(directory);
+    }
+
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/merger/DefaultProviderURLMergeProcessor.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/merger/DefaultProviderURLMergeProcessor.java
index 93f25bd..8610bc8 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/merger/DefaultProviderURLMergeProcessor.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/merger/DefaultProviderURLMergeProcessor.java
@@ -120,4 +120,4 @@ public class DefaultProviderURLMergeProcessor implements ProviderURLMergeProcess
         return remoteUrl.clearParameters().addParameters(map);
     }
 
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareCluster.java
index 64e09b8..cfd36e1 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareCluster.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareCluster.java
@@ -30,4 +30,4 @@ public class ZoneAwareCluster extends AbstractCluster {
         return new ZoneAwareClusterInvoker<T>(directory);
     }
 
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareClusterInvoker.java
index 97b7a0b..5e14b87 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareClusterInvoker.java
@@ -102,4 +102,4 @@ public class ZoneAwareClusterInvoker<T> extends AbstractClusterInvoker<T> {
         return invokers.get(0).invoke(invocation);
     }
 
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java
index 51d0a49..8dbf6f5 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java
@@ -1,195 +1,195 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.support.wrapper;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.logger.Logger;
-import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.utils.CollectionUtils;
-import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.rpc.AsyncRpcResult;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.Result;
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.cluster.ClusterInvoker;
-import org.apache.dubbo.rpc.cluster.Directory;
-import org.apache.dubbo.rpc.support.MockInvoker;
-
-import java.util.List;
-
-import static org.apache.dubbo.rpc.Constants.MOCK_KEY;
-import static org.apache.dubbo.rpc.cluster.Constants.INVOCATION_NEED_MOCK;
-
-public class MockClusterInvoker<T> implements ClusterInvoker<T> {
-
-    private static final Logger logger = LoggerFactory.getLogger(MockClusterInvoker.class);
-
-    private final Directory<T> directory;
-
-    private final Invoker<T> invoker;
-
-    public MockClusterInvoker(Directory<T> directory, Invoker<T> invoker) {
-        this.directory = directory;
-        this.invoker = invoker;
-    }
-
-    @Override
-    public URL getUrl() {
-        return directory.getConsumerUrl();
-    }
-
-    public URL getRegistryUrl() {
-        return directory.getUrl();
-    }
-
-    @Override
-    public Directory<T> getDirectory() {
-        return directory;
-    }
-
-    @Override
-    public boolean isDestroyed() {
-        return directory.isDestroyed();
-    }
-
-    @Override
-    public boolean isAvailable() {
-        return directory.isAvailable();
-    }
-
-    @Override
-    public void destroy() {
-        this.invoker.destroy();
-    }
-
-    @Override
-    public Class<T> getInterface() {
-        return directory.getInterface();
-    }
-
-    @Override
-    public Result invoke(Invocation invocation) throws RpcException {
-        Result result = null;
-
-        String value = getUrl().getMethodParameter(invocation.getMethodName(), MOCK_KEY, Boolean.FALSE.toString()).trim();
-        if (value.length() == 0 || "false".equalsIgnoreCase(value)) {
-            //no mock
-            result = this.invoker.invoke(invocation);
-        } else if (value.startsWith("force")) {
-            if (logger.isWarnEnabled()) {
-                logger.warn("force-mock: " + invocation.getMethodName() + " force-mock enabled , url : " + getUrl());
-            }
-            //force:direct mock
-            result = doMockInvoke(invocation, null);
-        } else {
-            //fail-mock
-            try {
-                result = this.invoker.invoke(invocation);
-
-                //fix:#4585
-                if(result.getException() != null && result.getException() instanceof RpcException){
-                    RpcException rpcException= (RpcException)result.getException();
-                    if(rpcException.isBiz()){
-                        throw  rpcException;
-                    }else {
-                        result = doMockInvoke(invocation, rpcException);
-                    }
-                }
-
-            } catch (RpcException e) {
-                if (e.isBiz()) {
-                    throw e;
-                }
-
-                if (logger.isWarnEnabled()) {
-                    logger.warn("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " + getUrl(), e);
-                }
-                result = doMockInvoke(invocation, e);
-            }
-        }
-        return result;
-    }
-
-    @SuppressWarnings({"unchecked", "rawtypes"})
-    private Result doMockInvoke(Invocation invocation, RpcException e) {
-        Result result = null;
-        Invoker<T> minvoker;
-
-        List<Invoker<T>> mockInvokers = selectMockInvoker(invocation);
-        if (CollectionUtils.isEmpty(mockInvokers)) {
-            minvoker = (Invoker<T>) new MockInvoker(getUrl(), directory.getInterface());
-        } else {
-            minvoker = mockInvokers.get(0);
-        }
-        try {
-            result = minvoker.invoke(invocation);
-        } catch (RpcException me) {
-            if (me.isBiz()) {
-                result = AsyncRpcResult.newDefaultAsyncResult(me.getCause(), invocation);
-            } else {
-                throw new RpcException(me.getCode(), getMockExceptionMessage(e, me), me.getCause());
-            }
-        } catch (Throwable me) {
-            throw new RpcException(getMockExceptionMessage(e, me), me.getCause());
-        }
-        return result;
-    }
-
-    private String getMockExceptionMessage(Throwable t, Throwable mt) {
-        String msg = "mock error : " + mt.getMessage();
-        if (t != null) {
-            msg = msg + ", invoke error is :" + StringUtils.toString(t);
-        }
-        return msg;
-    }
-
-    /**
-     * Return MockInvoker
-     * Contract:
-     * directory.list() will return a list of normal invokers if Constants.INVOCATION_NEED_MOCK is absent or not true in invocation, otherwise, a list of mock invokers will return.
-     * if directory.list() returns more than one mock invoker, only one of them will be used.
-     *
-     * @param invocation
-     * @return
-     */
-    private List<Invoker<T>> selectMockInvoker(Invocation invocation) {
-        List<Invoker<T>> invokers = null;
-        //TODO generic invoker?
-        if (invocation instanceof RpcInvocation) {
-            //Note the implicit contract (although the description is added to the interface declaration, but extensibility is a problem. The practice placed in the attachment needs to be improved)
-            ((RpcInvocation) invocation).setAttachment(INVOCATION_NEED_MOCK, Boolean.TRUE.toString());
-            //directory will return a list of normal invokers if Constants.INVOCATION_NEED_MOCK is absent or not true in invocation, otherwise, a list of mock invokers will return.
-            try {
-                invokers = directory.list(invocation);
-            } catch (RpcException e) {
-                if (logger.isInfoEnabled()) {
-                    logger.info("Exception when try to invoke mock. Get mock invokers error for service:"
-                            + getUrl().getServiceInterface() + ", method:" + invocation.getMethodName()
-                            + ", will construct a new mock with 'new MockInvoker()'.", e);
-                }
-            }
-        }
-        return invokers;
-    }
-
-    @Override
-    public String toString() {
-        return "invoker :" + this.invoker + ",directory: " + this.directory;
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.support.wrapper;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.rpc.AsyncRpcResult;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.RpcInvocation;
+import org.apache.dubbo.rpc.cluster.ClusterInvoker;
+import org.apache.dubbo.rpc.cluster.Directory;
+import org.apache.dubbo.rpc.support.MockInvoker;
+
+import java.util.List;
+
+import static org.apache.dubbo.rpc.Constants.MOCK_KEY;
+import static org.apache.dubbo.rpc.cluster.Constants.INVOCATION_NEED_MOCK;
+
+public class MockClusterInvoker<T> implements ClusterInvoker<T> {
+
+    private static final Logger logger = LoggerFactory.getLogger(MockClusterInvoker.class);
+
+    private final Directory<T> directory;
+
+    private final Invoker<T> invoker;
+
+    public MockClusterInvoker(Directory<T> directory, Invoker<T> invoker) {
+        this.directory = directory;
+        this.invoker = invoker;
+    }
+
+    @Override
+    public URL getUrl() {
+        return directory.getConsumerUrl();
+    }
+
+    public URL getRegistryUrl() {
+        return directory.getUrl();
+    }
+
+    @Override
+    public Directory<T> getDirectory() {
+        return directory;
+    }
+
+    @Override
+    public boolean isDestroyed() {
+        return directory.isDestroyed();
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return directory.isAvailable();
+    }
+
+    @Override
+    public void destroy() {
+        this.invoker.destroy();
+    }
+
+    @Override
+    public Class<T> getInterface() {
+        return directory.getInterface();
+    }
+
+    @Override
+    public Result invoke(Invocation invocation) throws RpcException {
+        Result result = null;
+
+        String value = getUrl().getMethodParameter(invocation.getMethodName(), MOCK_KEY, Boolean.FALSE.toString()).trim();
+        if (value.length() == 0 || "false".equalsIgnoreCase(value)) {
+            //no mock
+            result = this.invoker.invoke(invocation);
+        } else if (value.startsWith("force")) {
+            if (logger.isWarnEnabled()) {
+                logger.warn("force-mock: " + invocation.getMethodName() + " force-mock enabled , url : " + getUrl());
+            }
+            //force:direct mock
+            result = doMockInvoke(invocation, null);
+        } else {
+            //fail-mock
+            try {
+                result = this.invoker.invoke(invocation);
+
+                //fix:#4585
+                if(result.getException() != null && result.getException() instanceof RpcException){
+                    RpcException rpcException= (RpcException)result.getException();
+                    if(rpcException.isBiz()){
+                        throw  rpcException;
+                    }else {
+                        result = doMockInvoke(invocation, rpcException);
+                    }
+                }
+
+            } catch (RpcException e) {
+                if (e.isBiz()) {
+                    throw e;
+                }
+
+                if (logger.isWarnEnabled()) {
+                    logger.warn("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " + getUrl(), e);
+                }
+                result = doMockInvoke(invocation, e);
+            }
+        }
+        return result;
+    }
+
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    private Result doMockInvoke(Invocation invocation, RpcException e) {
+        Result result = null;
+        Invoker<T> minvoker;
+
+        List<Invoker<T>> mockInvokers = selectMockInvoker(invocation);
+        if (CollectionUtils.isEmpty(mockInvokers)) {
+            minvoker = (Invoker<T>) new MockInvoker(getUrl(), directory.getInterface());
+        } else {
+            minvoker = mockInvokers.get(0);
+        }
+        try {
+            result = minvoker.invoke(invocation);
+        } catch (RpcException me) {
+            if (me.isBiz()) {
+                result = AsyncRpcResult.newDefaultAsyncResult(me.getCause(), invocation);
+            } else {
+                throw new RpcException(me.getCode(), getMockExceptionMessage(e, me), me.getCause());
+            }
+        } catch (Throwable me) {
+            throw new RpcException(getMockExceptionMessage(e, me), me.getCause());
+        }
+        return result;
+    }
+
+    private String getMockExceptionMessage(Throwable t, Throwable mt) {
+        String msg = "mock error : " + mt.getMessage();
+        if (t != null) {
+            msg = msg + ", invoke error is :" + StringUtils.toString(t);
+        }
+        return msg;
+    }
+
+    /**
+     * Return MockInvoker
+     * Contract:
+     * directory.list() will return a list of normal invokers if Constants.INVOCATION_NEED_MOCK is absent or not true in invocation, otherwise, a list of mock invokers will return.
+     * if directory.list() returns more than one mock invoker, only one of them will be used.
+     *
+     * @param invocation
+     * @return
+     */
+    private List<Invoker<T>> selectMockInvoker(Invocation invocation) {
+        List<Invoker<T>> invokers = null;
+        //TODO generic invoker?
+        if (invocation instanceof RpcInvocation) {
+            //Note the implicit contract (although the description is added to the interface declaration, but extensibility is a problem. The practice placed in the attachment needs to be improved)
+            ((RpcInvocation) invocation).setAttachment(INVOCATION_NEED_MOCK, Boolean.TRUE.toString());
+            //directory will return a list of normal invokers if Constants.INVOCATION_NEED_MOCK is absent or not true in invocation, otherwise, a list of mock invokers will return.
+            try {
+                invokers = directory.list(invocation);
+            } catch (RpcException e) {
+                if (logger.isInfoEnabled()) {
+                    logger.info("Exception when try to invoke mock. Get mock invokers error for service:"
+                            + getUrl().getServiceInterface() + ", method:" + invocation.getMethodName()
+                            + ", will construct a new mock with 'new MockInvoker()'.", e);
+                }
+            }
+        }
+        return invokers;
+    }
+
+    @Override
+    public String toString() {
+        return "invoker :" + this.invoker + ",directory: " + this.directory;
+    }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterWrapper.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterWrapper.java
index cfe8cec..8aa2306 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterWrapper.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterWrapper.java
@@ -1,42 +1,42 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.support.wrapper;
-
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.cluster.Cluster;
-import org.apache.dubbo.rpc.cluster.Directory;
-
-/**
- * mock impl
- *
- */
-public class MockClusterWrapper implements Cluster {
-
-    private Cluster cluster;
-
-    public MockClusterWrapper(Cluster cluster) {
-        this.cluster = cluster;
-    }
-
-    @Override
-    public <T> Invoker<T> join(Directory<T> directory) throws RpcException {
-        return new MockClusterInvoker<T>(directory,
-                this.cluster.join(directory));
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.support.wrapper;
+
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.Cluster;
+import org.apache.dubbo.rpc.cluster.Directory;
+
+/**
+ * mock impl
+ *
+ */
+public class MockClusterWrapper implements Cluster {
+
+    private Cluster cluster;
+
+    public MockClusterWrapper(Cluster cluster) {
+        this.cluster = cluster;
+    }
+
+    @Override
+    public <T> Invoker<T> join(Directory<T> directory) throws RpcException {
+        return new MockClusterInvoker<T>(directory,
+                this.cluster.join(directory));
+    }
+
+}
diff --git a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.Cluster b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.Cluster
index 5808d13..f9e2570 100644
--- a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.Cluster
+++ b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.Cluster
@@ -1,10 +1,10 @@
-mock=org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterWrapper
-failover=org.apache.dubbo.rpc.cluster.support.FailoverCluster
-failfast=org.apache.dubbo.rpc.cluster.support.FailfastCluster
-failsafe=org.apache.dubbo.rpc.cluster.support.FailsafeCluster
-failback=org.apache.dubbo.rpc.cluster.support.FailbackCluster
-forking=org.apache.dubbo.rpc.cluster.support.ForkingCluster
-available=org.apache.dubbo.rpc.cluster.support.AvailableCluster
-mergeable=org.apache.dubbo.rpc.cluster.support.MergeableCluster
-broadcast=org.apache.dubbo.rpc.cluster.support.BroadcastCluster
+mock=org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterWrapper
+failover=org.apache.dubbo.rpc.cluster.support.FailoverCluster
+failfast=org.apache.dubbo.rpc.cluster.support.FailfastCluster
+failsafe=org.apache.dubbo.rpc.cluster.support.FailsafeCluster
+failback=org.apache.dubbo.rpc.cluster.support.FailbackCluster
+forking=org.apache.dubbo.rpc.cluster.support.ForkingCluster
+available=org.apache.dubbo.rpc.cluster.support.AvailableCluster
+mergeable=org.apache.dubbo.rpc.cluster.support.MergeableCluster
+broadcast=org.apache.dubbo.rpc.cluster.support.BroadcastCluster
 zone-aware=org.apache.dubbo.rpc.cluster.support.registry.ZoneAwareCluster
\ No newline at end of file
diff --git a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.ConfiguratorFactory b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.ConfiguratorFactory
index 0000187..38597bd 100644
--- a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.ConfiguratorFactory
+++ b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.ConfiguratorFactory
@@ -1,2 +1,2 @@
-override=org.apache.dubbo.rpc.cluster.configurator.override.OverrideConfiguratorFactory
+override=org.apache.dubbo.rpc.cluster.configurator.override.OverrideConfiguratorFactory
 absent=org.apache.dubbo.rpc.cluster.configurator.absent.AbsentConfiguratorFactory
\ No newline at end of file
diff --git a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.LoadBalance b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.LoadBalance
index 8a636a9..347ea10 100644
--- a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.LoadBalance
+++ b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.LoadBalance
@@ -1,5 +1,5 @@
-random=org.apache.dubbo.rpc.cluster.loadbalance.RandomLoadBalance
-roundrobin=org.apache.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance
-leastactive=org.apache.dubbo.rpc.cluster.loadbalance.LeastActiveLoadBalance
-consistenthash=org.apache.dubbo.rpc.cluster.loadbalance.ConsistentHashLoadBalance
+random=org.apache.dubbo.rpc.cluster.loadbalance.RandomLoadBalance
+roundrobin=org.apache.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance
+leastactive=org.apache.dubbo.rpc.cluster.loadbalance.LeastActiveLoadBalance
+consistenthash=org.apache.dubbo.rpc.cluster.loadbalance.ConsistentHashLoadBalance
 shortestresponse=org.apache.dubbo.rpc.cluster.loadbalance.ShortestResponseLoadBalance
\ No newline at end of file
diff --git a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.Merger b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.Merger
index 699decf..e3aeabb 100644
--- a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.Merger
+++ b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.Merger
@@ -1,11 +1,11 @@
-map=org.apache.dubbo.rpc.cluster.merger.MapMerger
-set=org.apache.dubbo.rpc.cluster.merger.SetMerger
-list=org.apache.dubbo.rpc.cluster.merger.ListMerger
-byte=org.apache.dubbo.rpc.cluster.merger.ByteArrayMerger
-char=org.apache.dubbo.rpc.cluster.merger.CharArrayMerger
-short=org.apache.dubbo.rpc.cluster.merger.ShortArrayMerger
-int=org.apache.dubbo.rpc.cluster.merger.IntArrayMerger
-long=org.apache.dubbo.rpc.cluster.merger.LongArrayMerger
-float=org.apache.dubbo.rpc.cluster.merger.FloatArrayMerger
-double=org.apache.dubbo.rpc.cluster.merger.DoubleArrayMerger
-boolean=org.apache.dubbo.rpc.cluster.merger.BooleanArrayMerger
+map=org.apache.dubbo.rpc.cluster.merger.MapMerger
+set=org.apache.dubbo.rpc.cluster.merger.SetMerger
+list=org.apache.dubbo.rpc.cluster.merger.ListMerger
+byte=org.apache.dubbo.rpc.cluster.merger.ByteArrayMerger
+char=org.apache.dubbo.rpc.cluster.merger.CharArrayMerger
+short=org.apache.dubbo.rpc.cluster.merger.ShortArrayMerger
+int=org.apache.dubbo.rpc.cluster.merger.IntArrayMerger
+long=org.apache.dubbo.rpc.cluster.merger.LongArrayMerger
+float=org.apache.dubbo.rpc.cluster.merger.FloatArrayMerger
+double=org.apache.dubbo.rpc.cluster.merger.DoubleArrayMerger
+boolean=org.apache.dubbo.rpc.cluster.merger.BooleanArrayMerger
diff --git a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory
index 9784158..e229f2a 100644
--- a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory
+++ b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory
@@ -1,7 +1,7 @@
-file=org.apache.dubbo.rpc.cluster.router.file.FileRouterFactory
-condition=org.apache.dubbo.rpc.cluster.router.condition.ConditionRouterFactory
-service=org.apache.dubbo.rpc.cluster.router.condition.config.ServiceRouterFactory
-app=org.apache.dubbo.rpc.cluster.router.condition.config.AppRouterFactory
-tag=org.apache.dubbo.rpc.cluster.router.tag.TagRouterFactory
-mock=org.apache.dubbo.rpc.cluster.router.mock.MockRouterFactory
-mesh-rule=org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleRouterFactory
+file=org.apache.dubbo.rpc.cluster.router.file.FileRouterFactory
+condition=org.apache.dubbo.rpc.cluster.router.condition.ConditionRouterFactory
+service=org.apache.dubbo.rpc.cluster.router.condition.config.ServiceRouterFactory
+app=org.apache.dubbo.rpc.cluster.router.condition.config.AppRouterFactory
+tag=org.apache.dubbo.rpc.cluster.router.tag.TagRouterFactory
+mock=org.apache.dubbo.rpc.cluster.router.mock.MockRouterFactory
+mesh-rule=org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleRouterFactory
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfiguratorTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfiguratorTest.java
index 36ef868..3f017a3 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfiguratorTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/configurator/absent/AbsentConfiguratorTest.java
@@ -1,68 +1,68 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.configurator.absent;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.utils.NetUtils;
-import org.apache.dubbo.rpc.cluster.configurator.consts.UrlConstant;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-/**
- * OverrideConfiguratorTest
- */
-public class AbsentConfiguratorTest {
-
-
-    @Test
-    public void testOverrideApplication() {
-        AbsentConfigurator configurator = new AbsentConfigurator(URL.valueOf("override://foo@0.0.0.0/com.foo.BarService?timeout=200"));
-
-        URL url = configurator.configure(URL.valueOf(UrlConstant.URL_CONSUMER));
-        Assertions.assertEquals("200", url.getParameter("timeout"));
-
-        url = configurator.configure(URL.valueOf(UrlConstant.URL_ONE));
-        Assertions.assertEquals("1000", url.getParameter("timeout"));
-
-        url = configurator.configure(URL.valueOf(UrlConstant.APPLICATION_BAR_SIDE_CONSUMER_11));
-        Assertions.assertNull(url.getParameter("timeout"));
-
-        url = configurator.configure(URL.valueOf(UrlConstant.TIMEOUT_1000_SIDE_CONSUMER_11));
-        Assertions.assertEquals("1000", url.getParameter("timeout"));
-    }
-
-    @Test
-    public void testOverrideHost() {
-        AbsentConfigurator configurator = new AbsentConfigurator(URL.valueOf("override://" + NetUtils.getLocalHost() + "/com.foo.BarService?timeout=200"));
-
-        URL url = configurator.configure(URL.valueOf(UrlConstant.URL_CONSUMER));
-        Assertions.assertEquals("200", url.getParameter("timeout"));
-
-        url = configurator.configure(URL.valueOf(UrlConstant.URL_ONE));
-        Assertions.assertEquals("1000", url.getParameter("timeout"));
-
-        AbsentConfigurator configurator1 = new AbsentConfigurator(URL.valueOf(UrlConstant.SERVICE_TIMEOUT_200));
-
-        url = configurator1.configure(URL.valueOf(UrlConstant.APPLICATION_BAR_SIDE_CONSUMER_10));
-        Assertions.assertNull(url.getParameter("timeout"));
-
-        url = configurator1.configure(URL.valueOf(UrlConstant.TIMEOUT_1000_SIDE_CONSUMER_10));
-        Assertions.assertEquals("1000", url.getParameter("timeout"));
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.configurator.absent;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.rpc.cluster.configurator.consts.UrlConstant;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * OverrideConfiguratorTest
+ */
+public class AbsentConfiguratorTest {
+
+
+    @Test
+    public void testOverrideApplication() {
+        AbsentConfigurator configurator = new AbsentConfigurator(URL.valueOf("override://foo@0.0.0.0/com.foo.BarService?timeout=200"));
+
+        URL url = configurator.configure(URL.valueOf(UrlConstant.URL_CONSUMER));
+        Assertions.assertEquals("200", url.getParameter("timeout"));
+
+        url = configurator.configure(URL.valueOf(UrlConstant.URL_ONE));
+        Assertions.assertEquals("1000", url.getParameter("timeout"));
+
+        url = configurator.configure(URL.valueOf(UrlConstant.APPLICATION_BAR_SIDE_CONSUMER_11));
+        Assertions.assertNull(url.getParameter("timeout"));
+
+        url = configurator.configure(URL.valueOf(UrlConstant.TIMEOUT_1000_SIDE_CONSUMER_11));
+        Assertions.assertEquals("1000", url.getParameter("timeout"));
+    }
+
+    @Test
+    public void testOverrideHost() {
+        AbsentConfigurator configurator = new AbsentConfigurator(URL.valueOf("override://" + NetUtils.getLocalHost() + "/com.foo.BarService?timeout=200"));
+
+        URL url = configurator.configure(URL.valueOf(UrlConstant.URL_CONSUMER));
+        Assertions.assertEquals("200", url.getParameter("timeout"));
+
+        url = configurator.configure(URL.valueOf(UrlConstant.URL_ONE));
+        Assertions.assertEquals("1000", url.getParameter("timeout"));
+
+        AbsentConfigurator configurator1 = new AbsentConfigurator(URL.valueOf(UrlConstant.SERVICE_TIMEOUT_200));
+
+        url = configurator1.configure(URL.valueOf(UrlConstant.APPLICATION_BAR_SIDE_CONSUMER_10));
+        Assertions.assertNull(url.getParameter("timeout"));
+
+        url = configurator1.configure(URL.valueOf(UrlConstant.TIMEOUT_1000_SIDE_CONSUMER_10));
+        Assertions.assertEquals("1000", url.getParameter("timeout"));
+    }
+
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfiguratorTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfiguratorTest.java
index f2b7d3d..e289144 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfiguratorTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/configurator/override/OverrideConfiguratorTest.java
@@ -1,68 +1,68 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.configurator.override;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.utils.NetUtils;
-import org.apache.dubbo.rpc.cluster.configurator.absent.AbsentConfigurator;
-import org.apache.dubbo.rpc.cluster.configurator.consts.UrlConstant;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-/**
- * OverrideConfiguratorTest
- */
-public class OverrideConfiguratorTest {
-
-    @Test
-    public void testOverride_Application() {
-        OverrideConfigurator configurator = new OverrideConfigurator(URL.valueOf("override://foo@0.0.0.0/com.foo.BarService?timeout=200"));
-
-        URL url = configurator.configure(URL.valueOf(UrlConstant.URL_CONSUMER));
-        Assertions.assertEquals("200", url.getParameter("timeout"));
-
-        url = configurator.configure(URL.valueOf(UrlConstant.URL_ONE));
-        Assertions.assertEquals("200", url.getParameter("timeout"));
-
-        url = configurator.configure(URL.valueOf(UrlConstant.APPLICATION_BAR_SIDE_CONSUMER_11));
-        Assertions.assertNull(url.getParameter("timeout"));
-
-        url = configurator.configure(URL.valueOf(UrlConstant.TIMEOUT_1000_SIDE_CONSUMER_11));
-        Assertions.assertEquals("1000", url.getParameter("timeout"));
-    }
-
-    @Test
-    public void testOverride_Host() {
-        OverrideConfigurator configurator = new OverrideConfigurator(URL.valueOf("override://" + NetUtils.getLocalHost() + "/com.foo.BarService?timeout=200"));
-
-        URL url = configurator.configure(URL.valueOf(UrlConstant.URL_CONSUMER));
-        Assertions.assertEquals("200", url.getParameter("timeout"));
-
-        url = configurator.configure(URL.valueOf(UrlConstant.URL_ONE));
-        Assertions.assertEquals("200", url.getParameter("timeout"));
-
-        AbsentConfigurator configurator1 = new AbsentConfigurator(URL.valueOf("override://10.20.153.10/com.foo.BarService?timeout=200"));
-
-        url = configurator1.configure(URL.valueOf(UrlConstant.APPLICATION_BAR_SIDE_CONSUMER_10));
-        Assertions.assertNull(url.getParameter("timeout"));
-
-        url = configurator1.configure(URL.valueOf(UrlConstant.TIMEOUT_1000_SIDE_CONSUMER_10));
-        Assertions.assertEquals("1000", url.getParameter("timeout"));
-    }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.configurator.override;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.rpc.cluster.configurator.absent.AbsentConfigurator;
+import org.apache.dubbo.rpc.cluster.configurator.consts.UrlConstant;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * OverrideConfiguratorTest
+ */
+public class OverrideConfiguratorTest {
+
+    @Test
+    public void testOverride_Application() {
+        OverrideConfigurator configurator = new OverrideConfigurator(URL.valueOf("override://foo@0.0.0.0/com.foo.BarService?timeout=200"));
+
+        URL url = configurator.configure(URL.valueOf(UrlConstant.URL_CONSUMER));
+        Assertions.assertEquals("200", url.getParameter("timeout"));
+
+        url = configurator.configure(URL.valueOf(UrlConstant.URL_ONE));
+        Assertions.assertEquals("200", url.getParameter("timeout"));
+
+        url = configurator.configure(URL.valueOf(UrlConstant.APPLICATION_BAR_SIDE_CONSUMER_11));
+        Assertions.assertNull(url.getParameter("timeout"));
+
+        url = configurator.configure(URL.valueOf(UrlConstant.TIMEOUT_1000_SIDE_CONSUMER_11));
+        Assertions.assertEquals("1000", url.getParameter("timeout"));
+    }
+
+    @Test
+    public void testOverride_Host() {
+        OverrideConfigurator configurator = new OverrideConfigurator(URL.valueOf("override://" + NetUtils.getLocalHost() + "/com.foo.BarService?timeout=200"));
+
+        URL url = configurator.configure(URL.valueOf(UrlConstant.URL_CONSUMER));
+        Assertions.assertEquals("200", url.getParameter("timeout"));
+
+        url = configurator.configure(URL.valueOf(UrlConstant.URL_ONE));
+        Assertions.assertEquals("200", url.getParameter("timeout"));
+
+        AbsentConfigurator configurator1 = new AbsentConfigurator(URL.valueOf("override://10.20.153.10/com.foo.BarService?timeout=200"));
+
+        url = configurator1.configure(URL.valueOf(UrlConstant.APPLICATION_BAR_SIDE_CONSUMER_10));
+        Assertions.assertNull(url.getParameter("timeout"));
+
+        url = configurator1.configure(URL.valueOf(UrlConstant.TIMEOUT_1000_SIDE_CONSUMER_10));
+        Assertions.assertEquals("1000", url.getParameter("timeout"));
+    }
+
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/MockDirInvocation.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/MockDirInvocation.java
index bc237b9..3923937 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/MockDirInvocation.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/MockDirInvocation.java
@@ -156,4 +156,4 @@ public class MockDirInvocation implements Invocation {
         return result;
     }
 
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoService.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoService.java
index 258b8c8..6c8f7ff 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoService.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoService.java
@@ -1,27 +1,27 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.filter;
-
-/**
- * <code>TestService</code>
- */
-
-public interface DemoService {
-    String sayHello(String name);
-
-    int plus(int a, int b);
-}
\ No newline at end of file
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.filter;
+
+/**
+ * <code>TestService</code>
+ */
+
+public interface DemoService {
+    String sayHello(String name);
+
+    int plus(int a, int b);
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceLocal.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceLocal.java
index e715ae6..8b92a59 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceLocal.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceLocal.java
@@ -1,43 +1,43 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.filter;
-
-/**
- * <code>TestService</code>
- */
-
-public class DemoServiceLocal implements DemoService {
-
-    public DemoServiceLocal(DemoService demoService) {
-    }
-
-    public String sayHello(String name) {
-        return name;
-    }
-
-    public int plus(int a, int b) {
-        return a + b;
-    }
-
-    public void ondisconnect() {
-
-    }
-
-    public void onconnect() {
-
-    }
-}
\ No newline at end of file
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.filter;
+
+/**
+ * <code>TestService</code>
+ */
+
+public class DemoServiceLocal implements DemoService {
+
+    public DemoServiceLocal(DemoService demoService) {
+    }
+
+    public String sayHello(String name) {
+        return name;
+    }
+
+    public int plus(int a, int b) {
+        return a + b;
+    }
+
+    public void ondisconnect() {
+
+    }
+
+    public void onconnect() {
+
+    }
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceMock.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceMock.java
index f888a1c..7b0898d 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceMock.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceMock.java
@@ -1,31 +1,31 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.filter;
-
-/**
- * MockService.java
- *
- */
-public class DemoServiceMock implements DemoService {
-    public String sayHello(String name) {
-        return name;
-    }
-
-    public int plus(int a, int b) {
-        return a + b;
-    }
-}
\ No newline at end of file
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.filter;
+
+/**
+ * MockService.java
+ *
+ */
+public class DemoServiceMock implements DemoService {
+    public String sayHello(String name) {
+        return name;
+    }
+
+    public int plus(int a, int b) {
+        return a + b;
+    }
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceStub.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceStub.java
index 02fda0a..6217ed6 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceStub.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/DemoServiceStub.java
@@ -1,35 +1,35 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.filter;
-
-/**
- * <code>TestService</code>
- */
-
-public class DemoServiceStub implements DemoService {
-
-    public DemoServiceStub(DemoService demoService) {
-    }
-
-    public String sayHello(String name) {
-        return name;
-    }
-
-    public int plus(int a, int b) {
-        return a + b;
-    }
-}
\ No newline at end of file
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.filter;
+
+/**
+ * <code>TestService</code>
+ */
+
+public class DemoServiceStub implements DemoService {
+
+    public DemoServiceStub(DemoService demoService) {
+    }
+
+    public String sayHello(String name) {
+        return name;
+    }
+
+    public int plus(int a, int b) {
+        return a + b;
+    }
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/MockService.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/MockService.java
index e01d9a4..5ae968a 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/MockService.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/filter/MockService.java
@@ -1,31 +1,31 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.filter;
-
-/**
- * MockService.java
- *
- */
-public class MockService implements DemoService {
-    public String sayHello(String name) {
-        return name;
-    }
-
-    public int plus(int a, int b) {
-        return a + b;
-    }
-}
\ No newline at end of file
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.filter;
+
+/**
+ * MockService.java
+ *
+ */
+public class MockService implements DemoService {
+    public String sayHello(String name) {
+        return name;
+    }
+
+    public int plus(int a, int b) {
+        return a + b;
+    }
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterTest.java
index 4637976..ace3cde 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterTest.java
@@ -1,348 +1,348 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.router.condition;
-
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.cluster.Router;
-import org.apache.dubbo.rpc.cluster.router.MockInvoker;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.apache.dubbo.rpc.cluster.Constants.FORCE_KEY;
-import static org.apache.dubbo.rpc.cluster.Constants.RULE_KEY;
-
-public class ConditionRouterTest {
-    private static final String LOCAL_HOST = "127.0.0.1";
-    private URL SCRIPT_URL = URL.valueOf("condition://0.0.0.0/com.foo.BarService");
-
-    @BeforeAll
-    public static void setUpBeforeClass() throws Exception {
-    }
-
-    @BeforeEach
-    public void setUp() throws Exception {
-    }
-
-    private URL getRouteUrl(String rule) {
-        return SCRIPT_URL.addParameterAndEncoded(RULE_KEY, rule);
-    }
-
-    @Test
-    public void testRoute_matchWhen() {
-        Invocation invocation = new RpcInvocation();
-
-        Router router = new ConditionRouterFactory().getRouter(getRouteUrl(" => host = 1.2.3.4"));
-        boolean matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation);
-        Assertions.assertTrue(matchWhen);
-
-        router = new ConditionRouterFactory().getRouter(getRouteUrl("host = 2.2.2.2,1.1.1.1,3.3.3.3 => host = 1.2.3.4"));
-        matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation);
-        Assertions.assertTrue(matchWhen);
-
-        router = new ConditionRouterFactory().getRouter(getRouteUrl("host = 2.2.2.2,1.1.1.1,3.3.3.3 & host !=1.1.1.1 => host = 1.2.3.4"));
-        matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation);
-        Assertions.assertFalse(matchWhen);
-
-        router = new ConditionRouterFactory().getRouter(getRouteUrl("host !=4.4.4.4 & host = 2.2.2.2,1.1.1.1,3.3.3.3 => host = 1.2.3.4"));
-        matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation);
-        Assertions.assertTrue(matchWhen);
-
-        router = new ConditionRouterFactory().getRouter(getRouteUrl("host !=4.4.4.* & host = 2.2.2.2,1.1.1.1,3.3.3.3 => host = 1.2.3.4"));
-        matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation);
-        Assertions.assertTrue(matchWhen);
-
-        router = new ConditionRouterFactory().getRouter(getRouteUrl("host = 2.2.2.2,1.1.1.*,3.3.3.3 & host != 1.1.1.1 => host = 1.2.3.4"));
-        matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation);
-        Assertions.assertFalse(matchWhen);
-
-        router = new ConditionRouterFactory().getRouter(getRouteUrl("host = 2.2.2.2,1.1.1.*,3.3.3.3 & host != 1.1.1.2 => host = 1.2.3.4"));
-        matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation);
-        Assertions.assertTrue(matchWhen);
-    }
-
-    @Test
-    public void testRoute_matchFilter() {
-        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
-        Invoker<String> invoker1 = new MockInvoker<String>(URL.valueOf(
-                "dubbo://10.20.3.3:20880/com.foo.BarService?serialization=fastjson"));
-        Invoker<String> invoker2 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST
-                + ":20880/com.foo.BarService"));
-        Invoker<String> invoker3 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST
-                + ":20880/com.foo.BarService"));
-        invokers.add(invoker1);
-        invokers.add(invoker2);
-        invokers.add(invoker3);
-
-        System.err.println("The localhost address: " + invoker2.getUrl().getAddress());
-        System.err.println(invoker3.getUrl().getAddress());
-
-        Router router1 = new ConditionRouterFactory().getRouter(getRouteUrl(
-                "host = " + LOCAL_HOST + " => " + " host = 10.20.3.3").addParameter(FORCE_KEY,
-                String.valueOf(true)));
-        Router router2 = new ConditionRouterFactory().getRouter(getRouteUrl(
-                "host = " + LOCAL_HOST + " => " + " host = 10.20.3.* & host != 10.20.3.3").addParameter(
-                FORCE_KEY, String.valueOf(true)));
-        Router router3 = new ConditionRouterFactory().getRouter(getRouteUrl(
-                "host = " + LOCAL_HOST + " => " + " host = 10.20.3.3  & host != 10.20.3.3").addParameter(
-                FORCE_KEY, String.valueOf(true)));
-        Router router4 = new ConditionRouterFactory().getRouter(getRouteUrl(
-                "host = " + LOCAL_HOST + " => " + " host = 10.20.3.2,10.20.3.3,10.20.3.4").addParameter(
-                FORCE_KEY, String.valueOf(true)));
-        Router router5 = new ConditionRouterFactory().getRouter(getRouteUrl(
-                "host = " + LOCAL_HOST + " => " + " host != 10.20.3.3").addParameter(FORCE_KEY,
-                String.valueOf(true)));
-        Router router6 = new ConditionRouterFactory().getRouter(getRouteUrl(
-                "host = " + LOCAL_HOST + " => " + " serialization = fastjson").addParameter(
-                FORCE_KEY, String.valueOf(true)));
-
-
-
-        List<Invoker<String>> filteredInvokers1 = router1.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
-        List<Invoker<String>> filteredInvokers2 = router2.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
-        List<Invoker<String>> filteredInvokers3 = router3.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
-        List<Invoker<String>> filteredInvokers4 = router4.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
-        List<Invoker<String>> filteredInvokers5 = router5.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
-        List<Invoker<String>> filteredInvokers6 = router6.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
-        Assertions.assertEquals(1, filteredInvokers1.size());
-        Assertions.assertEquals(0, filteredInvokers2.size());
-        Assertions.assertEquals(0, filteredInvokers3.size());
-        Assertions.assertEquals(1, filteredInvokers4.size());
-        Assertions.assertEquals(2, filteredInvokers5.size());
-        Assertions.assertEquals(1, filteredInvokers6.size());
-    }
-
-    @Test
-    public void testRoute_methodRoute() {
-        Invocation invocation = new RpcInvocation("getFoo", "com.foo.BarService", "", new Class<?>[0], new Object[0]);
-        // More than one methods, mismatch
-        Router router = new ConditionRouterFactory().getRouter(getRouteUrl("methods=getFoo => host = 1.2.3.4"));
-        boolean matchWhen = ((ConditionRouter) router).matchWhen(
-                URL.valueOf("consumer://1.1.1.1/com.foo.BarService?methods=setFoo,getFoo,findFoo"), invocation);
-        Assertions.assertTrue(matchWhen);
-        // Exactly one method, match
-        matchWhen = ((ConditionRouter) router).matchWhen(
-                URL.valueOf("consumer://1.1.1.1/com.foo.BarService?methods=getFoo"), invocation);
-        Assertions.assertTrue(matchWhen);
-        // Method routing and Other condition routing can work together
-        Router router2 = new ConditionRouterFactory()
-                .getRouter(getRouteUrl("methods=getFoo & host!=1.1.1.1 => host = 1.2.3.4"));
-        matchWhen = ((ConditionRouter) router2).matchWhen(
-                URL.valueOf("consumer://1.1.1.1/com.foo.BarService?methods=getFoo"), invocation);
-        Assertions.assertFalse(matchWhen);
-
-        Router router3 = new ConditionRouterFactory()
-                .getRouter(getRouteUrl("methods=getFoo & host=1.1.1.1 => host = 1.2.3.4"));
-        matchWhen = ((ConditionRouter) router3).matchWhen(
-                URL.valueOf("consumer://1.1.1.1/com.foo.BarService?methods=getFoo"), invocation);
-        Assertions.assertTrue(matchWhen);
-        // Test filter condition
-        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
-        Invoker<String> invoker1 = new MockInvoker<String>(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService"));
-        Invoker<String> invoker2 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST
-                + ":20880/com.foo.BarService"));
-        Invoker<String> invoker3 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST
-                + ":20880/com.foo.BarService"));
-        invokers.add(invoker1);
-        invokers.add(invoker2);
-        invokers.add(invoker3);
-
-        Router router4 = new ConditionRouterFactory().getRouter(getRouteUrl(
-                "host = " + LOCAL_HOST + " & methods = getFoo => " + " host = 10.20.3.3").addParameter(
-                FORCE_KEY, String.valueOf(true)));
-        List<Invoker<String>> filteredInvokers1 = router4.route(invokers,
-                URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
-        Assertions.assertEquals(1, filteredInvokers1.size());
-
-        Router router5 = new ConditionRouterFactory().getRouter(getRouteUrl(
-                "host = " + LOCAL_HOST + " & methods = unvalidmethod => " + " host = 10.20.3.3")
-                .addParameter(FORCE_KEY, String.valueOf(true)));
-        List<Invoker<String>> filteredInvokers2 = router5.route(invokers,
-                URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
-        Assertions.assertEquals(3, filteredInvokers2.size());
-        // Request a non-exists method
-    }
-
-    @Test
-    public void testRoute_ReturnFalse() {
-        Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => false"));
-        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
-        invokers.add(new MockInvoker<String>());
-        invokers.add(new MockInvoker<String>());
-        invokers.add(new MockInvoker<String>());
-        List<Invoker<String>> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
-        Assertions.assertEquals(0, filteredInvokers.size());
-    }
-
-    @Test
-    public void testRoute_ReturnEmpty() {
-        Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => "));
-        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
-        invokers.add(new MockInvoker<String>());
-        invokers.add(new MockInvoker<String>());
-        invokers.add(new MockInvoker<String>());
-        List<Invoker<String>> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
-        Assertions.assertEquals(0, filteredInvokers.size());
-    }
-
-    @Test
-    public void testRoute_ReturnAll() {
-        Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => " + " host = " + LOCAL_HOST));
-        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
-        invokers.add(new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")));
-        invokers.add(new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")));
-        invokers.add(new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")));
-        List<Invoker<String>> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
-        Assertions.assertEquals(invokers, filteredInvokers);
-    }
-
-    @Test
-    public void testRoute_HostFilter() {
-        Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => " + " host = " + LOCAL_HOST));
-        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
-        Invoker<String> invoker1 = new MockInvoker<String>(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService"));
-        Invoker<String> invoker2 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
-        Invoker<String> invoker3 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
-        invokers.add(invoker1);
-        invokers.add(invoker2);
-        invokers.add(invoker3);
-        List<Invoker<String>> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
-        Assertions.assertEquals(2, filteredInvokers.size());
-        Assertions.assertEquals(invoker2, filteredInvokers.get(0));
-        Assertions.assertEquals(invoker3, filteredInvokers.get(1));
-    }
-
-    @Test
-    public void testRoute_Empty_HostFilter() {
-        Router router = new ConditionRouterFactory().getRouter(getRouteUrl(" => " + " host = " + LOCAL_HOST));
-        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
-        Invoker<String> invoker1 = new MockInvoker<String>(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService"));
-        Invoker<String> invoker2 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
-        Invoker<String> invoker3 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
-        invokers.add(invoker1);
-        invokers.add(invoker2);
-        invokers.add(invoker3);
-        List<Invoker<String>> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
-        Assertions.assertEquals(2, filteredInvokers.size());
-        Assertions.assertEquals(invoker2, filteredInvokers.get(0));
-        Assertions.assertEquals(invoker3, filteredInvokers.get(1));
-    }
-
-    @Test
-    public void testRoute_False_HostFilter() {
-        Router router = new ConditionRouterFactory().getRouter(getRouteUrl("true => " + " host = " + LOCAL_HOST));
-        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
-        Invoker<String> invoker1 = new MockInvoker<String>(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService"));
-        Invoker<String> invoker2 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
-        Invoker<String> invoker3 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
-        invokers.add(invoker1);
-        invokers.add(invoker2);
-        invokers.add(invoker3);
-        List<Invoker<String>> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
-        Assertions.assertEquals(2, filteredInvokers.size());
-        Assertions.assertEquals(invoker2, filteredInvokers.get(0));
-        Assertions.assertEquals(invoker3, filteredInvokers.get(1));
-    }
-
-    @Test
-    public void testRoute_Placeholder() {
-        Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => " + " host = $host"));
-        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
-        Invoker<String> invoker1 = new MockInvoker<String>(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService"));
-        Invoker<String> invoker2 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
-        Invoker<String> invoker3 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
-        invokers.add(invoker1);
-        invokers.add(invoker2);
-        invokers.add(invoker3);
-        List<Invoker<String>> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
-        Assertions.assertEquals(2, filteredInvokers.size());
-        Assertions.assertEquals(invoker2, filteredInvokers.get(0));
-        Assertions.assertEquals(invoker3, filteredInvokers.get(1));
-    }
-
-    @Test
-    public void testRoute_NoForce() {
-        Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => " + " host = 1.2.3.4"));
-        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
-        Invoker<String> invoker1 = new MockInvoker<String>(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService"));
-        Invoker<String> invoker2 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
-        Invoker<String> invoker3 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
-        invokers.add(invoker1);
-        invokers.add(invoker2);
-        invokers.add(invoker3);
-        List<Invoker<String>> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
-        Assertions.assertEquals(invokers, filteredInvokers);
-    }
-
-    @Test
-    public void testRoute_Force() {
-        Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true)));
-        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
-        Invoker<String> invoker1 = new MockInvoker<String>(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService"));
-        Invoker<String> invoker2 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
-        Invoker<String> invoker3 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
-        invokers.add(invoker1);
-        invokers.add(invoker2);
-        invokers.add(invoker3);
-        List<Invoker<String>> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
-        Assertions.assertEquals(0, filteredInvokers.size());
-    }
-
-    @Test
-    public void testRoute_Arguments() {
-        Router router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments[0] = a " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true)));
-        List<Invoker<String>> invokers = new ArrayList<>();
-        Invoker<String> invoker1 = new MockInvoker<>(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService"));
-        Invoker<String> invoker2 = new MockInvoker<>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
-        Invoker<String> invoker3 = new MockInvoker<>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
-        invokers.add(invoker1);
-        invokers.add(invoker2);
-        invokers.add(invoker3);
-        RpcInvocation invocation = new RpcInvocation();
-        String p = "a";
-        invocation.setArguments(new Object[]{null});
-        List<Invoker<String>> fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
-        Assertions.assertEquals(3, fileredInvokers.size());
-
-        invocation.setArguments(new Object[]{p});
-        fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
-        Assertions.assertEquals(0, fileredInvokers.size());
-
-        router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments = b " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true)));
-        fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
-        Assertions.assertEquals(3, fileredInvokers.size());
-
-        router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments[10].inner = a " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true)));
-        fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
-        Assertions.assertEquals(3, fileredInvokers.size());
-
-        int integer = 1;
-        invocation.setArguments(new Object[]{integer});
-        router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments[0].inner = 1 " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true)));
-        fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
-        Assertions.assertEquals(0, fileredInvokers.size());
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.router.condition;
+
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.RpcInvocation;
+import org.apache.dubbo.rpc.cluster.Router;
+import org.apache.dubbo.rpc.cluster.router.MockInvoker;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.apache.dubbo.rpc.cluster.Constants.FORCE_KEY;
+import static org.apache.dubbo.rpc.cluster.Constants.RULE_KEY;
+
+public class ConditionRouterTest {
+    private static final String LOCAL_HOST = "127.0.0.1";
+    private URL SCRIPT_URL = URL.valueOf("condition://0.0.0.0/com.foo.BarService");
+
+    @BeforeAll
+    public static void setUpBeforeClass() throws Exception {
+    }
+
+    @BeforeEach
+    public void setUp() throws Exception {
+    }
+
+    private URL getRouteUrl(String rule) {
+        return SCRIPT_URL.addParameterAndEncoded(RULE_KEY, rule);
+    }
+
+    @Test
+    public void testRoute_matchWhen() {
+        Invocation invocation = new RpcInvocation();
+
+        Router router = new ConditionRouterFactory().getRouter(getRouteUrl(" => host = 1.2.3.4"));
+        boolean matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation);
+        Assertions.assertTrue(matchWhen);
+
+        router = new ConditionRouterFactory().getRouter(getRouteUrl("host = 2.2.2.2,1.1.1.1,3.3.3.3 => host = 1.2.3.4"));
+        matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation);
+        Assertions.assertTrue(matchWhen);
+
+        router = new ConditionRouterFactory().getRouter(getRouteUrl("host = 2.2.2.2,1.1.1.1,3.3.3.3 & host !=1.1.1.1 => host = 1.2.3.4"));
+        matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation);
+        Assertions.assertFalse(matchWhen);
+
+        router = new ConditionRouterFactory().getRouter(getRouteUrl("host !=4.4.4.4 & host = 2.2.2.2,1.1.1.1,3.3.3.3 => host = 1.2.3.4"));
+        matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation);
+        Assertions.assertTrue(matchWhen);
+
+        router = new ConditionRouterFactory().getRouter(getRouteUrl("host !=4.4.4.* & host = 2.2.2.2,1.1.1.1,3.3.3.3 => host = 1.2.3.4"));
+        matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation);
+        Assertions.assertTrue(matchWhen);
+
+        router = new ConditionRouterFactory().getRouter(getRouteUrl("host = 2.2.2.2,1.1.1.*,3.3.3.3 & host != 1.1.1.1 => host = 1.2.3.4"));
+        matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation);
+        Assertions.assertFalse(matchWhen);
+
+        router = new ConditionRouterFactory().getRouter(getRouteUrl("host = 2.2.2.2,1.1.1.*,3.3.3.3 & host != 1.1.1.2 => host = 1.2.3.4"));
+        matchWhen = ((ConditionRouter) router).matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), invocation);
+        Assertions.assertTrue(matchWhen);
+    }
+
+    @Test
+    public void testRoute_matchFilter() {
+        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
+        Invoker<String> invoker1 = new MockInvoker<String>(URL.valueOf(
+                "dubbo://10.20.3.3:20880/com.foo.BarService?serialization=fastjson"));
+        Invoker<String> invoker2 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST
+                + ":20880/com.foo.BarService"));
+        Invoker<String> invoker3 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST
+                + ":20880/com.foo.BarService"));
+        invokers.add(invoker1);
+        invokers.add(invoker2);
+        invokers.add(invoker3);
+
+        System.err.println("The localhost address: " + invoker2.getUrl().getAddress());
+        System.err.println(invoker3.getUrl().getAddress());
+
+        Router router1 = new ConditionRouterFactory().getRouter(getRouteUrl(
+                "host = " + LOCAL_HOST + " => " + " host = 10.20.3.3").addParameter(FORCE_KEY,
+                String.valueOf(true)));
+        Router router2 = new ConditionRouterFactory().getRouter(getRouteUrl(
+                "host = " + LOCAL_HOST + " => " + " host = 10.20.3.* & host != 10.20.3.3").addParameter(
+                FORCE_KEY, String.valueOf(true)));
+        Router router3 = new ConditionRouterFactory().getRouter(getRouteUrl(
+                "host = " + LOCAL_HOST + " => " + " host = 10.20.3.3  & host != 10.20.3.3").addParameter(
+                FORCE_KEY, String.valueOf(true)));
+        Router router4 = new ConditionRouterFactory().getRouter(getRouteUrl(
+                "host = " + LOCAL_HOST + " => " + " host = 10.20.3.2,10.20.3.3,10.20.3.4").addParameter(
+                FORCE_KEY, String.valueOf(true)));
+        Router router5 = new ConditionRouterFactory().getRouter(getRouteUrl(
+                "host = " + LOCAL_HOST + " => " + " host != 10.20.3.3").addParameter(FORCE_KEY,
+                String.valueOf(true)));
+        Router router6 = new ConditionRouterFactory().getRouter(getRouteUrl(
+                "host = " + LOCAL_HOST + " => " + " serialization = fastjson").addParameter(
+                FORCE_KEY, String.valueOf(true)));
+
+
+
+        List<Invoker<String>> filteredInvokers1 = router1.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
+        List<Invoker<String>> filteredInvokers2 = router2.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
+        List<Invoker<String>> filteredInvokers3 = router3.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
+        List<Invoker<String>> filteredInvokers4 = router4.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
+        List<Invoker<String>> filteredInvokers5 = router5.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
+        List<Invoker<String>> filteredInvokers6 = router6.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
+        Assertions.assertEquals(1, filteredInvokers1.size());
+        Assertions.assertEquals(0, filteredInvokers2.size());
+        Assertions.assertEquals(0, filteredInvokers3.size());
+        Assertions.assertEquals(1, filteredInvokers4.size());
+        Assertions.assertEquals(2, filteredInvokers5.size());
+        Assertions.assertEquals(1, filteredInvokers6.size());
+    }
+
+    @Test
+    public void testRoute_methodRoute() {
+        Invocation invocation = new RpcInvocation("getFoo", "com.foo.BarService", "", new Class<?>[0], new Object[0]);
+        // More than one methods, mismatch
+        Router router = new ConditionRouterFactory().getRouter(getRouteUrl("methods=getFoo => host = 1.2.3.4"));
+        boolean matchWhen = ((ConditionRouter) router).matchWhen(
+                URL.valueOf("consumer://1.1.1.1/com.foo.BarService?methods=setFoo,getFoo,findFoo"), invocation);
+        Assertions.assertTrue(matchWhen);
+        // Exactly one method, match
+        matchWhen = ((ConditionRouter) router).matchWhen(
+                URL.valueOf("consumer://1.1.1.1/com.foo.BarService?methods=getFoo"), invocation);
+        Assertions.assertTrue(matchWhen);
+        // Method routing and Other condition routing can work together
+        Router router2 = new ConditionRouterFactory()
+                .getRouter(getRouteUrl("methods=getFoo & host!=1.1.1.1 => host = 1.2.3.4"));
+        matchWhen = ((ConditionRouter) router2).matchWhen(
+                URL.valueOf("consumer://1.1.1.1/com.foo.BarService?methods=getFoo"), invocation);
+        Assertions.assertFalse(matchWhen);
+
+        Router router3 = new ConditionRouterFactory()
+                .getRouter(getRouteUrl("methods=getFoo & host=1.1.1.1 => host = 1.2.3.4"));
+        matchWhen = ((ConditionRouter) router3).matchWhen(
+                URL.valueOf("consumer://1.1.1.1/com.foo.BarService?methods=getFoo"), invocation);
+        Assertions.assertTrue(matchWhen);
+        // Test filter condition
+        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
+        Invoker<String> invoker1 = new MockInvoker<String>(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService"));
+        Invoker<String> invoker2 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST
+                + ":20880/com.foo.BarService"));
+        Invoker<String> invoker3 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST
+                + ":20880/com.foo.BarService"));
+        invokers.add(invoker1);
+        invokers.add(invoker2);
+        invokers.add(invoker3);
+
+        Router router4 = new ConditionRouterFactory().getRouter(getRouteUrl(
+                "host = " + LOCAL_HOST + " & methods = getFoo => " + " host = 10.20.3.3").addParameter(
+                FORCE_KEY, String.valueOf(true)));
+        List<Invoker<String>> filteredInvokers1 = router4.route(invokers,
+                URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
+        Assertions.assertEquals(1, filteredInvokers1.size());
+
+        Router router5 = new ConditionRouterFactory().getRouter(getRouteUrl(
+                "host = " + LOCAL_HOST + " & methods = unvalidmethod => " + " host = 10.20.3.3")
+                .addParameter(FORCE_KEY, String.valueOf(true)));
+        List<Invoker<String>> filteredInvokers2 = router5.route(invokers,
+                URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
+        Assertions.assertEquals(3, filteredInvokers2.size());
+        // Request a non-exists method
+    }
+
+    @Test
+    public void testRoute_ReturnFalse() {
+        Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => false"));
+        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
+        invokers.add(new MockInvoker<String>());
+        invokers.add(new MockInvoker<String>());
+        invokers.add(new MockInvoker<String>());
+        List<Invoker<String>> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
+        Assertions.assertEquals(0, filteredInvokers.size());
+    }
+
+    @Test
+    public void testRoute_ReturnEmpty() {
+        Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => "));
+        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
+        invokers.add(new MockInvoker<String>());
+        invokers.add(new MockInvoker<String>());
+        invokers.add(new MockInvoker<String>());
+        List<Invoker<String>> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
+        Assertions.assertEquals(0, filteredInvokers.size());
+    }
+
+    @Test
+    public void testRoute_ReturnAll() {
+        Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => " + " host = " + LOCAL_HOST));
+        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
+        invokers.add(new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")));
+        invokers.add(new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")));
+        invokers.add(new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService")));
+        List<Invoker<String>> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
+        Assertions.assertEquals(invokers, filteredInvokers);
+    }
+
+    @Test
+    public void testRoute_HostFilter() {
+        Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => " + " host = " + LOCAL_HOST));
+        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
+        Invoker<String> invoker1 = new MockInvoker<String>(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService"));
+        Invoker<String> invoker2 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
+        Invoker<String> invoker3 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
+        invokers.add(invoker1);
+        invokers.add(invoker2);
+        invokers.add(invoker3);
+        List<Invoker<String>> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
+        Assertions.assertEquals(2, filteredInvokers.size());
+        Assertions.assertEquals(invoker2, filteredInvokers.get(0));
+        Assertions.assertEquals(invoker3, filteredInvokers.get(1));
+    }
+
+    @Test
+    public void testRoute_Empty_HostFilter() {
+        Router router = new ConditionRouterFactory().getRouter(getRouteUrl(" => " + " host = " + LOCAL_HOST));
+        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
+        Invoker<String> invoker1 = new MockInvoker<String>(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService"));
+        Invoker<String> invoker2 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
+        Invoker<String> invoker3 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
+        invokers.add(invoker1);
+        invokers.add(invoker2);
+        invokers.add(invoker3);
+        List<Invoker<String>> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
+        Assertions.assertEquals(2, filteredInvokers.size());
+        Assertions.assertEquals(invoker2, filteredInvokers.get(0));
+        Assertions.assertEquals(invoker3, filteredInvokers.get(1));
+    }
+
+    @Test
+    public void testRoute_False_HostFilter() {
+        Router router = new ConditionRouterFactory().getRouter(getRouteUrl("true => " + " host = " + LOCAL_HOST));
+        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
+        Invoker<String> invoker1 = new MockInvoker<String>(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService"));
+        Invoker<String> invoker2 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
+        Invoker<String> invoker3 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
+        invokers.add(invoker1);
+        invokers.add(invoker2);
+        invokers.add(invoker3);
+        List<Invoker<String>> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
+        Assertions.assertEquals(2, filteredInvokers.size());
+        Assertions.assertEquals(invoker2, filteredInvokers.get(0));
+        Assertions.assertEquals(invoker3, filteredInvokers.get(1));
+    }
+
+    @Test
+    public void testRoute_Placeholder() {
+        Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => " + " host = $host"));
+        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
+        Invoker<String> invoker1 = new MockInvoker<String>(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService"));
+        Invoker<String> invoker2 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
+        Invoker<String> invoker3 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
+        invokers.add(invoker1);
+        invokers.add(invoker2);
+        invokers.add(invoker3);
+        List<Invoker<String>> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
+        Assertions.assertEquals(2, filteredInvokers.size());
+        Assertions.assertEquals(invoker2, filteredInvokers.get(0));
+        Assertions.assertEquals(invoker3, filteredInvokers.get(1));
+    }
+
+    @Test
+    public void testRoute_NoForce() {
+        Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => " + " host = 1.2.3.4"));
+        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
+        Invoker<String> invoker1 = new MockInvoker<String>(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService"));
+        Invoker<String> invoker2 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
+        Invoker<String> invoker3 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
+        invokers.add(invoker1);
+        invokers.add(invoker2);
+        invokers.add(invoker3);
+        List<Invoker<String>> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
+        Assertions.assertEquals(invokers, filteredInvokers);
+    }
+
+    @Test
+    public void testRoute_Force() {
+        Router router = new ConditionRouterFactory().getRouter(getRouteUrl("host = " + LOCAL_HOST + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true)));
+        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
+        Invoker<String> invoker1 = new MockInvoker<String>(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService"));
+        Invoker<String> invoker2 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
+        Invoker<String> invoker3 = new MockInvoker<String>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
+        invokers.add(invoker1);
+        invokers.add(invoker2);
+        invokers.add(invoker3);
+        List<Invoker<String>> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), new RpcInvocation());
+        Assertions.assertEquals(0, filteredInvokers.size());
+    }
+
+    @Test
+    public void testRoute_Arguments() {
+        Router router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments[0] = a " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true)));
+        List<Invoker<String>> invokers = new ArrayList<>();
+        Invoker<String> invoker1 = new MockInvoker<>(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService"));
+        Invoker<String> invoker2 = new MockInvoker<>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
+        Invoker<String> invoker3 = new MockInvoker<>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
+        invokers.add(invoker1);
+        invokers.add(invoker2);
+        invokers.add(invoker3);
+        RpcInvocation invocation = new RpcInvocation();
+        String p = "a";
+        invocation.setArguments(new Object[]{null});
+        List<Invoker<String>> fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
+        Assertions.assertEquals(3, fileredInvokers.size());
+
+        invocation.setArguments(new Object[]{p});
+        fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
+        Assertions.assertEquals(0, fileredInvokers.size());
+
+        router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments = b " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true)));
+        fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
+        Assertions.assertEquals(3, fileredInvokers.size());
+
+        router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments[10].inner = a " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true)));
+        fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
+        Assertions.assertEquals(3, fileredInvokers.size());
+
+        int integer = 1;
+        invocation.setArguments(new Object[]{integer});
+        router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments[0].inner = 1 " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true)));
+        fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
+        Assertions.assertEquals(0, fileredInvokers.size());
+    }
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshAppRuleListenerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshAppRuleListenerTest.java
index 8b89daa..3da5ea0 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshAppRuleListenerTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshAppRuleListenerTest.java
@@ -177,4 +177,4 @@ public class MeshAppRuleListenerTest {
         assertTrue(vsDestinationGroup1.getVirtualServiceRuleList().size() == 0);
 
     }
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManagerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManagerTest.java
index 7638c85..214a65b 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManagerTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManagerTest.java
@@ -157,4 +157,4 @@ public class MeshRuleManagerTest {
             ApplicationModel.getEnvironment().setDynamicConfiguration(before.orElse(null));
         }
     }
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactoryTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactoryTest.java
index 7bdc47a..1738093 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactoryTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterFactoryTest.java
@@ -33,4 +33,4 @@ public class MeshRuleRouterFactoryTest {
         when(url.getServiceKey()).thenReturn("demoService");
         ruleRouterFactory.getRouter(url);
     }
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterTest.java
index 8262cd6..554a875 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleRouterTest.java
@@ -1404,4 +1404,4 @@ public class MeshRuleRouterTest {
             assertNotNull(meshRuleRouter.route((List) inputInvokers, inputURL, invocation));
         }
     }
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/DestinationRuleTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/DestinationRuleTest.java
index 91f5ac7..0ddb0e2 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/DestinationRuleTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/DestinationRuleTest.java
@@ -99,4 +99,4 @@ public class DestinationRuleTest {
         }
     }
 
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/VirtualServiceRuleTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/VirtualServiceRuleTest.java
index ddfb127..9fa2098 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/VirtualServiceRuleTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/VirtualServiceRuleTest.java
@@ -35,4 +35,4 @@ public class VirtualServiceRuleTest {
         assertNotNull(virtualServiceRule);
     }
 
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboMatchRequestTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboMatchRequestTest.java
index 9bb55b4..69da8c4 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboMatchRequestTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/DubboMatchRequestTest.java
@@ -137,4 +137,4 @@ public class DubboMatchRequestTest {
 
         assertFalse(DubboMatchRequest.isMatch(dubboMatchRequest, "sayHello", new String[]{}, new Object[]{}, inputSourceLablesMap, invokeEagleEyeContextMap, invokeDubboContextMap2, new HashMap()));
     }
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatchTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatchTest.java
index 72d4774..336f5ca 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatchTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/BoolMatchTest.java
@@ -39,4 +39,4 @@ public class BoolMatchTest {
         assertTrue(BoolMatch.isMatch(boolMatch,false));
 
     }
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DoubleMatchTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DoubleMatchTest.java
index aba44bc..48dae5c 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DoubleMatchTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DoubleMatchTest.java
@@ -98,4 +98,4 @@ public class DoubleMatchTest {
         assertTrue(DoubleMatch.isMatch(doubleMatch, 3.0));
     }
 
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboAttachmentMatchTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboAttachmentMatchTest.java
index 99e704f..208f064 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboAttachmentMatchTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboAttachmentMatchTest.java
@@ -175,4 +175,4 @@ public class DubboAttachmentMatchTest {
         assertFalse(DubboAttachmentMatch.isMatch(dubboAttachmentMatch, invokeEagleEyeContextMap2, invokeDubboContextMap2));
 
     }
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboMethodMatchTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboMethodMatchTest.java
index 7c7189b..600dd8e 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboMethodMatchTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/DubboMethodMatchTest.java
@@ -153,4 +153,4 @@ public class DubboMethodMatchTest {
         assertTrue(DubboMethodMatch.isMatch(dubboMethodMatch, "test", new String[]{"int", "java.lang.String", "boolean"}, new Object[]{10, "sayHello", true}));
         assertFalse(DubboMethodMatch.isMatch(dubboMethodMatch, "test", new String[]{"int", "java.lang.String", "boolean"}, new Object[]{10, "sayHello", false}));
     }
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListDoubleMatchTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListDoubleMatchTest.java
index f3b30b1..90faaac 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListDoubleMatchTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListDoubleMatchTest.java
@@ -49,4 +49,4 @@ public class ListDoubleMatchTest {
         assertTrue(ListDoubleMatch.isMatch(listDoubleMatch, 11.0));
         assertFalse(ListDoubleMatch.isMatch(listDoubleMatch, 12.0));
     }
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListStringMatchTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListStringMatchTest.java
index 0561053..b60c439 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListStringMatchTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/ListStringMatchTest.java
@@ -51,4 +51,4 @@ public class ListStringMatchTest {
         assertFalse(ListStringMatch.isMatch(listStringMatch, "3"));
 
     }
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/StringMatchTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/StringMatchTest.java
index 13d0225..c25ab75 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/StringMatchTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/rule/virtualservice/match/StringMatchTest.java
@@ -78,4 +78,4 @@ public class StringMatchTest {
         assertFalse(StringMatch.isMatch(stringMatch, ""));
         assertFalse(StringMatch.isMatch(stringMatch, null));
     }
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleDispatcherTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleDispatcherTest.java
index 5193c8d..d108a79 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleDispatcherTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/util/VsDestinationGroupRuleDispatcherTest.java
@@ -71,4 +71,4 @@ class VsDestinationGroupRuleDispatcherTest {
 
         verify(vsDestinationGroupRuleListener, times(1)).onRuleChange(anyObject());
     }
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouterTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouterTest.java
index f52347f..fa86c00 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouterTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouterTest.java
@@ -96,15 +96,15 @@ public class ScriptRouterTest {
         invokers.add(invoker3);
 
         String script = "function route(invokers, invocation, context){ " +
-                "	var result = new java.util.ArrayList(invokers.size()); " +
-                "	var targetHost = new java.util.ArrayList(); " +
-                "	targetHost.add(\"10.134.108.2\"); " +
-                "	for (var i = 0; i < invokers.length; i++) { " +
-                "		if(targetHost.contains(invokers[i].getUrl().getHost())){ " +
-                "			result.add(invokers[i]); " +
-                "		} " +
-                "	} " +
-                "	return result; " +
+                "    var result = new java.util.ArrayList(invokers.size()); " +
+                "    var targetHost = new java.util.ArrayList(); " +
+                "    targetHost.add(\"10.134.108.2\"); " +
+                "    for (var i = 0; i < invokers.length; i++) { " +
+                "        if(targetHost.contains(invokers[i].getUrl().getHost())){ " +
+                "            result.add(invokers[i]); " +
+                "        } " +
+                "    } " +
+                "    return result; " +
                 "} " +
                 "route(invokers, invocation, context) ";
 
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailSafeClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailSafeClusterInvokerTest.java
index c666fb8..c6f45c6 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailSafeClusterInvokerTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailSafeClusterInvokerTest.java
@@ -1,122 +1,122 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.support;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.utils.LogUtil;
-import org.apache.dubbo.rpc.AppResponse;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.Result;
-import org.apache.dubbo.rpc.RpcContext;
-import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.cluster.Directory;
-import org.apache.dubbo.rpc.cluster.filter.DemoService;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.Mockito.mock;
-
-/**
- * FailfastClusterInvokerTest
- *
- */
-@SuppressWarnings("unchecked")
-public class FailSafeClusterInvokerTest {
-    List<Invoker<DemoService>> invokers = new ArrayList<Invoker<DemoService>>();
-    URL url = URL.valueOf("test://test:11/test");
-    Invoker<DemoService> invoker = mock(Invoker.class);
-    RpcInvocation invocation = new RpcInvocation();
-    Directory<DemoService> dic;
-    Result result = new AppResponse();
-
-    /**
-     * @throws java.lang.Exception
-     */
-
-    @BeforeEach
-    public void setUp() throws Exception {
-
-        dic = mock(Directory.class);
-
-        given(dic.getUrl()).willReturn(url);
-        given(dic.getConsumerUrl()).willReturn(url);
-        given(dic.list(invocation)).willReturn(invokers);
-        given(dic.getInterface()).willReturn(DemoService.class);
-        invocation.setMethodName("method1");
-
-        invokers.add(invoker);
-    }
-
-    private void resetInvokerToException() {
-        given(invoker.invoke(invocation)).willThrow(new RuntimeException());
-        given(invoker.getUrl()).willReturn(url);
-        given(invoker.getInterface()).willReturn(DemoService.class);
-    }
-
-    private void resetInvokerToNoException() {
-        given(invoker.invoke(invocation)).willReturn(result);
-        given(invoker.getUrl()).willReturn(url);
-        given(invoker.getInterface()).willReturn(DemoService.class);
-    }
-
-    //TODO assert error log
-    @Test
-    public void testInvokeExceptoin() {
-        resetInvokerToException();
-        FailsafeClusterInvoker<DemoService> invoker = new FailsafeClusterInvoker<DemoService>(dic);
-        invoker.invoke(invocation);
-        Assertions.assertNull(RpcContext.getServiceContext().getInvoker());
-    }
-
-    @Test()
-    public void testInvokeNoExceptoin() {
-
-        resetInvokerToNoException();
-
-        FailsafeClusterInvoker<DemoService> invoker = new FailsafeClusterInvoker<DemoService>(dic);
-        Result ret = invoker.invoke(invocation);
-        Assertions.assertSame(result, ret);
-    }
-
-    @Test()
-    public void testNoInvoke() {
-        dic = mock(Directory.class);
-
-        given(dic.getUrl()).willReturn(url);
-        given(dic.getConsumerUrl()).willReturn(url);
-        given(dic.list(invocation)).willReturn(null);
-        given(dic.getInterface()).willReturn(DemoService.class);
-
-        invocation.setMethodName("method1");
-
-        resetInvokerToNoException();
-
-        FailsafeClusterInvoker<DemoService> invoker = new FailsafeClusterInvoker<DemoService>(dic);
-        LogUtil.start();
-        invoker.invoke(invocation);
-        assertTrue(LogUtil.findMessage("No provider") > 0);
-        LogUtil.stop();
-    }
-
-}
\ No newline at end of file
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.support;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.LogUtil;
+import org.apache.dubbo.rpc.AppResponse;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcContext;
+import org.apache.dubbo.rpc.RpcInvocation;
+import org.apache.dubbo.rpc.cluster.Directory;
+import org.apache.dubbo.rpc.cluster.filter.DemoService;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.mock;
+
+/**
+ * FailfastClusterInvokerTest
+ *
+ */
+@SuppressWarnings("unchecked")
+public class FailSafeClusterInvokerTest {
+    List<Invoker<DemoService>> invokers = new ArrayList<Invoker<DemoService>>();
+    URL url = URL.valueOf("test://test:11/test");
+    Invoker<DemoService> invoker = mock(Invoker.class);
+    RpcInvocation invocation = new RpcInvocation();
+    Directory<DemoService> dic;
+    Result result = new AppResponse();
+
+    /**
+     * @throws java.lang.Exception
+     */
+
+    @BeforeEach
+    public void setUp() throws Exception {
+
+        dic = mock(Directory.class);
+
+        given(dic.getUrl()).willReturn(url);
+        given(dic.getConsumerUrl()).willReturn(url);
+        given(dic.list(invocation)).willReturn(invokers);
+        given(dic.getInterface()).willReturn(DemoService.class);
+        invocation.setMethodName("method1");
+
+        invokers.add(invoker);
+    }
+
+    private void resetInvokerToException() {
+        given(invoker.invoke(invocation)).willThrow(new RuntimeException());
+        given(invoker.getUrl()).willReturn(url);
+        given(invoker.getInterface()).willReturn(DemoService.class);
+    }
+
+    private void resetInvokerToNoException() {
+        given(invoker.invoke(invocation)).willReturn(result);
+        given(invoker.getUrl()).willReturn(url);
+        given(invoker.getInterface()).willReturn(DemoService.class);
+    }
+
+    //TODO assert error log
+    @Test
+    public void testInvokeExceptoin() {
+        resetInvokerToException();
+        FailsafeClusterInvoker<DemoService> invoker = new FailsafeClusterInvoker<DemoService>(dic);
+        invoker.invoke(invocation);
+        Assertions.assertNull(RpcContext.getServiceContext().getInvoker());
+    }
+
+    @Test()
+    public void testInvokeNoExceptoin() {
+
+        resetInvokerToNoException();
+
+        FailsafeClusterInvoker<DemoService> invoker = new FailsafeClusterInvoker<DemoService>(dic);
+        Result ret = invoker.invoke(invocation);
+        Assertions.assertSame(result, ret);
+    }
+
+    @Test()
+    public void testNoInvoke() {
+        dic = mock(Directory.class);
+
+        given(dic.getUrl()).willReturn(url);
+        given(dic.getConsumerUrl()).willReturn(url);
+        given(dic.list(invocation)).willReturn(null);
+        given(dic.getInterface()).willReturn(DemoService.class);
+
+        invocation.setMethodName("method1");
+
+        resetInvokerToNoException();
+
+        FailsafeClusterInvoker<DemoService> invoker = new FailsafeClusterInvoker<DemoService>(dic);
+        LogUtil.start();
+        invoker.invoke(invocation);
+        assertTrue(LogUtil.findMessage("No provider") > 0);
+        LogUtil.stop();
+    }
+
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvokerTest.java
index 84747b7..032c1c7 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvokerTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvokerTest.java
@@ -1,177 +1,177 @@
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.support;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.utils.DubboAppender;
-import org.apache.dubbo.common.utils.LogUtil;
-import org.apache.dubbo.rpc.AppResponse;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.Result;
-import org.apache.dubbo.rpc.RpcContext;
-import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.cluster.Directory;
-
-import org.apache.log4j.Level;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.MethodOrderer;
-import org.junit.jupiter.api.Order;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestMethodOrder;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.Mockito.mock;
-
-/**
- * FailbackClusterInvokerTest
- * <p>
- * add annotation @TestMethodOrder, the testARetryFailed Method must to first execution
- */
-@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
-public class FailbackClusterInvokerTest {
-
-    List<Invoker<FailbackClusterInvokerTest>> invokers = new ArrayList<Invoker<FailbackClusterInvokerTest>>();
-    URL url = URL.valueOf("test://test:11/test?retries=2&failbacktasks=2");
-    Invoker<FailbackClusterInvokerTest> invoker = mock(Invoker.class);
-    RpcInvocation invocation = new RpcInvocation();
-    Directory<FailbackClusterInvokerTest> dic;
-    Result result = new AppResponse();
-
-    /**
-     * @throws java.lang.Exception
-     */
-
-    @BeforeEach
-    public void setUp() throws Exception {
-
-        dic = mock(Directory.class);
-        given(dic.getUrl()).willReturn(url);
-        given(dic.getConsumerUrl()).willReturn(url);
-        given(dic.list(invocation)).willReturn(invokers);
-        given(dic.getInterface()).willReturn(FailbackClusterInvokerTest.class);
-
-        invocation.setMethodName("method1");
-
-        invokers.add(invoker);
-    }
-
-    @AfterEach
-    public void tearDown() {
-
-        dic = null;
-        invocation = new RpcInvocation();
-        invokers.clear();
-    }
-
-
-    private void resetInvokerToException() {
-        given(invoker.invoke(invocation)).willThrow(new RuntimeException());
-        given(invoker.getUrl()).willReturn(url);
-        given(invoker.getInterface()).willReturn(FailbackClusterInvokerTest.class);
-    }
-
-    private void resetInvokerToNoException() {
-        given(invoker.invoke(invocation)).willReturn(result);
-        given(invoker.getUrl()).willReturn(url);
-        given(invoker.getInterface()).willReturn(FailbackClusterInvokerTest.class);
-    }
-
-    @Test
-    @Order(1)
-    public void testInvokeException() {
-        resetInvokerToException();
-        FailbackClusterInvoker<FailbackClusterInvokerTest> invoker = new FailbackClusterInvoker<FailbackClusterInvokerTest>(
-                dic);
-        invoker.invoke(invocation);
-        Assertions.assertNull(RpcContext.getServiceContext().getInvoker());
-        DubboAppender.clear();
-    }
-
-    @Test
-    @Order(2)
-    public void testInvokeNoException() {
-
-        resetInvokerToNoException();
-
-        FailbackClusterInvoker<FailbackClusterInvokerTest> invoker = new FailbackClusterInvoker<FailbackClusterInvokerTest>(
-                dic);
-        Result ret = invoker.invoke(invocation);
-        Assertions.assertSame(result, ret);
-    }
-
-    @Test
-    @Order(3)
-    public void testNoInvoke() {
-        dic = mock(Directory.class);
-
-        given(dic.getUrl()).willReturn(url);
-        given(dic.getConsumerUrl()).willReturn(url);
-        given(dic.list(invocation)).willReturn(null);
-        given(dic.getInterface()).willReturn(FailbackClusterInvokerTest.class);
-
-        invocation.setMethodName("method1");
-
-        invokers.add(invoker);
-
-        resetInvokerToNoException();
-
-        FailbackClusterInvoker<FailbackClusterInvokerTest> invoker = new FailbackClusterInvoker<FailbackClusterInvokerTest>(
-                dic);
-        LogUtil.start();
-        DubboAppender.clear();
-        invoker.invoke(invocation);
-        assertEquals(1, LogUtil.findMessage("Failback to invoke"));
-        LogUtil.stop();
-    }
-
-    @Disabled
-    @Test
-    @Order(4)
-    public void testARetryFailed() throws Exception {
-        //Test retries and
-
-        resetInvokerToException();
-
-        FailbackClusterInvoker<FailbackClusterInvokerTest> invoker = new FailbackClusterInvoker<FailbackClusterInvokerTest>(
-                dic);
-        LogUtil.start();
-        DubboAppender.clear();
-        invoker.invoke(invocation);
-        invoker.invoke(invocation);
-        invoker.invoke(invocation);
-        Assertions.assertNull(RpcContext.getServiceContext().getInvoker());
-//        invoker.retryFailed();// when retry the invoker which get from failed map already is not the mocked invoker,so
-        //Ensure that the main thread is online
-        CountDownLatch countDown = new CountDownLatch(1);
-        countDown.await(15000L, TimeUnit.MILLISECONDS);
-        LogUtil.stop();
-        Assertions.assertEquals(4, LogUtil.findMessage(Level.ERROR, "Failed retry to invoke method"), "must have four error message ");
-        Assertions.assertEquals(2, LogUtil.findMessage(Level.ERROR, "Failed retry times exceed threshold"), "must have two error message ");
-        Assertions.assertEquals(1, LogUtil.findMessage(Level.ERROR, "Failback background works error"), "must have one error message ");
-        // it can be invoke successfully
-    }
-}
\ No newline at end of file
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.cluster.support;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.DubboAppender;
+import org.apache.dubbo.common.utils.LogUtil;
+import org.apache.dubbo.rpc.AppResponse;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcContext;
+import org.apache.dubbo.rpc.RpcInvocation;
+import org.apache.dubbo.rpc.cluster.Directory;
+
+import org.apache.log4j.Level;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.mock;
+
+/**
+ * FailbackClusterInvokerTest
+ * <p>
+ * add annotation @TestMethodOrder, the testARetryFailed Method must to first execution
+ */
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+public class FailbackClusterInvokerTest {
+
+    List<Invoker<FailbackClusterInvokerTest>> invokers = new ArrayList<Invoker<FailbackClusterInvokerTest>>();
+    URL url = URL.valueOf("test://test:11/test?retries=2&failbacktasks=2");
+    Invoker<FailbackClusterInvokerTest> invoker = mock(Invoker.class);
+    RpcInvocation invocation = new RpcInvocation();
+    Directory<FailbackClusterInvokerTest> dic;
+    Result result = new AppResponse();
+
+    /**
+     * @throws java.lang.Exception
+     */
+
+    @BeforeEach
+    public void setUp() throws Exception {
+
+        dic = mock(Directory.class);
+        given(dic.getUrl()).willReturn(url);
+        given(dic.getConsumerUrl()).willReturn(url);
+        given(dic.list(invocation)).willReturn(invokers);
+        given(dic.getInterface()).willReturn(FailbackClusterInvokerTest.class);
+
+        invocation.setMethodName("method1");
+
+        invokers.add(invoker);
+    }
+
+    @AfterEach
+    public void tearDown() {
+
+        dic = null;
+        invocation = new RpcInvocation();
+        invokers.clear();
+    }
+
+
+    private void resetInvokerToException() {
+        given(invoker.invoke(invocation)).willThrow(new RuntimeException());
+        given(invoker.getUrl()).willReturn(url);
+        given(invoker.getInterface()).willReturn(FailbackClusterInvokerTest.class);
+    }
+
+    private void resetInvokerToNoException() {
+        given(invoker.invoke(invocation)).willReturn(result);
+        given(invoker.getUrl()).willReturn(url);
+        given(invoker.getInterface()).willReturn(FailbackClusterInvokerTest.class);
+    }
+
+    @Test
+    @Order(1)
+    public void testInvokeException() {
+        resetInvokerToException();
+        FailbackClusterInvoker<FailbackClusterInvokerTest> invoker = new FailbackClusterInvoker<FailbackClusterInvokerTest>(
+                dic);
+        invoker.invoke(invocation);
+        Assertions.assertNull(RpcContext.getServiceContext().getInvoker());
+        DubboAppender.clear();
+    }
+
+    @Test
+    @Order(2)
+    public void testInvokeNoException() {
+
+        resetInvokerToNoException();
+
+        FailbackClusterInvoker<FailbackClusterInvokerTest> invoker = new FailbackClusterInvoker<FailbackClusterInvokerTest>(
+                dic);
+        Result ret = invoker.invoke(invocation);
+        Assertions.assertSame(result, ret);
+    }
+
+    @Test
+    @Order(3)
+    public void testNoInvoke() {
+        dic = mock(Directory.class);
+
+        given(dic.getUrl()).willReturn(url);
+        given(dic.getConsumerUrl()).willReturn(url);
+        given(dic.list(invocation)).willReturn(null);
+        given(dic.getInterface()).willReturn(FailbackClusterInvokerTest.class);
+
+        invocation.setMethodName("method1");
+
+        invokers.add(invoker);
+
+        resetInvokerToNoException();
+
+        FailbackClusterInvoker<FailbackClusterInvokerTest> invoker = new FailbackClusterInvoker<FailbackClusterInvokerTest>(
+                dic);
+        LogUtil.start();
+        DubboAppender.clear();
+        invoker.invoke(invocation);
+        assertEquals(1, LogUtil.findMessage("Failback to invoke"));
+        LogUtil.stop();
+    }
+
+    @Disabled
+    @Test
+    @Order(4)
+    public void testARetryFailed() throws Exception {
+        //Test retries and
+
+        resetInvokerToException();
+
+        FailbackClusterInvoker<FailbackClusterInvokerTest> invoker = new FailbackClusterInvoker<FailbackClusterInvokerTest>(
+                dic);
+        LogUtil.start();
+        DubboAppender.clear();
+        invoker.invoke(invocation);
+        invoker.invoke(invocation);
+        invoker.invoke(invocation);
+        Assertions.assertNull(RpcContext.getServiceContext().getInvoker());
+//        invoker.retryFailed();// when retry the invoker which get from failed map already is not the mocked invoker,so
+        //Ensure that the main thread is online
+        CountDownLatch countDown = new CountDownLatch(1);
+        countDown.await(15000L, TimeUnit.MILLISECONDS);
+        LogUtil.stop();
+        Assertions.assertEquals(4, LogUtil.findMessage(Level.ERROR, "Failed retry to invoke method"), "must have four error message ");
+        Assertions.assertEquals(2, LogUtil.findMessage(Level.ERROR, "Failed retry times exceed threshold"), "must have two error message ");
+        Assertions.assertEquals(1, LogUtil.findMessage(Level.ERROR, "Failback background works error"), "must have one error message ");
+        // it can be invoke successfully
+    }
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvokerTest.java
index 459dcfc..525f898 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvokerTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvokerTest.java
@@ -124,4 +124,4 @@ public class FailfastClusterInvokerTest {
         }
     }
 
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvokerTest.java
index a162526..b2742fb 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvokerTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvokerTest.java
@@ -1,290 +1,290 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.rpc.cluster.support;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.rpc.AppResponse;
-import org.apache.dubbo.rpc.AsyncRpcResult;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.Result;
-import org.apache.dubbo.rpc.RpcContext;
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.cluster.Directory;
-import org.apache.dubbo.rpc.cluster.directory.StaticDirectory;
-import org.apache.dubbo.rpc.protocol.AbstractInvoker;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Callable;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertSame;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.Mockito.mock;
-
-/**
- * FailoverClusterInvokerTest
- *
- */
-@SuppressWarnings("unchecked")
-public class FailoverClusterInvokerTest {
-    private List<Invoker<FailoverClusterInvokerTest>> invokers = new ArrayList<Invoker<FailoverClusterInvokerTest>>();
-    private int retries = 5;
-    private URL url = URL.valueOf("test://test:11/test?retries=" + retries);
-    private Invoker<FailoverClusterInvokerTest> invoker1 = mock(Invoker.class);
-    private Invoker<FailoverClusterInvokerTest> invoker2 = mock(Invoker.class);
-    private RpcInvocation invocation = new RpcInvocation();
-    private Directory<FailoverClusterInvokerTest> dic;
-    private Result result = new AppResponse();
-
-    /**
-     * @throws java.lang.Exception
-     */
-
-    @BeforeEach
-    public void setUp() throws Exception {
-
-        dic = mock(Directory.class);
-
-        given(dic.getUrl()).willReturn(url);
-        given(dic.getConsumerUrl()).willReturn(url);
-        given(dic.list(invocation)).willReturn(invokers);
-        given(dic.getInterface()).willReturn(FailoverClusterInvokerTest.class);
-        invocation.setMethodName("method1");
-
-        invokers.add(invoker1);
-        invokers.add(invoker2);
-    }
-
-
-    @Test
-    public void testInvokeWithRuntimeException() {
-        given(invoker1.invoke(invocation)).willThrow(new RuntimeException());
-        given(invoker1.isAvailable()).willReturn(true);
-        given(invoker1.getUrl()).willReturn(url);
-        given(invoker1.getInterface()).willReturn(FailoverClusterInvokerTest.class);
-
-        given(invoker2.invoke(invocation)).willThrow(new RuntimeException());
-        given(invoker2.isAvailable()).willReturn(true);
-        given(invoker2.getUrl()).willReturn(url);
-        given(invoker2.getInterface()).willReturn(FailoverClusterInvokerTest.class);
-
-        FailoverClusterInvoker<FailoverClusterInvokerTest> invoker = new FailoverClusterInvoker<FailoverClusterInvokerTest>(dic);
-        try {
-            invoker.invoke(invocation);
-            fail();
-        } catch (RpcException expected) {
-            assertEquals(0, expected.getCode());
-            assertFalse(expected.getCause() instanceof RpcException);
-        }
-    }
-
-    @Test()
-    public void testInvokeWithRPCException() {
-        given(invoker1.invoke(invocation)).willThrow(new RpcException());
-        given(invoker1.isAvailable()).willReturn(true);
-        given(invoker1.getUrl()).willReturn(url);
-        given(invoker1.getInterface()).willReturn(FailoverClusterInvokerTest.class);
-
-        given(invoker2.invoke(invocation)).willReturn(result);
-        given(invoker2.isAvailable()).willReturn(true);
-        given(invoker2.getUrl()).willReturn(url);
-        given(invoker2.getInterface()).willReturn(FailoverClusterInvokerTest.class);
-
-        FailoverClusterInvoker<FailoverClusterInvokerTest> invoker = new FailoverClusterInvoker<FailoverClusterInvokerTest>(dic);
-        for (int i = 0; i < 100; i++) {
-            Result ret = invoker.invoke(invocation);
-            assertSame(result, ret);
-        }
-    }
-
-    @Test()
-    public void testInvoke_retryTimes() {
-        given(invoker1.invoke(invocation)).willThrow(new RpcException(RpcException.TIMEOUT_EXCEPTION));
-        given(invoker1.isAvailable()).willReturn(false);
-        given(invoker1.getUrl()).willReturn(url);
-        given(invoker1.getInterface()).willReturn(FailoverClusterInvokerTest.class);
-
-        given(invoker2.invoke(invocation)).willThrow(new RpcException());
-        given(invoker2.isAvailable()).willReturn(false);
-        given(invoker2.getUrl()).willReturn(url);
-        given(invoker2.getInterface()).willReturn(FailoverClusterInvokerTest.class);
-
-        FailoverClusterInvoker<FailoverClusterInvokerTest> invoker = new FailoverClusterInvoker<FailoverClusterInvokerTest>(dic);
-        try {
-            Result ret = invoker.invoke(invocation);
-            assertSame(result, ret);
-            fail();
-        } catch (RpcException expected) {
-            assertTrue((expected.isTimeout() || expected.getCode() == 0));
-            assertTrue(expected.getMessage().indexOf((retries + 1) + " times") > 0);
-        }
-    }
-
-    @Test()
-    public void testInvoke_retryTimes2() {
-        int finalRetries = 1;
-        given(invoker1.invoke(invocation)).willThrow(new RpcException(RpcException.TIMEOUT_EXCEPTION));
-        given(invoker1.isAvailable()).willReturn(false);
-        given(invoker1.getUrl()).willReturn(url);
-        given(invoker1.getInterface()).willReturn(FailoverClusterInvokerTest.class);
-
-        given(invoker2.invoke(invocation)).willThrow(new RpcException());
-        given(invoker2.isAvailable()).willReturn(false);
-        given(invoker2.getUrl()).willReturn(url);
-        given(invoker2.getInterface()).willReturn(FailoverClusterInvokerTest.class);
-
-        RpcContext rpcContext = RpcContext.getContext();
-        rpcContext.setAttachment("retries", finalRetries);
-
... 80758 lines suppressed ...