Browse Source

fix #2792 Enhanced CPU load management and thread waiting logic for better system stability

Shinsuke Sugaya 1 year ago
parent
commit
becc83e9f2

+ 33 - 3
src/main/java/org/codelibs/fess/helper/SystemHelper.java

@@ -30,14 +30,17 @@ import java.nio.file.Path;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Calendar;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Properties;
+import java.util.Set;
 import java.util.TimeZone;
 import java.util.UUID;
 import java.util.concurrent.ExecutionException;
@@ -123,6 +126,8 @@ public class SystemHelper {
 
     protected Map<String, Supplier<String>> updateConfigListenerMap = new HashMap<>();
 
+    protected Set<String> waitingThreadNames = Collections.synchronizedSet(new HashSet<>());
+
     @PostConstruct
     public void init() {
         if (logger.isDebugEnabled()) {
@@ -589,15 +594,40 @@ public class SystemHelper {
     }
 
     public void calibrateCpuLoad() {
-        final int percent = ComponentUtil.getFessConfig().getAdaptiveLoadControlAsInteger();
+        final short percent = ComponentUtil.getFessConfig().getAdaptiveLoadControlAsInteger().shortValue();
         if (percent <= 0) {
             return;
         }
-        while (getSystemCpuPercent() > percent) {
+        short current = getSystemCpuPercent();
+        if (current < percent) {
+            return;
+        }
+        final String threadName = Thread.currentThread().getName();
+        try {
+            waitingThreadNames.add(threadName);
+            while (current >= percent) {
+                if (logger.isInfoEnabled()) {
+                    logger.info("Cpu Load {}% is greater than {}%. {} threads are waiting.", current, percent, waitingThreadNames.size());
+                }
+                if (logger.isDebugEnabled()) {
+                    logger.debug("Waiting threads: {}", waitingThreadNames);
+                }
+                ThreadUtil.sleep(systemCpuCheckInterval);
+                current = getSystemCpuPercent();
+            }
+        } finally {
+            waitingThreadNames.remove(threadName);
+        }
+    }
+
+    public void waitForNoWaitingThreads() {
+        int count = waitingThreadNames.size();
+        while (count > 0) {
             if (logger.isInfoEnabled()) {
-                logger.info("Cpu Load {}% is greater than {}%.", getSystemCpuPercent(), percent);
+                logger.info("{} threads are waiting.", count);
             }
             ThreadUtil.sleep(systemCpuCheckInterval);
+            count = waitingThreadNames.size();
         }
     }
 

+ 4 - 3
src/main/java/org/codelibs/fess/indexer/IndexUpdater.java

@@ -197,6 +197,9 @@ public class IndexUpdater extends Thread {
                     final int sessionIdListSize = finishedSessionIdList.size();
                     intervalControlHelper.setCrawlerRunning(true);
 
+                    docList.clear();
+                    accessResultList.clear();
+
                     updateTime = System.currentTimeMillis() - updateTime;
 
                     final long interval = updateInterval - updateTime;
@@ -206,9 +209,7 @@ public class IndexUpdater extends Thread {
                     }
 
                     systemHelper.calibrateCpuLoad();
-
-                    docList.clear();
-                    accessResultList.clear();
+                    systemHelper.waitForNoWaitingThreads();
 
                     intervalControlHelper.delayByRules();