Refactor service metadata export process (#12990)

* * Migrate service metadata export process to MetadataPublisher

* * Fix ut

* * Move metadata API out of dubbo-config-api

* * Move metadata API spi file out of dubbo-config-api

* * Merge remote branch

* * Merge remote branch

* * Add license

* Add license

* Update MetadataPublisherRegister.java

* Update DefaultMetadataPublisher.java

* Update MetadataServiceExporterTest.java

* * Bug fix

* Update MetadataPublisher.java

* * Remove unnecessary SPI for MetadataPublisher

* * Update pom

* * Move spi file back

* * Add MetadataPublisherRegister

* * Add license

* Update MetadataPublisherRegister.java

* * Bug fix
This commit is contained in:
namelessssssssssss 2023-09-11 11:15:27 +08:00 committed by GitHub
parent 98e7313e71
commit 9eb83d16bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 196 additions and 68 deletions

View File

@ -0,0 +1,32 @@
/*
* 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.metadata;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ServiceDescriptor;
/**
* Metadata publisher.
*/
public interface MetadataPublisher {
/**
* Publish a service metadata to all available MetadataReport.
*/
void publishServiceDefinition(URL url, ServiceDescriptor serviceDescriptor, ApplicationModel applicationModel);
}

View File

@ -34,7 +34,7 @@ import org.apache.dubbo.common.utils.UrlUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.config.utils.ConfigValidationUtils;
import org.apache.dubbo.registry.client.metadata.MetadataUtils;
import org.apache.dubbo.metadata.MetadataPublisher;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Protocol;
import org.apache.dubbo.rpc.ProxyFactory;
@ -471,7 +471,11 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
referenceParameters.get(INTERFACE_KEY), referenceParameters);
consumerUrl = consumerUrl.setScopeModel(getScopeModel());
consumerUrl = consumerUrl.setServiceModel(consumerModel);
MetadataUtils.publishServiceDefinition(consumerUrl, consumerModel.getServiceModel(), getApplicationModel());
MetadataPublisher metadataPublisher = getApplicationModel().getBeanFactory().getBean(MetadataPublisher.class);
if(metadataPublisher != null){
metadataPublisher.publishServiceDefinition(consumerUrl, consumerModel.getServiceModel(), getApplicationModel());
}
// create service proxy
return (T) proxyFactory.getProxy(invoker, ProtocolUtils.isGeneric(generic));

View File

@ -37,10 +37,10 @@ import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.invoker.DelegateProviderMetaDataInvoker;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.config.utils.ConfigValidationUtils;
import org.apache.dubbo.metadata.MetadataPublisher;
import org.apache.dubbo.metadata.ServiceNameMapping;
import org.apache.dubbo.metrics.event.MetricsEventBus;
import org.apache.dubbo.metrics.event.MetricsInitEvent;
import org.apache.dubbo.registry.client.metadata.MetadataUtils;
import org.apache.dubbo.rpc.Exporter;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Protocol;
@ -768,7 +768,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
url = exportRemote(url, registryURLs, registerType);
if (!isGeneric(generic) && !getScopeModel().isInternal()) {
MetadataUtils.publishServiceDefinition(url, providerModel.getServiceModel(), getApplicationModel());
publishServiceDefinition(url);
}
if (StringUtils.isNotBlank(extProtocol)) {
@ -783,7 +783,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
build();
localUrl = exportRemote(localUrl, registryURLs, registerType);
if (!isGeneric(generic) && !getScopeModel().isInternal()) {
MetadataUtils.publishServiceDefinition(localUrl, providerModel.getServiceModel(), getApplicationModel());
publishServiceDefinition(url);
}
this.urls.add(localUrl);
}
@ -1062,4 +1062,11 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
public Runnable getDestroyRunner() {
return this::unexport;
}
private void publishServiceDefinition(URL url){
MetadataPublisher metadataPublisher = getApplicationModel().getBeanFactory().getBean(MetadataPublisher.class);
if(metadataPublisher != null){
metadataPublisher.publishServiceDefinition(url, providerModel.getServiceModel(), getApplicationModel());
}
}
}

View File

@ -25,8 +25,8 @@
//import org.apache.dubbo.config.ServiceConfig;
//import org.apache.dubbo.config.api.DemoService;
//import org.apache.dubbo.config.bootstrap.DubboBootstrap;
//import org.apache.dubbo.config.metadata.ConfigurableMetadataServiceExporter;
//import org.apache.dubbo.config.metadata.ExporterDeployListener;
//import org.apache.dubbo.metadata.deploy.ConfigurableMetadataServiceExporter;
//import org.apache.dubbo.metadata.deploy.ExporterDeployListener;
//import org.apache.dubbo.registry.client.metadata.MetadataServiceDelegation;
//import org.apache.dubbo.config.provider.impl.DemoServiceImpl;
//import org.apache.dubbo.rpc.model.ApplicationModel;
@ -253,4 +253,4 @@
// return (ExporterDeployListener)model.getExtensionLoader(ApplicationDeployListener.class).getExtension("exporter");
// }
//
//}
//}

View File

@ -0,0 +1,44 @@
/*
* 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.metadata;
import org.apache.dubbo.common.deploy.ApplicationDeployListener;
import org.apache.dubbo.metadata.report.DefaultMetadataPublisher;
import org.apache.dubbo.rpc.model.ApplicationModel;
public class MetadataPublisherRegister implements ApplicationDeployListener {
@Override
public void onStarting(ApplicationModel scopeModel) {
scopeModel.getBeanFactory().getOrRegisterBean(DefaultMetadataPublisher.class);
}
@Override
public void onInitialize(ApplicationModel scopeModel) {}
@Override
public void onStarted(ApplicationModel scopeModel) {}
@Override
public void onStopping(ApplicationModel scopeModel) {}
@Override
public void onStopped(ApplicationModel scopeModel) {}
@Override
public void onFailure(ApplicationModel scopeModel, Throwable cause) {}
}

View File

@ -0,0 +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.metadata.report;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.metadata.MetadataPublisher;
import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ServiceDescriptor;
import java.util.Map;
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE;
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.REGISTRY_FAILED_CREATE_INSTANCE;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.REGISTRY_FAILED_LOAD_METADATA;
public class DefaultMetadataPublisher implements MetadataPublisher {
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(DefaultMetadataPublisher.class);
@Override
public void publishServiceDefinition(URL url, ServiceDescriptor serviceDescriptor, ApplicationModel applicationModel) {
if (getMetadataReports(applicationModel).isEmpty()) {
String msg = "Remote Metadata Report Server is not provided or unavailable, will stop registering service definition to remote center!";
logger.warn(REGISTRY_FAILED_LOAD_METADATA, "", "", msg);
return;
}
try {
String side = url.getSide();
if (PROVIDER_SIDE.equalsIgnoreCase(side)) {
String serviceKey = url.getServiceKey();
FullServiceDefinition serviceDefinition = serviceDescriptor.getFullServiceDefinition(serviceKey);
if (StringUtils.isNotEmpty(serviceKey) && serviceDefinition != null) {
serviceDefinition.setParameters(url.getParameters());
for (Map.Entry<String, MetadataReport> entry : getMetadataReports(applicationModel).entrySet()) {
MetadataReport metadataReport = entry.getValue();
if (!metadataReport.shouldReportDefinition()) {
logger.info("Report of service definition is disabled for " + entry.getKey());
continue;
}
metadataReport.storeProviderMetadata(
new MetadataIdentifier(
url.getServiceInterface(),
url.getVersion() == null ? "" : url.getVersion(),
url.getGroup() == null ? "" : url.getGroup(),
PROVIDER_SIDE,
applicationModel.getApplicationName())
, serviceDefinition);
}
}
} else {
for (Map.Entry<String, MetadataReport> entry : getMetadataReports(applicationModel).entrySet()) {
MetadataReport metadataReport = entry.getValue();
if (!metadataReport.shouldReportDefinition()) {
logger.info("Report of service definition is disabled for " + entry.getKey());
continue;
}
metadataReport.storeConsumerMetadata(
new MetadataIdentifier(
url.getServiceInterface(),
url.getVersion() == null ? "" : url.getVersion(),
url.getGroup() == null ? "" : url.getGroup(),
CONSUMER_SIDE,
applicationModel.getApplicationName()),
url.getParameters());
}
}
} catch (Exception e) {
//ignore error
logger.error(REGISTRY_FAILED_CREATE_INSTANCE, "", "", "publish service definition metadata error.", e);
}
}
private static Map<String, MetadataReport> getMetadataReports(ApplicationModel applicationModel) {
return applicationModel.getBeanFactory().getBean(MetadataReportInstance.class).getMetadataReports(false);
}
}

View File

@ -0,0 +1 @@
metadata-register=org.apache.dubbo.metadata.MetadataPublisherRegister

View File

@ -25,10 +25,8 @@ import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.metadata.MetadataInfo;
import org.apache.dubbo.metadata.MetadataService;
import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
import org.apache.dubbo.metadata.report.MetadataReport;
import org.apache.dubbo.metadata.report.MetadataReportInstance;
import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
import org.apache.dubbo.metadata.report.identifier.SubscriberMetadataIdentifier;
import org.apache.dubbo.registry.client.ServiceInstance;
import org.apache.dubbo.rpc.Invoker;
@ -37,7 +35,6 @@ import org.apache.dubbo.rpc.ProxyFactory;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ConsumerModel;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.apache.dubbo.rpc.model.ServiceDescriptor;
import org.apache.dubbo.rpc.service.Destroyable;
import java.util.HashMap;
@ -45,11 +42,8 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE;
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
import static org.apache.dubbo.common.constants.CommonConstants.PROXY_CLASS_REF;
import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.REGISTRY_FAILED_CREATE_INSTANCE;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.REGISTRY_FAILED_LOAD_METADATA;
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_CLUSTER_KEY;
import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_URLS_PROPERTY_NAME;
@ -57,60 +51,6 @@ import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataU
public class MetadataUtils {
public static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(MetadataUtils.class);
public static void publishServiceDefinition(URL url, ServiceDescriptor serviceDescriptor, ApplicationModel applicationModel) {
if (getMetadataReports(applicationModel).size() == 0) {
String msg = "Remote Metadata Report Server is not provided or unavailable, will stop registering service definition to remote center!";
logger.warn(REGISTRY_FAILED_LOAD_METADATA, "", "", msg);
return;
}
try {
String side = url.getSide();
if (PROVIDER_SIDE.equalsIgnoreCase(side)) {
String serviceKey = url.getServiceKey();
FullServiceDefinition serviceDefinition = serviceDescriptor.getFullServiceDefinition(serviceKey);
if (StringUtils.isNotEmpty(serviceKey) && serviceDefinition != null) {
serviceDefinition.setParameters(url.getParameters());
for (Map.Entry<String, MetadataReport> entry : getMetadataReports(applicationModel).entrySet()) {
MetadataReport metadataReport = entry.getValue();
if (!metadataReport.shouldReportDefinition()) {
logger.info("Report of service definition is disabled for " + entry.getKey());
continue;
}
metadataReport.storeProviderMetadata(
new MetadataIdentifier(
url.getServiceInterface(),
url.getVersion() == null ? "" : url.getVersion(),
url.getGroup() == null ? "" : url.getGroup(),
PROVIDER_SIDE,
applicationModel.getApplicationName())
, serviceDefinition);
}
}
} else {
for (Map.Entry<String, MetadataReport> entry : getMetadataReports(applicationModel).entrySet()) {
MetadataReport metadataReport = entry.getValue();
if (!metadataReport.shouldReportDefinition()) {
logger.info("Report of service definition is disabled for " + entry.getKey());
continue;
}
metadataReport.storeConsumerMetadata(
new MetadataIdentifier(
url.getServiceInterface(),
url.getVersion() == null ? "" : url.getVersion(),
url.getGroup() == null ? "" : url.getGroup(),
CONSUMER_SIDE,
applicationModel.getApplicationName()),
url.getParameters());
}
}
} catch (Exception e) {
//ignore error
logger.error(REGISTRY_FAILED_CREATE_INSTANCE, "", "", "publish service definition metadata error.", e);
}
}
public static ProxyHolder referProxy(ServiceInstance instance) {
MetadataServiceURLBuilder builder;
ExtensionLoader<MetadataServiceURLBuilder> loader = instance.getApplicationModel()