Refactor migration

This commit is contained in:
ken.lj 2020-08-27 14:43:10 +08:00
parent 4428b93e83
commit 346166e674
19 changed files with 237 additions and 125 deletions

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.registry.integration;
package org.apache.dubbo.registry.client.migration;
import org.apache.dubbo.rpc.cluster.ClusterInvoker;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.registry.integration;
package org.apache.dubbo.registry.client.migration;
public interface InvokersChangedListener {
void onChange();

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.registry.integration;
package org.apache.dubbo.registry.client.migration;
import org.apache.dubbo.common.extension.SPI;
import org.apache.dubbo.rpc.cluster.ClusterInvoker;

View File

@ -0,0 +1,38 @@
/*
* 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.registry.client.migration;
import org.apache.dubbo.registry.client.migration.model.MigrationStep;
import org.apache.dubbo.rpc.cluster.ClusterInvoker;
/**
* FIXME, some methods need to be further optimized.
*
* @param <T>
*/
public interface MigrationClusterInvoker<T> extends ClusterInvoker<T> {
boolean isServiceDiscovery();
MigrationStep getCurrentStep();
boolean invokersChanged();
void fallbackToInterfaceInvoker();
void migrateToServiceDiscoveryInvoker(boolean forceMigrate);
}

View File

@ -14,12 +14,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.registry.integration;
package org.apache.dubbo.registry.client.migration;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.registry.Registry;
import org.apache.dubbo.registry.client.RegistryProtocol;
import org.apache.dubbo.registry.client.migration.model.MigrationStep;
import org.apache.dubbo.registry.integration.DynamicDirectory;
import org.apache.dubbo.registry.integration.RegistryProtocol;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
@ -29,7 +31,7 @@ import org.apache.dubbo.rpc.cluster.Directory;
import java.util.Set;
public class MigrationInvoker<T> implements ClusterInvoker<T> {
public class MigrationInvoker<T> implements MigrationClusterInvoker<T> {
private URL url;
private Cluster cluster;
@ -85,18 +87,8 @@ public class MigrationInvoker<T> implements ClusterInvoker<T> {
return type;
}
private boolean forceMigrate;
public boolean isForceMigrate() {
return forceMigrate;
}
public void setForceMigrate(boolean forceMigrate) {
this.forceMigrate = forceMigrate;
}
@Override
public synchronized void migrateToServiceDiscoveryInvoker(boolean forceMigrate) {
setForceMigrate(forceMigrate);
if (!forceMigrate) {
refreshServiceDiscoveryInvoker();
refreshInterfaceInvoker();
@ -110,63 +102,12 @@ public class MigrationInvoker<T> implements ClusterInvoker<T> {
}
}
private synchronized void checkAddresses() {
Set<MigrationAddressComparator> detectors = ExtensionLoader.getExtensionLoader(MigrationAddressComparator.class).getSupportedExtensionInstances();
if (detectors != null && detectors.stream().allMatch(migrationDetector -> migrationDetector.shouldMigrate(serviceDiscoveryInvoker, invoker))) {
discardInterfaceInvokerAddress();
} else {
discardServiceDiscoveryInvokerAddress();
}
}
@Override
public synchronized void fallbackToInterfaceInvoker() {
refreshInterfaceInvoker();
destroyServiceDiscoveryInvoker();
}
protected synchronized void destroyServiceDiscoveryInvoker() {
if (serviceDiscoveryInvoker != null) {
serviceDiscoveryInvoker.destroy();
serviceDiscoveryInvoker = null;
}
}
protected synchronized void discardServiceDiscoveryInvokerAddress() {
if (serviceDiscoveryInvoker != null) {
serviceDiscoveryInvoker.getDirectory().discordAddresses();
}
}
protected synchronized void refreshServiceDiscoveryInvoker() {
if (needRefresh(serviceDiscoveryInvoker)) {
serviceDiscoveryInvoker = registryProtocol.getServiceDiscoveryInvoker(cluster, registry, type, url);
}
}
protected synchronized void refreshInterfaceInvoker() {
if (needRefresh(invoker)) {
// FIXME invoker.destroy();
invoker = registryProtocol.getInvoker(cluster, registry, type, url);
}
}
protected synchronized void destroyInterfaceInvoker() {
if (invoker != null) {
invoker.destroy();
invoker = null;
}
}
protected synchronized void discardInterfaceInvokerAddress() {
if (invoker != null) {
invoker.getDirectory().discordAddresses();
}
}
private boolean needRefresh(ClusterInvoker<T> invoker) {
return invoker == null || invoker.isDestroyed() || !invoker.isAvailable();
}
@Override
public Result invoke(Invocation invocation) throws RpcException {
if (needRefresh(serviceDiscoveryInvoker)) {
@ -225,4 +166,73 @@ public class MigrationInvoker<T> implements ClusterInvoker<T> {
return (invoker == null || invoker.isDestroyed())
&& (serviceDiscoveryInvoker == null || serviceDiscoveryInvoker.isDestroyed());
}
@Override
public boolean isServiceDiscovery() {
return false;
}
@Override
public MigrationStep getCurrentStep() {
return null;
}
@Override
public boolean invokersChanged() {
return false;
}
private synchronized void checkAddresses() {
Set<MigrationAddressComparator> detectors = ExtensionLoader.getExtensionLoader(MigrationAddressComparator.class).getSupportedExtensionInstances();
if (detectors != null && detectors.stream().allMatch(migrationDetector -> migrationDetector.shouldMigrate(serviceDiscoveryInvoker, invoker))) {
discardInterfaceInvokerAddress();
} else {
discardServiceDiscoveryInvokerAddress();
}
}
protected synchronized void destroyServiceDiscoveryInvoker() {
if (serviceDiscoveryInvoker != null) {
serviceDiscoveryInvoker.destroy();
serviceDiscoveryInvoker = null;
}
}
protected synchronized void discardServiceDiscoveryInvokerAddress() {
if (serviceDiscoveryInvoker != null) {
serviceDiscoveryInvoker.getDirectory().discordAddresses();
}
}
protected synchronized void refreshServiceDiscoveryInvoker() {
if (needRefresh(serviceDiscoveryInvoker)) {
serviceDiscoveryInvoker = registryProtocol.getServiceDiscoveryInvoker(cluster, registry, type, url);
}
}
protected synchronized void refreshInterfaceInvoker() {
if (needRefresh(invoker)) {
// FIXME invoker.destroy();
invoker = registryProtocol.getInvoker(cluster, registry, type, url);
}
}
protected synchronized void destroyInterfaceInvoker() {
if (invoker != null) {
invoker.destroy();
invoker = null;
}
}
protected synchronized void discardInterfaceInvokerAddress() {
if (invoker != null) {
invoker.getDirectory().discordAddresses();
}
}
private boolean needRefresh(ClusterInvoker<T> invoker) {
return invoker == null || invoker.isDestroyed() || !invoker.isAvailable();
}
}

View File

@ -14,30 +14,31 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.registry.integration;
package org.apache.dubbo.registry.client.migration;
import org.apache.dubbo.common.config.ConfigurationUtils;
import org.apache.dubbo.common.extension.Activate;
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.registry.client.RegistryProtocol;
import org.apache.dubbo.registry.client.migration.model.MigrationRule;
import org.apache.dubbo.registry.client.migration.model.MigrationStep;
import static org.apache.dubbo.common.constants.RegistryConstants.INIT;
@Activate
public class MigrationRuleListener<T> {
private static final Logger logger = LoggerFactory.getLogger(MigrationRuleListener.class);
public class MigrationRuleHandler<T> {
private static final Logger logger = LoggerFactory.getLogger(MigrationRuleHandler.class);
private static final String DUBBO_SERVICEDISCOVERY_MIGRATION = "dubbo.application.service-discovery.migration";
private MigrationInvoker<T> migrationInvoker;
public MigrationRuleListener(MigrationInvoker<T> invoker) {
public MigrationRuleHandler(MigrationInvoker<T> invoker) {
this.migrationInvoker = invoker;
}
public void doMigrate(String rawRule) {
MigrationStep step = (migrationInvoker instanceof RegistryProtocol.ServiceDiscoveryMigrationInvoker)
MigrationStep step = (migrationInvoker instanceof ServiceDiscoveryMigrationInvoker)
? MigrationStep.FORCE_APPLICATION
: MigrationStep.INTERFACE_FIRST;
if (StringUtils.isEmpty(rawRule)) {

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.registry.client;
package org.apache.dubbo.registry.client.migration;
import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent;
import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
@ -25,8 +25,7 @@ import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.ConcurrentHashSet;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.registry.integration.MigrationInvoker;
import org.apache.dubbo.registry.integration.MigrationRuleListener;
import org.apache.dubbo.registry.integration.RegistryProtocol;
import org.apache.dubbo.registry.integration.RegistryProtocolListener;
import org.apache.dubbo.rpc.Exporter;
import org.apache.dubbo.rpc.Invoker;
@ -37,17 +36,17 @@ import java.util.Set;
import static org.apache.dubbo.common.constants.RegistryConstants.INIT;
@Activate
public class ServiceDiscoveryRegistryProtocolListener implements RegistryProtocolListener, ConfigurationListener {
private static final Logger logger = LoggerFactory.getLogger(ServiceDiscoveryRegistryProtocolListener.class);
public class MigrationRuleListener implements RegistryProtocolListener, ConfigurationListener {
private static final Logger logger = LoggerFactory.getLogger(MigrationRuleListener.class);
private static final String RULE_KEY = ApplicationModel.getName() + ".migration";
private static final String DUBBO_SERVICEDISCOVERY_MIGRATION = "DUBBO_SERVICEDISCOVERY_MIGRATION";
private Set<MigrationRuleListener> listeners = new ConcurrentHashSet<>();
private Set<MigrationRuleHandler> listeners = new ConcurrentHashSet<>();
private DynamicConfiguration configuration;
private volatile String rawRule;
public ServiceDiscoveryRegistryProtocolListener() {
public MigrationRuleListener() {
this.configuration = ApplicationModel.getEnvironment().getDynamicConfiguration().orElseGet(null);
configuration.addListener(RULE_KEY, DUBBO_SERVICEDISCOVERY_MIGRATION, this);
@ -81,7 +80,7 @@ public class ServiceDiscoveryRegistryProtocolListener implements RegistryProtoco
public synchronized <T> void onRefer(RegistryProtocol registryProtocol, Invoker<T> invoker) {
MigrationInvoker<T> migrationInvoker = (MigrationInvoker<T>) invoker;
MigrationRuleListener<T> migrationListener = new MigrationRuleListener<>(migrationInvoker);
MigrationRuleHandler<T> migrationListener = new MigrationRuleHandler<>(migrationInvoker);
listeners.add(migrationListener);
migrationListener.doMigrate(rawRule);

View File

@ -0,0 +1,52 @@
/*
* 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.registry.client.migration;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.registry.Registry;
import org.apache.dubbo.registry.integration.RegistryProtocol;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.cluster.Cluster;
import org.apache.dubbo.rpc.cluster.ClusterInvoker;
public class ServiceDiscoveryMigrationInvoker<T> extends MigrationInvoker<T> {
public ServiceDiscoveryMigrationInvoker(RegistryProtocol registryProtocol, Cluster cluster, Registry registry, Class<T> type, URL url) {
super(registryProtocol, cluster, registry, type, url);
}
@Override
public synchronized void fallbackToInterfaceInvoker() {
destroyServiceDiscoveryInvoker();
}
@Override
public synchronized void migrateToServiceDiscoveryInvoker(boolean forceMigrate) {
refreshServiceDiscoveryInvoker();
}
@Override
public Result invoke(Invocation invocation) throws RpcException {
ClusterInvoker<T> invoker = getServiceDiscoveryInvoker();
if (invoker == null) {
throw new IllegalStateException("There's no service discovery invoker available for service " + invocation.getServiceName());
}
return invoker.invoke(invocation);
}
}

View File

@ -14,11 +14,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.registry.integration;
package org.apache.dubbo.registry.client.migration.model;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
/**
* # key = demo-consumer.migration
* # group = DUBBO_SERVICEDISCOVERY_MIGRATION
* # content
* key: demo-consumer
* step: APPLICATION_FIRST
*/
public class MigrationRule {
private String key;
private MigrationStep step;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.registry.integration;
package org.apache.dubbo.registry.client.migration.model;
public enum MigrationStep {
INTERFACE_FIRST,

View File

@ -26,6 +26,7 @@ import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.registry.NotifyListener;
import org.apache.dubbo.registry.Registry;
import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener;
import org.apache.dubbo.registry.client.migration.InvokersChangedListener;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Protocol;

View File

@ -19,8 +19,8 @@ package org.apache.dubbo.registry.integration;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.URLBuilder;
import org.apache.dubbo.registry.Registry;
import org.apache.dubbo.registry.client.RegistryProtocol;
import org.apache.dubbo.registry.client.ServiceDiscoveryRegistryDirectory;
import org.apache.dubbo.registry.client.migration.MigrationInvoker;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.cluster.Cluster;
import org.apache.dubbo.rpc.cluster.ClusterInvoker;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.registry.client;
package org.apache.dubbo.registry.integration;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.ConfigurationUtils;
@ -31,21 +31,15 @@ import org.apache.dubbo.registry.NotifyListener;
import org.apache.dubbo.registry.Registry;
import org.apache.dubbo.registry.RegistryFactory;
import org.apache.dubbo.registry.RegistryService;
import org.apache.dubbo.registry.integration.AbstractConfiguratorListener;
import org.apache.dubbo.registry.integration.DynamicDirectory;
import org.apache.dubbo.registry.integration.InterfaceCompatibleRegistryProtocol;
import org.apache.dubbo.registry.integration.MigrationInvoker;
import org.apache.dubbo.registry.integration.RegistryDirectory;
import org.apache.dubbo.registry.integration.RegistryProtocolListener;
import org.apache.dubbo.registry.client.ServiceDiscoveryRegistryDirectory;
import org.apache.dubbo.registry.client.migration.ServiceDiscoveryMigrationInvoker;
import org.apache.dubbo.registry.retry.ReExportTask;
import org.apache.dubbo.registry.support.SkipFailbackWrapperException;
import org.apache.dubbo.rpc.Exporter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Protocol;
import org.apache.dubbo.rpc.ProtocolServer;
import org.apache.dubbo.rpc.ProxyFactory;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.cluster.Cluster;
import org.apache.dubbo.rpc.cluster.ClusterInvoker;
@ -837,30 +831,4 @@ public class RegistryProtocol implements Protocol {
}
return INSTANCE;
}
public static class ServiceDiscoveryMigrationInvoker<T> extends MigrationInvoker<T> {
public ServiceDiscoveryMigrationInvoker(RegistryProtocol registryProtocol, Cluster cluster, Registry registry, Class<T> type, URL url) {
super(registryProtocol, cluster, registry, type, url);
}
@Override
public synchronized void fallbackToInterfaceInvoker() {
destroyServiceDiscoveryInvoker();
}
@Override
public synchronized void migrateToServiceDiscoveryInvoker(boolean forceMigrate) {
refreshServiceDiscoveryInvoker();
}
@Override
public Result invoke(Invocation invocation) throws RpcException {
ClusterInvoker<T> invoker = getServiceDiscoveryInvoker();
if (invoker == null) {
throw new IllegalStateException("There's no service discovery invoker available for service " + invocation.getServiceName());
}
return invoker.invoke(invocation);
}
}
}

View File

@ -18,7 +18,6 @@ package org.apache.dubbo.registry.integration;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.SPI;
import org.apache.dubbo.registry.client.RegistryProtocol;
import org.apache.dubbo.rpc.Exporter;
import org.apache.dubbo.rpc.Invoker;

View File

@ -0,0 +1 @@
default=org.apache.dubbo.registry.client.migration.DefaultMigrationAddressComparator

View File

@ -1 +0,0 @@
default=org.apache.dubbo.registry.integration.DefaultMigrationAddressComparator

View File

@ -1 +1 @@
service-discovery=org.apache.dubbo.registry.client.ServiceDiscoveryRegistryProtocolListener
migration=org.apache.dubbo.registry.client.migration.MigrationRuleListener

View File

@ -1,2 +1,2 @@
registry=org.apache.dubbo.registry.integration.InterfaceCompatibleRegistryProtocol
service-discovery-registry=org.apache.dubbo.registry.client.RegistryProtocol
service-discovery-registry=org.apache.dubbo.registry.integration.RegistryProtocol

37
pom.xml
View File

@ -586,6 +586,43 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<autoVersionSubmodules>true</autoVersionSubmodules>
<useReleaseProfile>false</useReleaseProfile>
<releaseProfiles>release</releaseProfiles>
<goals>deploy</goals>
<arguments>${arguments}</arguments>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>${maven_flatten_version}</version>
<configuration>
<updatePomFile>true</updatePomFile>
<flattenMode>resolveCiFriendliesOnly</flattenMode>
</configuration>
<executions>
<execution>
<id>flatten</id>
<phase>process-resources</phase>
<goals>
<goal>flatten</goal>
</goals>
</execution>
<execution>
<id>flatten.clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>