This is an automated email from the ASF dual-hosted git repository.

Aias00 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git


The following commit(s) were added to refs/heads/master by this push:
     new ac2487d55b fix(tars): avoid busy spin during proxy initialization 
(#7099)
ac2487d55b is described below

commit ac2487d55b4ff9841b09e644f2e55f2f17c66948
Author: Liming Deng <[email protected]>
AuthorDate: Wed Sep 23 16:00:50 2026 +0800

    fix(tars): avoid busy spin during proxy initialization (#7099)
    
    * fix(tars): avoid busy spin during proxy initialization
    
    * test(tars): enable module test suite
    
    ---------
    
    Co-authored-by: aias00 <[email protected]>
---
 .../shenyu-plugin-rpc/shenyu-plugin-tars/pom.xml   | 11 ----
 .../plugin/tars/cache/ApplicationConfigCache.java  | 60 ++++++++++------------
 .../tars/cache/ApplicationConfigCacheTest.java     | 27 ++++++++++
 3 files changed, 54 insertions(+), 44 deletions(-)

diff --git 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-tars/pom.xml
 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-tars/pom.xml
index 25f0c005ce..87741342f2 100644
--- 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-tars/pom.xml
+++ 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-tars/pom.xml
@@ -62,15 +62,4 @@
         </dependency>
     </dependencies>
 
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-surefire-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
 </project>
diff --git 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-tars/src/main/java/org/apache/shenyu/plugin/tars/cache/ApplicationConfigCache.java
 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-tars/src/main/java/org/apache/shenyu/plugin/tars/cache/ApplicationConfigCache.java
index 1422da5d0c..6bd72c4896 100644
--- 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-tars/src/main/java/org/apache/shenyu/plugin/tars/cache/ApplicationConfigCache.java
+++ 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-tars/src/main/java/org/apache/shenyu/plugin/tars/cache/ApplicationConfigCache.java
@@ -186,27 +186,20 @@ public final class ApplicationConfigCache {
      * @param metaData metaData
      */
     public void initPrx(final MetaData metaData) {
-        while (true) {
-            Class<?> prxClass = prxClassCache.get(metaData.getPath());
-            try {
-                if (Objects.isNull(prxClass)) {
-                    // Spin's Attempt to Load
-                    tryLockedLoadMetaData(metaData);
-                } else {
-                    if (Objects.nonNull(metaData.getContextPath()) && 
Objects.nonNull(refreshUpstreamCache.get(metaData.getContextPath()))) {
-                        refreshTarsInvokePrxList(metaData, 
refreshUpstreamCache.get(metaData.getContextPath()));
-                    }
-                    break;
-                }
-            } catch (Exception e) {
-                LOG.error("ShenyuTarsPluginInitializeException: init tars ref 
ex:{}", e.getMessage());
-                break;
+        try {
+            if (Objects.isNull(prxClassCache.get(metaData.getPath()))) {
+                lockedLoadMetaData(metaData);
+            }
+            if (Objects.nonNull(metaData.getContextPath()) && 
Objects.nonNull(refreshUpstreamCache.get(metaData.getContextPath()))) {
+                refreshTarsInvokePrxList(metaData, 
refreshUpstreamCache.get(metaData.getContextPath()));
             }
+        } catch (Exception e) {
+            LOG.error("ShenyuTarsPluginInitializeException: init tars ref 
ex:{}", e.getMessage());
         }
     }
-    
+
     /**
-     * Try to load once, if it fails, it will give up.<br>
+     * Load metadata while holding the initialization lock.<br>
      * add class cache to {@link #prxClassCache}.<br>
      * add method params cache to {@link #prxParamCache}.<br>
      * add paths cache to {@link #ctxPathCache}.<br>
@@ -215,23 +208,24 @@ public final class ApplicationConfigCache {
      * @throws ClassNotFoundException meta data class definition not found
      * @see ReentrantLock
      */
-    private void tryLockedLoadMetaData(final MetaData metaData) throws 
ClassNotFoundException {
-        Objects.requireNonNull(LOCK);
-        if (LOCK.tryLock()) {
-            try {
-                if (StringUtils.isEmpty(metaData.getRpcExt())) {
-                    throw new 
ShenyuTarsPluginException("ShenyuTarsPluginInitializeException: can't init prx 
with empty ext string");
-                }
-                Class<?> prxClazz = buildClassDefinition(metaData);
-                prxClassCache.put(metaData.getPath(), prxClazz);
-                List<MetaData> paths = 
ctxPathCache.getOrDefault(metaData.getContextPath(), new ArrayList<>());
-                if (!IterableUtils.matchesAny(paths, p -> 
p.getPath().equals(metaData.getPath()))) {
-                    paths.add(metaData);
-                }
-                ctxPathCache.put(metaData.getContextPath(), paths);
-            } finally {
-                LOCK.unlock();
+    private void lockedLoadMetaData(final MetaData metaData) throws 
ClassNotFoundException {
+        LOCK.lock();
+        try {
+            if (prxClassCache.containsKey(metaData.getPath())) {
+                return;
+            }
+            if (StringUtils.isEmpty(metaData.getRpcExt())) {
+                throw new 
ShenyuTarsPluginException("ShenyuTarsPluginInitializeException: can't init prx 
with empty ext string");
+            }
+            Class<?> prxClazz = buildClassDefinition(metaData);
+            prxClassCache.put(metaData.getPath(), prxClazz);
+            List<MetaData> paths = 
ctxPathCache.getOrDefault(metaData.getContextPath(), new ArrayList<>());
+            if (!IterableUtils.matchesAny(paths, p -> 
p.getPath().equals(metaData.getPath()))) {
+                paths.add(metaData);
             }
+            ctxPathCache.put(metaData.getContextPath(), paths);
+        } finally {
+            LOCK.unlock();
         }
     }
     
diff --git 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-tars/src/test/java/org/apache/shenyu/plugin/tars/cache/ApplicationConfigCacheTest.java
 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-tars/src/test/java/org/apache/shenyu/plugin/tars/cache/ApplicationConfigCacheTest.java
index cbf228627e..eadccbb998 100644
--- 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-tars/src/test/java/org/apache/shenyu/plugin/tars/cache/ApplicationConfigCacheTest.java
+++ 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-tars/src/test/java/org/apache/shenyu/plugin/tars/cache/ApplicationConfigCacheTest.java
@@ -30,13 +30,16 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.junit.jupiter.MockitoExtension;
 
+import java.lang.reflect.Field;
 import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.concurrent.locks.ReentrantLock;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -121,6 +124,30 @@ public final class ApplicationConfigCacheTest {
         });
     }
 
+    @Test
+    public void testInitPrxWaitsForInitializationLock() throws Exception {
+        final Field lockField = 
ApplicationConfigCache.class.getDeclaredField("LOCK");
+        lockField.setAccessible(true);
+        final ReentrantLock lock = (ReentrantLock) lockField.get(null);
+        final MetaData metaData = new MetaData("id", "appName", "contextPath", 
"waitingPath",
+                RpcTypeEnum.TARS.getName(), "serviceName", "methodName", 
"parameterTypes",
+                null, false, Constants.SYS_DEFAULT_NAMESPACE_ID);
+        final Thread initThread = new Thread(() -> 
applicationConfigCacheUnderTest.initPrx(metaData));
+
+        lock.lock();
+        try {
+            initThread.start();
+            for (int i = 0; i < 100 && !lock.hasQueuedThread(initThread); i++) 
{
+                Thread.sleep(10L);
+            }
+            assertTrue(lock.hasQueuedThread(initThread));
+        } finally {
+            lock.unlock();
+        }
+        initThread.join(1000L);
+        assertFalse(initThread.isAlive());
+    }
+
     @Test
     public void testInitPrx() {
         final MetaData metaData = new MetaData("id", "127.0.0.1:8080", 
"contextPath",

Reply via email to