Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
96c0eb6
Supporting triple and rest protocols on the same port
chickenlj Jun 12, 2023
692ff67
Feature enhance, support triple and rest protocols work on the same port
chickenlj Jun 14, 2023
b2969d0
add processor module
chickenlj Jun 14, 2023
4bbd6c7
ad doc
chickenlj Jun 14, 2023
92d1c26
API usage update, make application and registry not mandatory.
chickenlj Jul 7, 2023
68d2004
Merge branch '3.3' of https://github.com/apache/dubbo into 3.3
chickenlj Jul 7, 2023
c0b0467
Merge branch '3.3' into 3.3-multiple-protocol-support
chickenlj Jul 7, 2023
13b93aa
Merge branch '3.3' of https://github.com/apache/dubbo into 3.3
chickenlj Jul 10, 2023
2e9f863
log level to info
chickenlj Jul 11, 2023
1165258
Merge branch '3.3' into 3.3-multiple-protocol-support
chickenlj Jul 11, 2023
053d04a
export metadata service in service config
chickenlj Jul 12, 2023
973c236
update module
chickenlj Jul 12, 2023
d2793c8
Merge branch '3.3' into 3.3-multiple-protocol-support
chickenlj Aug 8, 2023
ac7bbd2
remove automatic protocol append
chickenlj Aug 9, 2023
012e7c4
fix unused imports
chickenlj Aug 9, 2023
6ce82a7
fix ut
chickenlj Aug 9, 2023
34c23d2
fix ut
chickenlj Aug 9, 2023
59370c7
fix ut
chickenlj Aug 9, 2023
ebe72f6
fix test check
chickenlj Aug 10, 2023
3688890
Merge branch '3.3.0-beta.1-release' into 3.3-multiple-protocol-support
chickenlj Aug 30, 2023
e825b84
Merge branch '3.3.0-beta.1-release' into 3.3-multiple-protocol-support
chickenlj Aug 30, 2023
8a9c1ed
Merge remote-tracking branch 'chickenlj/3.3-multiple-protocol-support…
chickenlj Aug 30, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,13 @@ public interface CommonConstants {

String REST_SERVICE_DEPLOYER_URL_ATTRIBUTE_KEY = "restServiceDeployerAttributeKey";

String SERVICE_DEPLOYER_ATTRIBUTE_KEY = "serviceDeployer"; String RESTEASY_NETTY_HTTP_REQUEST_ATTRIBUTE_KEY = "resteasyNettyHttpRequest";
String SERVICE_DEPLOYER_ATTRIBUTE_KEY = "serviceDeployer";

String RESTEASY_NETTY_HTTP_REQUEST_ATTRIBUTE_KEY = "resteasyNettyHttpRequest";

String DUBBO_MANUAL_REGISTER_KEY = "dubbo.application.manual-register";

String EXT_PROTOCOL = "ext.protocol";

String IS_EXTRA = "isExtra";
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ public interface ApplicationDeployer extends Deployer<ApplicationModel> {
/**
* Register application instance and start internal services
*/
void prepareApplicationInstance();
void prepareApplicationInstance(ModuleModel moduleModel);

void exportMetadataService();

/**
* Register application instance and start internal services
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,8 @@ public interface ModuleDeployer extends Deployer<ModuleModel> {
* Whether start in background, do not await finish
*/
boolean isBackground();

boolean hasRegistryInteraction();

ApplicationDeployer getApplicationDeployer();
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_PROTOCOL_KEY;
Expand Down Expand Up @@ -82,6 +83,8 @@ public class ApplicationConfig extends AbstractConfig {

private static final long serialVersionUID = 5508512956753757169L;

private static final String DEFAULT_NAME_PREFIX = "DUBBO_APP_";

/**
* Application name
*/
Expand Down Expand Up @@ -747,6 +750,12 @@ public String getExecutorManagementMode() {
public void refresh() {
super.refresh();
appendEnvironmentProperties();
if (StringUtils.isEmpty(getName())) {
String defaultName = DEFAULT_NAME_PREFIX + UUID.randomUUID();
this.setName(defaultName);
LOGGER.info("No application name was set, '" + defaultName + "' will be used as the default application name," +
" it's highly recommended to set a unique and customized name for it can be critical for some service governance features.");
}
}

private void appendEnvironmentProperties() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_IP_TO_BIND;
import static org.apache.dubbo.common.constants.CommonConstants.EXECUTOR_MANAGEMENT_MODE_ISOLATION;
import static org.apache.dubbo.common.constants.CommonConstants.EXPORTER_LISTENER_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.EXT_PROTOCOL;
import static org.apache.dubbo.common.constants.CommonConstants.IS_EXTRA;
import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_VALUE;
import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY;
Expand Down Expand Up @@ -366,7 +368,17 @@ protected void exported() {
mapServiceName(url, serviceNameMapping, scheduledExecutor);
}
});

onExported();

if (hasRegistrySpecified()) {
getScopeModel().getDeployer().getApplicationDeployer().exportMetadataService();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depends on MetadataService here might not a good design

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider provide a solution for this issue with #12750

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that the full service export process can move from ServiceConfig to a new ModuleLifecycle implement? This might solve this problem

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think so, this might need some extra efforts to merge this change with Lifecycle mechanism.

}
}

public boolean hasRegistrySpecified() {
return CollectionUtils.isNotEmpty(this.getRegistries())
|| CollectionUtils.isNotEmpty(getScopeModel().getApplicationModel().getApplicationConfigManager().getRegistries());
}

protected void mapServiceName(URL url, ServiceNameMapping serviceNameMapping, ScheduledExecutorService scheduledExecutor) {
Expand Down Expand Up @@ -740,14 +752,13 @@ private void exportUrl(URL url, List<URL> registryURLs, RegisterTypeEnum registe
// export to remote if the config is not local (export to local only when config is local)
if (!SCOPE_LOCAL.equalsIgnoreCase(scope)) {
// export to extra protocol is used in remote export
String extProtocol = url.getParameter("ext.protocol", "");
String extProtocol = url.getParameter(EXT_PROTOCOL, "");
List<String> protocols = new ArrayList<>();

if (StringUtils.isNotBlank(extProtocol)) {
// export original url
url = URLBuilder.from(url).
addParameter(IS_PU_SERVER_KEY, Boolean.TRUE.toString()).
removeParameter("ext.protocol").
build();
}

Expand All @@ -765,6 +776,8 @@ private void exportUrl(URL url, List<URL> registryURLs, RegisterTypeEnum registe
if (StringUtils.isNotBlank(protocol)) {
URL localUrl = URLBuilder.from(url).
setProtocol(protocol).
addParameter(IS_EXTRA, Boolean.TRUE.toString()).
removeParameter(EXT_PROTOCOL).
build();
localUrl = exportRemote(localUrl, registryURLs, registerType);
if (!isGeneric(generic) && !getScopeModel().isInternal()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
public class InternalServiceConfigBuilder<T> {

private final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(getClass());
private static final Set<String> UNACCEPTABLE_PROTOCOL = Stream.of("rest", "grpc").collect(Collectors.toSet());
private static final Set<String> ACCEPTABLE_PROTOCOL = Stream.of("dubbo", "tri", "injvm").collect(Collectors.toSet());

private final ApplicationModel applicationModel;
private String protocol;
Expand Down Expand Up @@ -112,19 +112,20 @@ public InternalServiceConfigBuilder<T> protocol(String protocol, String key) {
*/
private String getRelatedOrDefaultProtocol() {
String protocol = "";
// <dubbo:consumer/>
List<ModuleModel> moduleModels = applicationModel.getPubModuleModels();
protocol = moduleModels.stream()
.map(ModuleModel::getConfigManager)
.map(ModuleConfigManager::getConsumers)
.filter(CollectionUtils::isNotEmpty)
.flatMap(Collection::stream)
.map(ConsumerConfig::getProtocol)
.filter(StringUtils::isNotEmpty)
.filter(p -> !UNACCEPTABLE_PROTOCOL.contains(p))
.findFirst()
.orElse("");
// <dubbo:protocol/>
if (StringUtils.isEmpty(protocol)) {
Collection<ProtocolConfig> protocols = applicationModel.getApplicationConfigManager().getProtocols();
if (CollectionUtils.isNotEmpty(protocols)) {
protocol = protocols.stream()
.map(ProtocolConfig::getName)
.filter(StringUtils::isNotEmpty)
.filter(p -> ACCEPTABLE_PROTOCOL.contains(p))
.findFirst()
.orElse("");
}
}
// <dubbo:provider/>
List<ModuleModel> moduleModels = applicationModel.getPubModuleModels();
if (StringUtils.isEmpty(protocol)) {
Stream<ProviderConfig> providerConfigStream = moduleModels.stream()
.map(ModuleModel::getConfigManager)
Expand All @@ -145,22 +146,10 @@ private String getRelatedOrDefaultProtocol() {
}
})
.filter(StringUtils::isNotEmpty)
.filter(p -> !UNACCEPTABLE_PROTOCOL.contains(p))
.filter(p -> ACCEPTABLE_PROTOCOL.contains(p))
.findFirst()
.orElse("");
}
// <dubbo:protocol/>
if (StringUtils.isEmpty(protocol)) {
Collection<ProtocolConfig> protocols = applicationModel.getApplicationConfigManager().getProtocols();
if (CollectionUtils.isNotEmpty(protocols)) {
protocol = protocols.stream()
.map(ProtocolConfig::getName)
.filter(StringUtils::isNotEmpty)
.filter(p -> !UNACCEPTABLE_PROTOCOL.contains(p))
.findFirst()
.orElse("");
}
}
// <dubbo:application/>
if (StringUtils.isEmpty(protocol)) {
protocol = getApplicationConfig().getProtocol();
Expand All @@ -171,7 +160,18 @@ private String getRelatedOrDefaultProtocol() {
}
}
}
return StringUtils.isNotEmpty(protocol) && !UNACCEPTABLE_PROTOCOL.contains(protocol) ? protocol : DUBBO_PROTOCOL;
// <dubbo:consumer/>
protocol = moduleModels.stream()
.map(ModuleModel::getConfigManager)
.map(ModuleConfigManager::getConsumers)
.filter(CollectionUtils::isNotEmpty)
.flatMap(Collection::stream)
.map(ConsumerConfig::getProtocol)
.filter(StringUtils::isNotEmpty)
.filter(p -> ACCEPTABLE_PROTOCOL.contains(p))
.findFirst()
.orElse("");
return StringUtils.isNotEmpty(protocol) && ACCEPTABLE_PROTOCOL.contains(protocol) ? protocol : DUBBO_PROTOCOL;
}

public InternalServiceConfigBuilder<T> protocol(String protocol) {
Expand Down Expand Up @@ -254,7 +254,11 @@ public ServiceConfig<T> build(Consumer<ServiceConfig<T>> configConsumer){
logger.info("Using " + this.protocol + " protocol to export "+interfaceClass.getName()+" service on port " + protocolConfig.getPort());

applicationModel.getApplicationConfigManager().getProtocol(this.protocol)
.ifPresent(protocolConfig::mergeProtocol);
.ifPresent(p -> {
protocolConfig.mergeProtocol(p);
// clear extra protocols possibly merged from global ProtocolConfig
protocolConfig.setExtProtocol(null);
});

ApplicationConfig applicationConfig = getApplicationConfig();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,13 @@ private void unRegisterShutdownHook() {
}

/**
* Close registration of instance for pure Consumer process by setting registerConsumer to 'false'
* by default is true.
* Enable registration of instance for pure Consumer process by setting registerConsumer to 'true'
* by default is false.
*/
private boolean isRegisterConsumerInstance() {
Boolean registerConsumer = getApplication().getRegisterConsumer();
if (registerConsumer == null) {
return true;
return false;
}
return Boolean.TRUE.equals(registerConsumer);
}
Expand Down Expand Up @@ -746,23 +746,27 @@ private void startModules() {
}

@Override
public void prepareApplicationInstance() {
public void prepareApplicationInstance(ModuleModel moduleModel) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ApplicationDeployer depends on ModuleModel might not a good design.
BTW, if there are more than one ModuleModels, will this work not expected?

Copy link
Contributor Author

@chickenlj chickenlj Aug 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DefaultApplicationDeployer.java

    public void notifyModuleChanged(ModuleModel moduleModel, DeployState state) {
        checkState(moduleModel, state);
    }

    public void checkState(ModuleModel moduleModel, DeployState moduleState) {
        synchronized (stateLock) {
            if (!moduleModel.isInternal() && moduleState == DeployState.STARTED) {
                prepareApplicationInstance(moduleModel);
            }
}

It's currently designed to work this way:

  1. when the state of a ModuleModel changes, it will call notifyModuleChanged and passes ModuleModel instance in.
  2. checkState will then check if this ModelModel isInternal, if true, prepareApplicationInstance(moduleModel); will be called.

ApplicationDeployer depends on ModuleModel mainly querying for statuses such as 'STARTED', 'isInternal', and 'hasRegistryInteraction'. All these statuses can be wrapped into an Event or something, but I think this can be further optimized with this issue #12750

if (hasPreparedApplicationInstance.get()) {
return;
}

// export MetricsService
exportMetricsService();

if (isRegisterConsumerInstance()) {
exportMetadataService();
if (isRegisterConsumerInstance() || moduleModel.getDeployer().hasRegistryInteraction()) {
if (hasPreparedApplicationInstance.compareAndSet(false, true)) {
// register the local ServiceInstance if required
registerServiceInstance();
}
}
}

@Override
public synchronized void exportMetadataService() {
doExportMetadataService();
}

public void prepareInternalModule() {
if (hasPreparedInternalModule) {
return;
Expand Down Expand Up @@ -1081,7 +1085,7 @@ public void notifyModuleChanged(ModuleModel moduleModel, DeployState state) {
public void checkState(ModuleModel moduleModel, DeployState moduleState) {
synchronized (stateLock) {
if (!moduleModel.isInternal() && moduleState == DeployState.STARTED) {
prepareApplicationInstance();
prepareApplicationInstance(moduleModel);
}
DeployState newState = calculateState();
switch (newState) {
Expand Down Expand Up @@ -1183,8 +1187,8 @@ private void onInitialize() {
}
}

private void exportMetadataService() {
if (!isStarting()) {
private void doExportMetadataService() {
if (!isStarting() && !isStarted()) {
return;
}
for (DeployListener<ApplicationModel> listener : listeners) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ public class DefaultModuleDeployer extends AbstractDeployer<ModuleModel> impleme
private Boolean background;
private Boolean exportAsync;
private Boolean referAsync;

private boolean registryInteracted;

private CompletableFuture<?> exportFuture;
private CompletableFuture<?> referFuture;

Expand Down Expand Up @@ -439,6 +442,10 @@ private void exportServiceInternal(ServiceConfigBase sc) {
exportedServices.add(sc);
}
}

if (serviceConfig.hasRegistrySpecified()) {
registryInteracted = true;
}
}

private void registerServiceInternal(ServiceConfigBase sc) {
Expand Down Expand Up @@ -578,4 +585,13 @@ public void prepare() {
this.initialize();
}

@Override
public boolean hasRegistryInteraction() {
return registryInteracted;
}

@Override
public ApplicationDeployer getApplicationDeployer() {
return applicationDeployer;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@
import static org.apache.dubbo.common.constants.CommonConstants.THREADPOOL_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.USERNAME_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_CLASS_NOT_FOUND;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_PARAMETER_FORMAT_ERROR;
import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_REGISTER_MODE_ALL;
import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_REGISTER_MODE_INSTANCE;
Expand Down Expand Up @@ -464,7 +463,7 @@ private static void checkQosDependency(ApplicationConfig config) {
try {
ClassUtils.forName("org.apache.dubbo.qos.protocol.QosProtocolWrapper");
} catch (ClassNotFoundException e) {
logger.warn(COMMON_CLASS_NOT_FOUND, "", "", "No QosProtocolWrapper class was found. Please check the dependency of dubbo-qos whether was imported correctly.", e);
logger.info("QosProtocolWrapper not found, qos will not be enabled, please check if 'dubbo-qos' dependency was imported correctly.");
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
import org.apache.dubbo.rpc.ProxyFactory;
import org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder;
import org.apache.dubbo.rpc.cluster.support.registry.ZoneAwareClusterInvoker;
//import org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker;
import org.apache.dubbo.rpc.cluster.support.wrapper.ScopeClusterInvoker;
import org.apache.dubbo.rpc.listener.ListenerInvokerWrapper;
import org.apache.dubbo.rpc.model.ApplicationModel;
Expand Down Expand Up @@ -1041,6 +1040,7 @@ public void testDifferentClassLoaderRequest() throws Exception {
referenceConfig1.setRegistry(new RegistryConfig(zkUrl1));
referenceConfig1.setScopeModel(moduleModel);
referenceConfig1.setScope("remote");
referenceConfig1.setTimeout(30000);
Object object1 = referenceConfig1.get();

java.lang.reflect.Method callBean1 = object1.getClass().getDeclaredMethod("call", requestClazzOrigin);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,9 @@ void testExport() throws Exception {
assertThat(url.getParameters(), hasKey(METHODS_KEY));
assertThat(url.getParameters().get(METHODS_KEY), containsString("echo"));
assertThat(url.getParameters(), hasEntry(SIDE_KEY, PROVIDER));
// export MetadataService and DemoService in "mockprotocol2" protocol.
Mockito.verify(protocolDelegate, times(2)).export(Mockito.any(Invoker.class));
// export DemoService in "mockprotocol2" protocol.
Mockito.verify(protocolDelegate, times(1)).export(Mockito.any(Invoker.class));
// MetadataService will be exported on either dubbo or triple (the only two default acceptable protocol)
}

@Test
Expand Down Expand Up @@ -351,8 +352,8 @@ void testExportWithoutRegistryConfig() {
assertThat(url.getParameters(), hasKey(METHODS_KEY));
assertThat(url.getParameters().get(METHODS_KEY), containsString("echo"));
assertThat(url.getParameters(), hasEntry(SIDE_KEY, PROVIDER));
// export MetadataService and DemoService in "mockprotocol2" protocol.
Mockito.verify(protocolDelegate, times(2)).export(Mockito.any(Invoker.class));
// export DemoService in "mockprotocol2" protocol (MetadataService will be not exported if no registry specified)
Mockito.verify(protocolDelegate, times(1)).export(Mockito.any(Invoker.class));
}

@Test
Expand Down
Loading