diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java index 8f5875333f..dab89c0848 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java @@ -348,6 +348,7 @@ public abstract class AbstractDirectory implements Directory { if (!invokersToReconnect.isEmpty()) { checkConnectivity(); } + MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta())); }, reconnectTaskPeriod, TimeUnit.MILLISECONDS); } MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta())); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java index 3380621774..c3aea739ee 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java @@ -643,7 +643,7 @@ 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 DUBBO_MANUAL_REGISTER_KEY = "dubbo.application.manual-register"; } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java index 49bd9665c7..53e377f9f9 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java @@ -40,17 +40,19 @@ public interface MetricsConstants { String TAG_VERSION_KEY = "version"; String TAG_APPLICATION_VERSION_KEY = "application.version"; - + String TAG_KEY_KEY = "key"; - + String TAG_CONFIG_CENTER = "config.center"; - + String TAG_CHANGE_TYPE = "change.type"; String TAG_ERROR_CODE = "error"; String ENABLE_JVM_METRICS_KEY = "enable.jvm"; + String ENABLE_COLLECTOR_SYNC_KEY = "enable.collector.sync"; + String AGGREGATION_COLLECTOR_KEY = "aggregation"; String AGGREGATION_ENABLED_KEY = "aggregation.enabled"; diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/ErrorTypeAwareLogger.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/ErrorTypeAwareLogger.java index fe9ebcc774..72db45e868 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/ErrorTypeAwareLogger.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/ErrorTypeAwareLogger.java @@ -17,8 +17,23 @@ package org.apache.dubbo.common.logger; +import org.apache.dubbo.common.constants.LoggerCodeConstants; + /** * Logger interface with the ability of displaying solution of different types of error. + * + *

+ * This logger will log a message like this: + * + *

+ *     ... (original logging message) This may be caused by (... cause),
+ *     go to https://dubbo.apache.org/faq/[Cat]/[X] to find instructions. (... extendedInformation)
+ * 
+ * + * Where "[Cat]/[X]" is the error code ("code" in arguments). The link is clickable, leading user to + * the "Error code and its corresponding solutions" page. + * + * @see LoggerCodeConstants Detailed Format of Error Code and Error Code Constants */ public interface ErrorTypeAwareLogger extends Logger { diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java index 75a80c8999..cda3390abd 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java @@ -103,6 +103,11 @@ public abstract class AbstractConfig implements Serializable { protected final AtomicBoolean refreshed = new AtomicBoolean(false); + /** + * Indicate that if current config needs to being refreshed, default is true + */ + protected transient volatile boolean needRefresh = true; + /** * Is default config or not */ @@ -679,16 +684,18 @@ public abstract class AbstractConfig implements Serializable { * Dubbo config property override */ public void refresh() { - try { - // check and init before do refresh - preProcessRefresh(); - refreshWithPrefixes(getPrefixes(), getConfigMode()); - } catch (Exception e) { - logger.error(COMMON_FAILED_OVERRIDE_FIELD, "", "", "Failed to override field value of config bean: " + this, e); - throw new IllegalStateException("Failed to override field value of config bean: " + this, e); - } + if (needRefresh) { + try { + // check and init before do refresh + preProcessRefresh(); + refreshWithPrefixes(getPrefixes(), getConfigMode()); + } catch (Exception e) { + logger.error(COMMON_FAILED_OVERRIDE_FIELD, "", "", "Failed to override field value of config bean: " + this, e); + throw new IllegalStateException("Failed to override field value of config bean: " + this, e); + } - postProcessRefresh(); + postProcessRefresh(); + } refreshed.set(true); } @@ -949,6 +956,17 @@ public abstract class AbstractConfig implements Serializable { this.isDefault = isDefault; } + @Transient + @Parameter(excluded = true, attribute = false) + public boolean isNeedRefresh() { + return needRefresh; + } + + @Transient + public void setNeedRefresh(boolean needRefresh) { + this.needRefresh = needRefresh; + } + @Override public String toString() { try { diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/MetricsConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/MetricsConfig.java index 37cd727f4c..3faa74f012 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/MetricsConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/MetricsConfig.java @@ -66,6 +66,16 @@ public class MetricsConfig extends AbstractConfig { */ private Boolean enableNetty; + /** + * Enable metrics init. + */ + private Boolean enableMetricsInit; + + /** + * Enable collector sync. + */ + private Boolean enableCollectorSync; + /** * @deprecated After metrics config is refactored. * This parameter should no longer use and will be deleted in the future. @@ -213,6 +223,22 @@ public class MetricsConfig extends AbstractConfig { this.enableThreadpool = enableThreadpool; } + public Boolean getEnableMetricsInit() { + return enableMetricsInit; + } + + public void setEnableMetricsInit(Boolean enableMetricsInit) { + this.enableMetricsInit = enableMetricsInit; + } + + public Boolean getEnableCollectorSync() { + return enableCollectorSync; + } + + public void setEnableCollectorSync(Boolean enableCollectorSync) { + this.enableCollectorSync = enableCollectorSync; + } + public Boolean getUseGlobalRegistry() { return useGlobalRegistry; } diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java index c11f9c3f62..9d8280d312 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java @@ -228,8 +228,13 @@ public class ReferenceConfig extends ReferenceConfigBase { } if (ref == null) { - // ensure start module, compatible with old api usage - getScopeModel().getDeployer().start(); + if (getScopeModel().isLifeCycleManagedExternally()) { + // prepare model for reference + getScopeModel().getDeployer().prepare(); + } else { + // ensure start module, compatible with old api usage + getScopeModel().getDeployer().start(); + } init(check); } diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java index d9d6862255..92fae4a971 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java @@ -296,8 +296,13 @@ public class ServiceConfig extends ServiceConfigBase { return; } - // ensure start module, compatible with old api usage - getScopeModel().getDeployer().start(); + if (getScopeModel().isLifeCycleManagedExternally()) { + // prepare model for reference + getScopeModel().getDeployer().prepare(); + } else { + // ensure start module, compatible with old api usage + getScopeModel().getDeployer().start(); + } synchronized (this) { if (this.exported) { diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java index d4a3da0cee..b4cee19e11 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java @@ -391,6 +391,7 @@ public class DefaultApplicationDeployer extends AbstractDeployer org.aspectj aspectjweaver - 1.9.20 + 1.9.20.1 test diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java index edad8afd0e..28d0ef0973 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java @@ -25,6 +25,7 @@ import org.apache.dubbo.common.utils.ClassUtils; import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.config.ReferenceConfig; import org.apache.dubbo.config.spring.aot.AotWithSpringDetector; +import org.apache.dubbo.config.spring.context.DubboConfigApplicationListener; import org.apache.dubbo.config.spring.context.DubboConfigBeanInitializer; import org.apache.dubbo.config.spring.reference.ReferenceAttributes; import org.apache.dubbo.config.spring.reference.ReferenceBeanManager; @@ -54,6 +55,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_DUBBO_BEAN_INITIALIZER; import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROXY_FAILED; @@ -143,6 +145,9 @@ public class ReferenceBean implements FactoryBean, //actual reference config private ReferenceConfig referenceConfig; + // ReferenceBeanManager + private ReferenceBeanManager referenceBeanManager; + // Registration sources of this reference, may be xml file or annotation location private List> sources = new ArrayList<>(); @@ -256,7 +261,7 @@ public class ReferenceBean implements FactoryBean, } Assert.notNull(this.interfaceName, "The interface name of ReferenceBean is not initialized"); - ReferenceBeanManager referenceBeanManager = beanFactory.getBean(ReferenceBeanManager.BEAN_NAME, ReferenceBeanManager.class); + this.referenceBeanManager = beanFactory.getBean(ReferenceBeanManager.BEAN_NAME, ReferenceBeanManager.class); referenceBeanManager.addReference(this); } @@ -393,7 +398,9 @@ public class ReferenceBean implements FactoryBean, private Object getCallProxy() throws Exception { if (referenceConfig == null) { - throw new IllegalStateException("ReferenceBean is not ready yet, please make sure to call reference interface method after dubbo is started."); + referenceBeanManager.initReferenceBean(this); + applicationContext.getBean(DubboConfigApplicationListener.class.getName(), DubboConfigApplicationListener.class).init(); + logger.warn(CONFIG_DUBBO_BEAN_INITIALIZER, "", "", "ReferenceBean is not ready yet, please make sure to call reference interface method after dubbo is started."); } //get reference proxy //Subclasses should synchronize on the given Object if they perform any sort of extended singleton creation phase. diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationPostProcessor.java index 43f1ae5a19..87f1e74f1f 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationPostProcessor.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationPostProcessor.java @@ -238,7 +238,7 @@ public class ServiceAnnotationPostProcessor implements BeanDefinitionRegistryPos } } else { if (logger.isWarnEnabled()) { - logger.warn(CONFIG_NO_ANNOTATIONS_FOUND, "No annotations were found on the class", "", "No class annotated by Dubbo @Service was found under package [" + logger.warn(CONFIG_NO_ANNOTATIONS_FOUND, "No annotations were found on the class", "", "No class annotated by Dubbo @DubboService or @Service was found under package [" + packageToScan + "], ignore re-scanned classes: " + scanExcludeFilter.getExcludedCount()); } } diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboConfigApplicationListener.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboConfigApplicationListener.java index 17343637bb..2cdf512053 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboConfigApplicationListener.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboConfigApplicationListener.java @@ -16,21 +16,22 @@ */ package org.apache.dubbo.config.spring.context; -import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_DUBBO_BEAN_NOT_FOUND; -import static org.springframework.util.ObjectUtils.nullSafeEquals; - -import java.util.concurrent.atomic.AtomicBoolean; - import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.config.spring.context.event.DubboConfigInitEvent; import org.apache.dubbo.config.spring.util.DubboBeanUtils; import org.apache.dubbo.rpc.model.ModuleModel; + import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationListener; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_DUBBO_BEAN_NOT_FOUND; +import static org.springframework.util.ObjectUtils.nullSafeEquals; + /** * An ApplicationListener to load config beans */ @@ -53,11 +54,15 @@ public class DubboConfigApplicationListener implements ApplicationListener - + diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml index 627419a2a6..03c36be9dd 100644 --- a/dubbo-dependencies-bom/pom.xml +++ b/dubbo-dependencies-bom/pom.xml @@ -102,7 +102,7 @@ 4.5.14 4.4.16 1.2.83 - 2.0.39 + 2.0.40 3.4.14 4.3.0 2.12.0 @@ -112,12 +112,12 @@ 1.5.3 1.4.3 3.5.5 - 0.18.1 + 0.19.0 4.0.66 3.24.2 1.3.2 3.1.0 - 9.4.51.v20230217 + 9.4.52.v20230823 3.0.2 1.1.0.Final 5.4.3.Final diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/AggregateMetricsCollector.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/AggregateMetricsCollector.java index 2f04416bf2..ff7abf5d3c 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/AggregateMetricsCollector.java +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/AggregateMetricsCollector.java @@ -267,10 +267,16 @@ public class AggregateMetricsCollector implements MetricsCollector @Override public void initMetrics(MetricsEvent event) { MethodMetric metric = new MethodMetric(applicationModel, event.getAttachmentValue(MetricsConstants.INVOCATION)); - initMethodMetric(event); - initQpsMetric(metric); - initRtMetric(metric); - initRtAgrMetric(metric); + if (enableQps) { + initMethodMetric(event); + initQpsMetric(metric); + } + if (enableRt) { + initRtMetric(metric); + } + if (enableRtPxx) { + initRtAgrMetric(metric); + } } public void initMethodMetric(MetricsEvent event){ diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/DefaultMetricsCollector.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/DefaultMetricsCollector.java index 65f40b5185..7f2d502a86 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/DefaultMetricsCollector.java +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/collector/DefaultMetricsCollector.java @@ -62,6 +62,8 @@ public class DefaultMetricsCollector extends CombMetricsCollector private volatile boolean threadpoolCollectEnabled = false; + private volatile boolean metricsInitEnabled = true; + private final ThreadPoolMetricsSampler threadPoolSampler = new ThreadPoolMetricsSampler(this); private final ErrorCodeSampler errorCodeSampler; @@ -132,6 +134,14 @@ public class DefaultMetricsCollector extends CombMetricsCollector this.threadpoolCollectEnabled = threadpoolCollectEnabled; } + public boolean isMetricsInitEnabled() { + return metricsInitEnabled; + } + + public void setMetricsInitEnabled(boolean metricsInitEnabled) { + this.metricsInitEnabled = metricsInitEnabled; + } + public void collectApplication() { this.setApplicationName(applicationModel.getApplicationName()); applicationSampler.inc(applicationName, MetricsEvent.Type.APPLICATION_INFO); @@ -164,6 +174,9 @@ public class DefaultMetricsCollector extends CombMetricsCollector @Override public void onEvent(TimeCounterEvent event) { if(event instanceof MetricsInitEvent){ + if (!metricsInitEnabled) { + return; + } if(initialized.compareAndSet(false,true)) { collectors.addAll(applicationModel.getBeanFactory().getBeansOfType(MetricsCollector.class)); } diff --git a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/report/AbstractMetricsReporter.java b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/report/AbstractMetricsReporter.java index c6eb309b36..13c8cecdc4 100644 --- a/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/report/AbstractMetricsReporter.java +++ b/dubbo-metrics/dubbo-metrics-default/src/main/java/org/apache/dubbo/metrics/report/AbstractMetricsReporter.java @@ -17,26 +17,26 @@ package org.apache.dubbo.metrics.report; -import io.micrometer.core.instrument.FunctionCounter; -import io.micrometer.core.instrument.binder.MeterBinder; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.beans.factory.ScopeBeanFactory; import org.apache.dubbo.common.lang.ShutdownHookCallbacks; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.metrics.MetricsGlobalRegistry; import org.apache.dubbo.common.utils.NamedThreadFactory; +import org.apache.dubbo.metrics.MetricsGlobalRegistry; import org.apache.dubbo.metrics.collector.AggregateMetricsCollector; -import org.apache.dubbo.metrics.collector.MetricsCollector; import org.apache.dubbo.metrics.collector.HistogramMetricsCollector; +import org.apache.dubbo.metrics.collector.MetricsCollector; import org.apache.dubbo.metrics.model.sample.CounterMetricSample; import org.apache.dubbo.metrics.model.sample.GaugeMetricSample; import org.apache.dubbo.metrics.model.sample.MetricSample; import org.apache.dubbo.rpc.model.ApplicationModel; +import io.micrometer.core.instrument.FunctionCounter; import io.micrometer.core.instrument.Gauge; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.binder.MeterBinder; import io.micrometer.core.instrument.binder.jvm.ClassLoaderMetrics; import io.micrometer.core.instrument.binder.jvm.JvmGcMetrics; import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics; @@ -53,6 +53,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_METRICS_COLLECTOR_EXCEPTION; +import static org.apache.dubbo.common.constants.MetricsConstants.ENABLE_COLLECTOR_SYNC_KEY; import static org.apache.dubbo.common.constants.MetricsConstants.ENABLE_JVM_METRICS_KEY; /** @@ -140,9 +141,12 @@ public abstract class AbstractMetricsReporter implements MetricsReporter { } private void scheduleMetricsCollectorSyncJob() { - NamedThreadFactory threadFactory = new NamedThreadFactory("metrics-collector-sync-job", true); - collectorSyncJobExecutor = Executors.newScheduledThreadPool(1, threadFactory); - collectorSyncJobExecutor.scheduleWithFixedDelay(this::refreshData, DEFAULT_SCHEDULE_INITIAL_DELAY, DEFAULT_SCHEDULE_PERIOD, TimeUnit.SECONDS); + boolean enableCollectorSync = url.getParameter(ENABLE_COLLECTOR_SYNC_KEY, true); + if (enableCollectorSync) { + NamedThreadFactory threadFactory = new NamedThreadFactory("metrics-collector-sync-job", true); + collectorSyncJobExecutor = Executors.newScheduledThreadPool(1, threadFactory); + collectorSyncJobExecutor.scheduleWithFixedDelay(this::refreshData, DEFAULT_SCHEDULE_INITIAL_DELAY, DEFAULT_SCHEDULE_PERIOD, TimeUnit.SECONDS); + } } @SuppressWarnings({"unchecked", "rawtypes"}) diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/protocol/QosProtocolWrapper.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/protocol/QosProtocolWrapper.java index d45ee69749..fe47762a33 100644 --- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/protocol/QosProtocolWrapper.java +++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/protocol/QosProtocolWrapper.java @@ -96,7 +96,9 @@ public class QosProtocolWrapper implements Protocol, ScopeModelAware { return protocol.getServers(); } - private void startQosServer(URL url) { + private void startQosServer(URL url) throws RpcException { + boolean qosCheck = url.getParameter(QOS_CHECK, false); + try { if (!hasStarted.compareAndSet(false, true)) { return; @@ -132,9 +134,13 @@ public class QosProtocolWrapper implements Protocol, ScopeModelAware { } catch (Throwable throwable) { logger.warn(QOS_FAILED_START_SERVER, "", "", "Fail to start qos server: ", throwable); - boolean qosCheck = url.getParameter(QOS_CHECK, false); + try { + stopServer(); + } catch (Throwable stop) { + logger.warn(QOS_FAILED_START_SERVER, "", "", "Fail to stop qos server: ", stop); + } if (qosCheck) { - throw new IllegalStateException("Fail to start qos server: " + throwable.getMessage(), throwable); + throw new RpcException(throwable); } } } diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/QosBindException.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/QosBindException.java new file mode 100644 index 0000000000..57aecd228f --- /dev/null +++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/QosBindException.java @@ -0,0 +1,26 @@ +/* + * 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.qos.server; + +/** + * Indicate that if Qos Start failed + */ +public class QosBindException extends RuntimeException { + public QosBindException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/Server.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/Server.java index 65e7e3b9fa..12c02ccea7 100644 --- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/Server.java +++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/server/Server.java @@ -35,8 +35,6 @@ import io.netty.util.concurrent.DefaultThreadFactory; import java.util.concurrent.atomic.AtomicBoolean; -import static org.apache.dubbo.common.constants.LoggerCodeConstants.QOS_FAILED_START_SERVER; - /** * A server serves for both telnet access and http access *
    @@ -105,13 +103,13 @@ public class Server { @Override protected void initChannel(Channel ch) throws Exception { ch.pipeline().addLast(new QosProcessHandler(frameworkModel, - QosConfiguration.builder() - .welcome(welcome) - .acceptForeignIp(acceptForeignIp) - .acceptForeignIpWhitelist(acceptForeignIpWhitelist) - .anonymousAccessPermissionLevel(anonymousAccessPermissionLevel) - .anonymousAllowCommands(anonymousAllowCommands) - .build() + QosConfiguration.builder() + .welcome(welcome) + .acceptForeignIp(acceptForeignIp) + .acceptForeignIpWhitelist(acceptForeignIpWhitelist) + .anonymousAccessPermissionLevel(anonymousAccessPermissionLevel) + .anonymousAllowCommands(anonymousAllowCommands) + .build() )); } }); @@ -124,8 +122,7 @@ public class Server { logger.info("qos-server bind localhost:" + port); } catch (Throwable throwable) { - logger.error(QOS_FAILED_START_SERVER, "", "", "qos-server can not bind localhost:" + port, throwable); - throw throwable; + throw new QosBindException("qos-server can not bind localhost:" + port, throwable); } } @@ -140,6 +137,7 @@ public class Server { if (worker != null) { worker.shutdownGracefully(); } + started.set(false); } public String getHost() { diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Constants.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Constants.java index 5346193900..ab75d2b183 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Constants.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Constants.java @@ -130,6 +130,10 @@ public interface Constants { String BIND_PORT_KEY = "bind.port"; + String BIND_RETRY_TIMES = "bind.retry.times"; + + String BIND_RETRY_INTERVAL = "bind.retry.interval"; + String SENT_KEY = "sent"; String DISPATCHER_KEY = "dispatcher"; diff --git a/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/restclient/HttpClientRestClient.java b/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/restclient/HttpClientRestClient.java index 0344a4aab9..f8f85411af 100644 --- a/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/restclient/HttpClientRestClient.java +++ b/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/restclient/HttpClientRestClient.java @@ -93,7 +93,8 @@ public class HttpClientRestClient implements RestClient { future.complete(new RestResult() { @Override public String getContentType() { - return response.getFirstHeader("Content-Type").getValue(); + Header header = response.getFirstHeader("Content-Type"); + return header == null ? null : header.getValue(); } @Override diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyPortUnificationServer.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyPortUnificationServer.java index f5fdc9a919..a7cab7b985 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyPortUnificationServer.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyPortUnificationServer.java @@ -97,14 +97,14 @@ public class NettyPortUnificationServer extends AbstractPortUnificationServer { } } - public void bind() { + public void bind() throws Throwable { if (channel == null) { doOpen(); } } @Override - public void doOpen() { + public void doOpen() throws Throwable { bootstrap = new ServerBootstrap(); bossGroup = NettyEventLoopFactory.eventLoopGroup(1, EVENT_LOOP_BOSS_POOL_NAME); @@ -138,9 +138,31 @@ public class NettyPortUnificationServer extends AbstractPortUnificationServer { bindIp = ANYHOST_VALUE; } InetSocketAddress bindAddress = new InetSocketAddress(bindIp, bindPort); - ChannelFuture channelFuture = bootstrap.bind(bindAddress); - channelFuture.syncUninterruptibly(); - channel = channelFuture.channel(); + try { + ChannelFuture channelFuture = bootstrap.bind(bindAddress); + channelFuture.syncUninterruptibly(); + channel = channelFuture.channel(); + } catch (Throwable t) { + closeBootstrap(); + throw t; + } + } + + private void closeBootstrap() { + try { + if (bootstrap != null) { + long timeout = ConfigurationUtils.reCalShutdownTime(serverShutdownTimeoutMills); + long quietPeriod = Math.min(2000L, timeout); + Future bossGroupShutdownFuture = bossGroup.shutdownGracefully(quietPeriod, + timeout, MILLISECONDS); + Future workerGroupShutdownFuture = workerGroup.shutdownGracefully(quietPeriod, + timeout, MILLISECONDS); + bossGroupShutdownFuture.awaitUninterruptibly(timeout, MILLISECONDS); + workerGroupShutdownFuture.awaitUninterruptibly(timeout, MILLISECONDS); + } + } catch (Throwable e) { + logger.warn(TRANSPORT_FAILED_CLOSE, "", "", e.getMessage(), e); + } } @Override @@ -176,20 +198,7 @@ public class NettyPortUnificationServer extends AbstractPortUnificationServer { protocol.close(); } - try { - if (bootstrap != null) { - long timeout = ConfigurationUtils.reCalShutdownTime(serverShutdownTimeoutMills); - long quietPeriod = Math.min(2000L, timeout); - Future bossGroupShutdownFuture = bossGroup.shutdownGracefully(quietPeriod, - timeout, MILLISECONDS); - Future workerGroupShutdownFuture = workerGroup.shutdownGracefully(quietPeriod, - timeout, MILLISECONDS); - bossGroupShutdownFuture.awaitUninterruptibly(timeout, MILLISECONDS); - workerGroupShutdownFuture.awaitUninterruptibly(timeout, MILLISECONDS); - } - } catch (Throwable e) { - logger.warn(TRANSPORT_FAILED_CLOSE, "", "", e.getMessage(), e); - } + closeBootstrap(); } @Override diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyServer.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyServer.java index 6acf226391..d165651858 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyServer.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyServer.java @@ -111,9 +111,14 @@ public class NettyServer extends AbstractServer { initServerBootstrap(nettyServerHandler); // bind - ChannelFuture channelFuture = bootstrap.bind(getBindAddress()); - channelFuture.syncUninterruptibly(); - channel = channelFuture.channel(); + try { + ChannelFuture channelFuture = bootstrap.bind(getBindAddress()); + channelFuture.syncUninterruptibly(); + channel = channelFuture.channel(); + } catch (Throwable t) { + closeBootstrap(); + throw t; + } // metrics if (isSupportMetrics()) { @@ -198,6 +203,17 @@ public class NettyServer extends AbstractServer { } catch (Throwable e) { logger.warn(TRANSPORT_FAILED_CLOSE, "", "", e.getMessage(), e); } + closeBootstrap(); + try { + if (channels != null) { + channels.clear(); + } + } catch (Throwable e) { + logger.warn(TRANSPORT_FAILED_CLOSE, "", "", e.getMessage(), e); + } + } + + private void closeBootstrap() { try { if (bootstrap != null) { long timeout = ConfigurationUtils.reCalShutdownTime(serverShutdownTimeoutMills); @@ -210,13 +226,6 @@ public class NettyServer extends AbstractServer { } catch (Throwable e) { logger.warn(TRANSPORT_FAILED_CLOSE, "", "", e.getMessage(), e); } - try { - if (channels != null) { - channels.clear(); - } - } catch (Throwable e) { - logger.warn(TRANSPORT_FAILED_CLOSE, "", "", e.getMessage(), e); - } } @Override diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/ConnectionTest.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/ConnectionTest.java index 2c230d6c61..ba9fd3eb0d 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/ConnectionTest.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/ConnectionTest.java @@ -21,13 +21,13 @@ import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.utils.NetUtils; import org.apache.dubbo.config.ApplicationConfig; import org.apache.dubbo.config.context.ConfigManager; -import org.apache.dubbo.remoting.RemotingException; import org.apache.dubbo.remoting.api.connection.AbstractConnectionClient; import org.apache.dubbo.remoting.api.connection.ConnectionManager; import org.apache.dubbo.remoting.api.connection.MultiplexProtocolConnectionManager; import org.apache.dubbo.remoting.api.pu.DefaultPuHandler; import org.apache.dubbo.rpc.model.ApplicationModel; import org.apache.dubbo.rpc.model.ModuleModel; + import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -50,7 +50,7 @@ public class ConnectionTest { private static ConnectionManager connectionManager; @BeforeAll - public static void init() throws RemotingException { + public static void init() throws Throwable { int port = NetUtils.getAvailablePort(); url = URL.valueOf("empty://127.0.0.1:" + port + "?foo=bar"); ApplicationModel applicationModel = ApplicationModel.defaultModel(); @@ -123,7 +123,7 @@ public class ConnectionTest { } @Test - void connectSyncTest() throws RemotingException { + void connectSyncTest() throws Throwable { int port = NetUtils.getAvailablePort(); URL url = URL.valueOf("empty://127.0.0.1:" + port + "?foo=bar"); NettyPortUnificationServer nettyPortUnificationServer = new NettyPortUnificationServer(url, new DefaultPuHandler()); diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/PortUnificationServerTest.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/PortUnificationServerTest.java index 0f5268da89..c5b1234e0e 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/PortUnificationServerTest.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/PortUnificationServerTest.java @@ -21,11 +21,10 @@ import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.utils.NetUtils; import org.apache.dubbo.config.ApplicationConfig; import org.apache.dubbo.config.context.ConfigManager; -import org.apache.dubbo.remoting.RemotingException; import org.apache.dubbo.remoting.api.pu.DefaultPuHandler; - import org.apache.dubbo.rpc.model.ApplicationModel; import org.apache.dubbo.rpc.model.ModuleModel; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -34,7 +33,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.EXECUTOR_MANAGEM class PortUnificationServerTest { @Test - void testBind() throws RemotingException { + void testBind() throws Throwable { int port = NetUtils.getAvailablePort(); URL url = URL.valueOf("empty://127.0.0.1:" + port + "?foo=bar"); ApplicationModel applicationModel = ApplicationModel.defaultModel(); diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/api/MultiplexProtocolConnectionManagerTest.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/api/MultiplexProtocolConnectionManagerTest.java index 2bceec7ab6..76a45adadd 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/api/MultiplexProtocolConnectionManagerTest.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/api/MultiplexProtocolConnectionManagerTest.java @@ -21,15 +21,14 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.config.ApplicationConfig; import org.apache.dubbo.config.context.ConfigManager; -import org.apache.dubbo.remoting.RemotingException; import org.apache.dubbo.remoting.api.connection.AbstractConnectionClient; import org.apache.dubbo.remoting.api.connection.ConnectionManager; import org.apache.dubbo.remoting.api.connection.MultiplexProtocolConnectionManager; import org.apache.dubbo.remoting.api.pu.DefaultPuHandler; import org.apache.dubbo.remoting.transport.netty4.NettyPortUnificationServer; - import org.apache.dubbo.rpc.model.ApplicationModel; import org.apache.dubbo.rpc.model.ModuleModel; + import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -52,7 +51,7 @@ public class MultiplexProtocolConnectionManagerTest { private static ConnectionManager connectionManager; @BeforeAll - public static void init() throws RemotingException { + public static void init() throws Throwable { ApplicationModel applicationModel = ApplicationModel.defaultModel(); ApplicationConfig applicationConfig = new ApplicationConfig("provider-app"); applicationConfig.setExecutorManagementMode(EXECUTOR_MANAGEMENT_MODE_DEFAULT); @@ -95,7 +94,7 @@ public class MultiplexProtocolConnectionManagerTest { } @Test - public void testForEachConnection() throws RemotingException { + public void testForEachConnection() throws Throwable { DefaultPuHandler handler = new DefaultPuHandler(); NettyPortUnificationServer server2 = new NettyPortUnificationServer(url2, handler); diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/api/SingleProtocolConnectionManagerTest.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/api/SingleProtocolConnectionManagerTest.java index bc4d548008..5369ea0f22 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/api/SingleProtocolConnectionManagerTest.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/api/SingleProtocolConnectionManagerTest.java @@ -31,6 +31,7 @@ import org.apache.dubbo.remoting.transport.netty4.NettyConnectionClient; import org.apache.dubbo.remoting.transport.netty4.NettyPortUnificationServer; import org.apache.dubbo.rpc.model.ApplicationModel; import org.apache.dubbo.rpc.model.ModuleModel; + import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -51,7 +52,7 @@ public class SingleProtocolConnectionManagerTest { private static ConnectionManager connectionManager; @BeforeAll - public static void init() throws RemotingException { + public static void init() throws Throwable { int port = NetUtils.getAvailablePort(); url = URL.valueOf("empty://127.0.0.1:" + port + "?foo=bar"); ApplicationModel applicationModel = ApplicationModel.defaultModel(); diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/ResteasyContext.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/ResteasyContext.java index 002e2e993b..2134381842 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/ResteasyContext.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/ResteasyContext.java @@ -160,9 +160,9 @@ public interface ResteasyContext { } } - default DubboContainerResponseContextImpl createContainerResponseContext(RequestFacade request, HttpResponse httpResponse, BuiltResponse jaxrsResponse, ContainerResponseFilter[] responseFilters) { + default DubboContainerResponseContextImpl createContainerResponseContext(Object originRequest, RequestFacade request, HttpResponse httpResponse, BuiltResponse jaxrsResponse, ContainerResponseFilter[] responseFilters) { - NettyHttpRequest nettyHttpRequest = createNettyHttpRequest(request); + NettyHttpRequest nettyHttpRequest = originRequest == null ? createNettyHttpRequest(request) : (NettyHttpRequest) originRequest; ResponseContainerRequestContext requestContext = new ResponseContainerRequestContext(nettyHttpRequest); DubboContainerResponseContextImpl responseContext = new DubboContainerResponseContextImpl(nettyHttpRequest, httpResponse, jaxrsResponse, diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/ResteasyRequestContainerFilterAdapter.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/ResteasyRequestContainerFilterAdapter.java index 5843c69945..851da89a2f 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/ResteasyRequestContainerFilterAdapter.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/ResteasyRequestContainerFilterAdapter.java @@ -18,7 +18,6 @@ package org.apache.dubbo.rpc.protocol.rest.extension.resteasy.filter; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.Activate; -import org.apache.dubbo.rpc.RpcContext; import org.apache.dubbo.rpc.protocol.rest.deploy.ServiceDeployer; import org.apache.dubbo.rpc.protocol.rest.extension.resteasy.ResteasyContext; import org.apache.dubbo.rpc.protocol.rest.filter.RestRequestFilter; @@ -30,7 +29,6 @@ import org.jboss.resteasy.specimpl.BuiltResponse; import javax.ws.rs.container.ContainerRequestFilter; import java.util.List; -import static org.apache.dubbo.common.constants.CommonConstants.RESTEASY_NETTY_HTTP_REQUEST_ATTRIBUTE_KEY; @Activate(value = "resteasy", onClass = {"javax.ws.rs.container.ContainerRequestFilter", "org.jboss.resteasy.plugins.server.netty.NettyHttpRequest", "org.jboss.resteasy.plugins.server.netty.NettyHttpResponse"}, order = Integer.MAX_VALUE - 1) @@ -55,7 +53,8 @@ public class ResteasyRequestContainerFilterAdapter implements RestRequestFilter, DubboPreMatchContainerRequestContext containerRequestContext = convertHttpRequestToContainerRequestContext(requestFacade, containerRequestFilters.toArray(new ContainerRequestFilter[0])); - RpcContext.getServiceContext().setObjectAttachment(RESTEASY_NETTY_HTTP_REQUEST_ATTRIBUTE_KEY, containerRequestContext.getHttpRequest()); + // set resteasy request for save user`s custom request attribute + restFilterContext.setOriginRequest(containerRequestContext.getHttpRequest()); try { BuiltResponse restResponse = containerRequestContext.filter(); diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/ResteasyResponseContainerFilterAdapter.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/ResteasyResponseContainerFilterAdapter.java index c6af847ece..89ea8a6e21 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/ResteasyResponseContainerFilterAdapter.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/filter/ResteasyResponseContainerFilterAdapter.java @@ -53,7 +53,7 @@ public class ResteasyResponseContainerFilterAdapter implements RestResponseFilte DubboBuiltResponse dubboBuiltResponse = new DubboBuiltResponse(response.getResponseBody(), response.getStatus(), response.getEntityClass()); // NettyHttpResponse wrapper HttpResponse httpResponse = new ResteasyNettyHttpResponse(response); - DubboContainerResponseContextImpl containerResponseContext = createContainerResponseContext(requestFacade, httpResponse, dubboBuiltResponse, containerRequestFilters.toArray(new ContainerResponseFilter[0])); + DubboContainerResponseContextImpl containerResponseContext = createContainerResponseContext(restFilterContext.getOriginRequest(),requestFacade, httpResponse, dubboBuiltResponse, containerRequestFilters.toArray(new ContainerResponseFilter[0])); containerResponseContext.filter(); // user reset entity diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/intercept/ResteasyWriterInterceptorAdapter.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/intercept/ResteasyWriterInterceptorAdapter.java index fbde93b39f..60d7b63eff 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/intercept/ResteasyWriterInterceptorAdapter.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/extension/resteasy/intercept/ResteasyWriterInterceptorAdapter.java @@ -18,7 +18,6 @@ package org.apache.dubbo.rpc.protocol.rest.extension.resteasy.intercept; import org.apache.commons.io.IOUtils; import org.apache.dubbo.common.extension.Activate; -import org.apache.dubbo.rpc.RpcContext; import org.apache.dubbo.rpc.RpcInvocation; import org.apache.dubbo.rpc.protocol.rest.RestHeaderEnum; import org.apache.dubbo.rpc.protocol.rest.deploy.ServiceDeployer; @@ -41,8 +40,6 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.List; -import static org.apache.dubbo.common.constants.CommonConstants.RESTEASY_NETTY_HTTP_REQUEST_ATTRIBUTE_KEY; - @Activate(value = "resteasy", onClass = {"javax.ws.rs.ext.WriterInterceptorContext", "org.jboss.resteasy.plugins.server.netty.NettyHttpRequest", "org.jboss.resteasy.plugins.server.netty.NettyHttpResponse"}) public class ResteasyWriterInterceptorAdapter implements RestResponseInterceptor, ResteasyContext { @@ -67,7 +64,7 @@ public class ResteasyWriterInterceptorAdapter implements RestResponseInterceptor return; } - NettyHttpRequest nettyHttpRequest = (NettyHttpRequest) RpcContext.getServiceContext().getObjectAttachment(RESTEASY_NETTY_HTTP_REQUEST_ATTRIBUTE_KEY); + NettyHttpRequest nettyHttpRequest = (NettyHttpRequest) restResponseInterceptor.getOriginRequest(); HttpRequest restRequest = nettyHttpRequest == null ? createNettyHttpRequest(request) : nettyHttpRequest; diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/ServiceInvokeRestFilter.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/ServiceInvokeRestFilter.java index 404f8edd5a..2e97493c0e 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/ServiceInvokeRestFilter.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/ServiceInvokeRestFilter.java @@ -63,7 +63,12 @@ public class ServiceInvokeRestFilter implements RestRequestFilter { FullHttpRequest nettyHttpRequest = nettyRequestFacade.getRequest(); - doHandler(nettyHttpRequest, restFilterContext.getResponse(), restFilterContext.getRequestFacade(), restFilterContext.getUrl(), restFilterContext.getServiceDeployer()); + doHandler(nettyHttpRequest, + restFilterContext.getResponse(), + restFilterContext.getRequestFacade(), + restFilterContext.getUrl(), + restFilterContext.getOriginRequest(), + restFilterContext.getServiceDeployer()); } @@ -72,6 +77,7 @@ public class ServiceInvokeRestFilter implements RestRequestFilter { NettyHttpResponse nettyHttpResponse, RequestFacade request, URL url, + Object originRequest,// resteasy request ServiceDeployer serviceDeployer) throws Exception { PathMatcher pathMatcher = RestRPCInvocationUtil.createPathMatcher(request); @@ -130,8 +136,12 @@ public class ServiceInvokeRestFilter implements RestRequestFilter { } try { + RestInterceptContext restFilterContext = new RestInterceptContext(url, request, nettyHttpResponse, serviceDeployer, result.getValue(), rpcInvocation); + // set filter request + restFilterContext.setOriginRequest(originRequest); + // invoke the intercept chain before Result write to response - executeResponseIntercepts(url, request, nettyHttpResponse, result.getValue(), rpcInvocation, serviceDeployer); + executeResponseIntercepts(restFilterContext); } catch (Exception exception) { logger.error("", exception.getMessage(), "", "dubbo rest protocol execute ResponseIntercepts error", exception); throw exception; @@ -215,17 +225,11 @@ public class ServiceInvokeRestFilter implements RestRequestFilter { /** * execute response Intercepts * - * @param url - * @param request - * @param nettyHttpResponse - * @param result - * @param rpcInvocation - * @param serviceDeployer + * @param restFilterContext * @throws Exception */ - public void executeResponseIntercepts(URL url, RequestFacade request, NettyHttpResponse nettyHttpResponse, Object result, RpcInvocation rpcInvocation, ServiceDeployer serviceDeployer) throws Exception { + public void executeResponseIntercepts(RestInterceptContext restFilterContext) throws Exception { - RestInterceptContext restFilterContext = new RestInterceptContext(url, request, nettyHttpResponse, serviceDeployer, result, rpcInvocation); for (RestResponseInterceptor restResponseInterceptor : restResponseInterceptors) { diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/context/FilterContext.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/context/FilterContext.java index e64d175529..d40c41e27e 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/context/FilterContext.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/context/FilterContext.java @@ -35,4 +35,8 @@ public interface FilterContext { boolean complete(); void setComplete(boolean complete); + + Object getOriginRequest(); + + Object getOriginResponse(); } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/context/RestFilterContext.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/context/RestFilterContext.java index a563c5e09b..bf2be29d45 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/context/RestFilterContext.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/filter/context/RestFilterContext.java @@ -27,6 +27,8 @@ public class RestFilterContext implements FilterContext { protected NettyHttpResponse response; protected ServiceDeployer serviceDeployer; protected boolean completed; + protected Object originRequest; + protected Object originResponse; public RestFilterContext(URL url, RequestFacade requestFacade, NettyHttpResponse response, ServiceDeployer serviceDeployer) { this.url = url; @@ -64,4 +66,25 @@ public class RestFilterContext implements FilterContext { public void setComplete(boolean complete) { this.completed = complete; } + + @Override + public Object getOriginRequest() { + return originRequest; + } + + @Override + public Object getOriginResponse() { + return originResponse; + } + + public void setOriginRequest(Object originRequest) { + if (this.originRequest != null) { + return; + } + this.originRequest = originRequest; + } + + public void setOriginResponse(Object originResponse) { + this.originResponse = originResponse; + } } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/handler/NettyHttpHandler.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/handler/NettyHttpHandler.java index e24207b792..c8aff6afc2 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/handler/NettyHttpHandler.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/handler/NettyHttpHandler.java @@ -32,7 +32,6 @@ import org.apache.dubbo.rpc.protocol.rest.filter.ServiceInvokeRestFilter; import org.apache.dubbo.rpc.protocol.rest.filter.context.RestFilterContext; import org.apache.dubbo.rpc.protocol.rest.netty.NettyHttpResponse; import org.apache.dubbo.rpc.protocol.rest.request.NettyRequestFacade; -import org.apache.dubbo.rpc.protocol.rest.request.RequestFacade; import java.io.IOException; import java.util.ArrayList; @@ -74,11 +73,12 @@ public class NettyHttpHandler implements HttpHandler restFilters) throws Exception { - RestFilterContext restFilterContext = new RestFilterContext(url, requestFacade, nettyHttpResponse, serviceDeployer); + public void executeFilters(RestFilterContext restFilterContext, List restFilters) throws Exception { for (RestFilter restFilter : restFilters) { restFilter.filter(restFilterContext); diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/JaxrsRestProtocolTest.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/JaxrsRestProtocolTest.java index b20734cd44..6bfbd77f20 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/JaxrsRestProtocolTest.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/JaxrsRestProtocolTest.java @@ -43,6 +43,7 @@ import org.apache.dubbo.rpc.protocol.rest.exception.ResteasyExceptionMapper; import org.apache.dubbo.rpc.protocol.rest.exception.mapper.ExceptionHandler; import org.apache.dubbo.rpc.protocol.rest.exception.mapper.ExceptionMapper; +import org.apache.dubbo.rpc.protocol.rest.filter.TraceRequestAndResponseFilter; import org.apache.dubbo.rpc.protocol.rest.rest.AnotherUserRestService; import org.apache.dubbo.rpc.protocol.rest.rest.AnotherUserRestServiceImpl; import org.apache.dubbo.rpc.protocol.rest.rest.HttpMethodService; @@ -755,7 +756,7 @@ class JaxrsRestProtocolTest { URL url = this.registerProvider(exportUrl, server, DemoService.class); - URL nettyUrl = url.addParameter(org.apache.dubbo.remoting.Constants.PAYLOAD_KEY, 1024); + URL nettyUrl = url.addParameter(org.apache.dubbo.remoting.Constants.PAYLOAD_KEY, 1024); Exporter exporter = protocol.export(proxy.getInvoker(server, DemoService.class, nettyUrl)); @@ -775,6 +776,26 @@ class JaxrsRestProtocolTest { } + + @Test + void testRequestAndResponseFilter() { + DemoService server = new DemoServiceImpl(); + + URL exportUrl = URL.valueOf("rest://127.0.0.1:" + availablePort + "/rest?interface=org.apache.dubbo.rpc.protocol.rest.DemoService&extension=" + + TraceRequestAndResponseFilter.class.getName()); + + URL nettyUrl = this.registerProvider(exportUrl, server, DemoService.class); + + Exporter exporter = protocol.export(proxy.getInvoker(server, DemoService.class, nettyUrl)); + + DemoService demoService = this.proxy.getProxy(protocol.refer(DemoService.class, nettyUrl)); + + + Assertions.assertEquals("header-result", demoService.sayHello("hello")); + exporter.unexport(); + } + + private URL registerProvider(URL url, Object impl, Class interfaceClass) { ServiceDescriptor serviceDescriptor = repository.registerService(interfaceClass); ProviderModel providerModel = new ProviderModel( diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/filter/TraceRequestAndResponseFilter.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/filter/TraceRequestAndResponseFilter.java new file mode 100644 index 0000000000..b6ca0f1e9f --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/filter/TraceRequestAndResponseFilter.java @@ -0,0 +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.protocol.rest.filter; + +import javax.annotation.Priority; +import javax.ws.rs.Priorities; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import java.io.IOException; + +@Priority(Priorities.USER) +public class TraceRequestAndResponseFilter implements ContainerRequestFilter, ContainerResponseFilter { + + @Override + public void filter(ContainerRequestContext requestContext) throws IOException { + + requestContext.getHeaders().add("test-response","header-result"); + } + + @Override + public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) throws + + IOException { + + String headerString = containerRequestContext.getHeaderString("test-response"); + containerResponseContext.setEntity(headerString); + + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleInvoker.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleInvoker.java index 61c6870c50..b666c8c5e3 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleInvoker.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleInvoker.java @@ -67,7 +67,6 @@ import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.locks.ReentrantLock; -import java.util.stream.Collectors; import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY; import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PACKABLE_METHOD_FACTORY; @@ -249,7 +248,7 @@ public class TripleInvoker extends AbstractInvoker { if (methodDescriptor.isGeneric()) { Object[] args = new Object[3]; args[0] = RpcUtils.getMethodName(invocation); - args[1] = Arrays.stream(RpcUtils.getParameterTypes(invocation)).map(Class::getName).collect(Collectors.toList()); + args[1] = Arrays.stream(RpcUtils.getParameterTypes(invocation)).map(Class::getName).toArray(String[]::new); args[2] = RpcUtils.getArguments(invocation); pureArgument = args; } else { diff --git a/dubbo-spring-boot/pom.xml b/dubbo-spring-boot/pom.xml index 18261a7340..5155377044 100644 --- a/dubbo-spring-boot/pom.xml +++ b/dubbo-spring-boot/pom.xml @@ -46,7 +46,7 @@ 2.20.0 - 1.14.5 + 1.14.7 diff --git a/pom.xml b/pom.xml index 5801f45d56..4490dc7d27 100644 --- a/pom.xml +++ b/pom.xml @@ -119,7 +119,7 @@ 3.11.0 3.2.1 3.5.0 - 9.4.51.v20230217 + 9.4.52.v20230823 3.2.1 0.8.10 1.5.0