This is an automated email from the ASF dual-hosted git repository.
albumenj pushed a commit to branch 3.1
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/3.1 by this push:
new d0a1bd0143 Fix recreate client after destroy (#11780)
d0a1bd0143 is described below
commit d0a1bd014331483c19208b831c4f6b488654a508
Author: Albumen Kevin <[email protected]>
AuthorDate: Fri Mar 10 16:25:56 2023 +0800
Fix recreate client after destroy (#11780)
* Fix recreate client after destroy
* Fix uts
---
.../apache/dubbo/config/ReferenceConfigTest.java | 10 ++-
.../dubbo/rpc/protocol/InvokerCountWrapper.java | 57 ++++++++++++++
.../rpc/protocol/ReferenceCountInvokerWrapper.java | 87 ++++++++++++++++++++++
.../dubbo/internal/org.apache.dubbo.rpc.Protocol | 1 +
4 files changed, 151 insertions(+), 4 deletions(-)
diff --git
a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
index e2c781ec22..815b6800e0 100644
---
a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
+++
b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
@@ -42,6 +42,7 @@ import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.apache.dubbo.rpc.model.ServiceMetadata;
+import org.apache.dubbo.rpc.protocol.ReferenceCountInvokerWrapper;
import org.apache.dubbo.rpc.protocol.injvm.InjvmInvoker;
import org.apache.dubbo.rpc.protocol.injvm.InjvmProtocol;
import org.apache.dubbo.rpc.service.GenericService;
@@ -479,10 +480,11 @@ class ReferenceConfigTest {
referenceConfig.init();
Assertions.assertTrue(referenceConfig.getInvoker() instanceof
MockClusterInvoker);
- Invoker<?> withFilter = ((MockClusterInvoker<?>)
referenceConfig.getInvoker()).getDirectory().getAllInvokers().get(0);
- Assertions.assertTrue(withFilter instanceof ListenerInvokerWrapper);
- Assertions.assertTrue(((ListenerInvokerWrapper<?>)
withFilter).getInvoker() instanceof InjvmInvoker);
- URL url = withFilter.getUrl();
+ Invoker<?> withCount = ((MockClusterInvoker<?>)
referenceConfig.getInvoker()).getDirectory().getAllInvokers().get(0);
+ Assertions.assertTrue(withCount instanceof
ReferenceCountInvokerWrapper);
+ Assertions.assertTrue(((ReferenceCountInvokerWrapper<?>)
withCount).getInvoker() instanceof ListenerInvokerWrapper);
+
Assertions.assertTrue(((ListenerInvokerWrapper<?>)(((ReferenceCountInvokerWrapper<?>)
withCount).getInvoker())).getInvoker() instanceof InjvmInvoker);
+ URL url = withCount.getUrl();
Assertions.assertEquals("application1",
url.getParameter("application"));
Assertions.assertEquals("value1", url.getParameter("key1"));
Assertions.assertEquals("value2", url.getParameter("key2"));
diff --git
a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/InvokerCountWrapper.java
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/InvokerCountWrapper.java
new file mode 100644
index 0000000000..985ece8f51
--- /dev/null
+++
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/InvokerCountWrapper.java
@@ -0,0 +1,57 @@
+/*
+ * 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;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.common.utils.UrlUtils;
+import org.apache.dubbo.rpc.Exporter;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.RpcException;
+
+@Activate(order = Integer.MIN_VALUE + 1000)
+public class InvokerCountWrapper implements Protocol {
+ private final Protocol protocol;
+
+ public InvokerCountWrapper(Protocol protocol) {
+ this.protocol = protocol;
+ }
+
+ @Override
+ public int getDefaultPort() {
+ return protocol.getDefaultPort();
+ }
+
+ @Override
+ public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
+ return protocol.export(invoker);
+ }
+
+ @Override
+ public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
+ if (UrlUtils.isRegistry(url)) {
+ return protocol.refer(type, url);
+ }
+ return new ReferenceCountInvokerWrapper<>(protocol.refer(type, url));
+ }
+
+ @Override
+ public void destroy() {
+ protocol.destroy();
+ }
+}
diff --git
a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ReferenceCountInvokerWrapper.java
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ReferenceCountInvokerWrapper.java
new file mode 100644
index 0000000000..1326cf16a4
--- /dev/null
+++
b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ReferenceCountInvokerWrapper.java
@@ -0,0 +1,87 @@
+/*
+ * 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;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.constants.LoggerCodeConstants;
+import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcException;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+public class ReferenceCountInvokerWrapper<T> implements Invoker<T> {
+ private final ErrorTypeAwareLogger logger =
LoggerFactory.getErrorTypeAwareLogger(ReferenceCountInvokerWrapper.class);
+ private final Invoker<T> invoker;
+
+ private final ReadWriteLock lock = new ReentrantReadWriteLock();
+ private final AtomicBoolean destroyed = new AtomicBoolean(false);
+
+ public ReferenceCountInvokerWrapper(Invoker<T> invoker) {
+ this.invoker = invoker;
+ }
+
+ @Override
+ public URL getUrl() {
+ return invoker.getUrl();
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return !destroyed.get() && invoker.isAvailable();
+ }
+
+ @Override
+ public void destroy() {
+ try {
+ lock.writeLock().lock();
+ destroyed.set(true);
+ } finally {
+ lock.writeLock().unlock();
+ }
+ invoker.destroy();
+ }
+
+ @Override
+ public Class<T> getInterface() {
+ return invoker.getInterface();
+ }
+
+ @Override
+ public Result invoke(Invocation invocation) throws RpcException {
+ try {
+ lock.readLock().lock();
+ if (destroyed.get()) {
+ logger.warn(LoggerCodeConstants.PROTOCOL_CLOSED_SERVER, "", "",
+ "Remote invoker has been destroyed, and unable to invoke
anymore.");
+ throw new RpcException("This invoker has been destroyed!");
+ }
+ return invoker.invoke(invocation);
+ } finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ public Invoker<T> getInvoker() {
+ return invoker;
+ }
+}
diff --git
a/dubbo-rpc/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol
b/dubbo-rpc/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol
index eff2b090d6..ce1e6d393a 100644
---
a/dubbo-rpc/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol
+++
b/dubbo-rpc/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol
@@ -2,3 +2,4 @@ listener=org.apache.dubbo.rpc.protocol.ProtocolListenerWrapper
mock=org.apache.dubbo.rpc.support.MockProtocol
serializationwrapper=org.apache.dubbo.rpc.protocol.ProtocolSerializationWrapper
securitywrapper=org.apache.dubbo.rpc.protocol.ProtocolSecurityWrapper
+invokercount=org.apache.dubbo.rpc.protocol.InvokerCountWrapper