This is an automated email from the ASF dual-hosted git repository. liubao pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git
commit 0c41408c5cf1f9989cff1cdb421834c6dbef5d6f Author: liubao <bi...@qq.com> AuthorDate: Mon May 25 15:32:31 2020 +0800 [SCB-1930]When MicroserivceVersions.setInstances continues fail will cause OOM --- .../config/inject/ConfigObjectFactory.java | 3 +- .../config/priority/PriorityProperty.java | 14 +++++---- .../config/priority/PriorityPropertyManager.java | 34 +++++++++++++--------- .../inspector/internal/InspectorImpl.java | 3 +- 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/inject/ConfigObjectFactory.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/inject/ConfigObjectFactory.java index 8dee778..1c73d84 100644 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/inject/ConfigObjectFactory.java +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/inject/ConfigObjectFactory.java @@ -25,7 +25,6 @@ import org.apache.servicecomb.config.priority.PriorityProperty; import org.apache.servicecomb.config.priority.PriorityPropertyManager; import org.apache.servicecomb.foundation.common.utils.JsonUtils; import org.apache.servicecomb.foundation.common.utils.LambdaMetafactoryUtils; -import org.apache.servicecomb.foundation.common.utils.bean.Setter; import org.apache.servicecomb.foundation.common.utils.bean.SetterWrapper; import com.fasterxml.jackson.databind.BeanDescription; @@ -104,7 +103,7 @@ public class ConfigObjectFactory { new SetterWrapper(LambdaMetafactoryUtils.createSetter(propertyDefinition.getSetter().getAnnotated())); PriorityProperty<?> priorityProperty = createPriorityProperty(propertyDefinition.getField().getAnnotated()); - priorityProperty.setCallback(value -> setter.set(instance, value)); + priorityProperty.setCallback((value, target) -> setter.set(target, value), instance); priorityProperties.add(priorityProperty); } } diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/PriorityProperty.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/PriorityProperty.java index 53cc9cc..a07f8c3 100644 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/PriorityProperty.java +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/PriorityProperty.java @@ -19,7 +19,7 @@ package org.apache.servicecomb.config.priority; import java.lang.reflect.Type; import java.util.Arrays; import java.util.Objects; -import java.util.function.Consumer; +import java.util.function.BiConsumer; import java.util.function.Function; import org.slf4j.Logger; @@ -53,7 +53,7 @@ public class PriorityProperty<T> { private Function<DynamicProperty, T> internalValueReader; - private Consumer<T> callback = v -> { + private BiConsumer<T, Object> callback = (t, u) -> { }; @SuppressWarnings("unchecked") @@ -144,6 +144,10 @@ public class PriorityProperty<T> { } synchronized void updateFinalValue(boolean init) { + updateFinalValue(init, this); + } + + synchronized void updateFinalValue(boolean init, Object target) { T lastValue = finalValue; String effectiveKey = "default value"; @@ -171,15 +175,15 @@ public class PriorityProperty<T> { joinedPriorityKeys, finalValue, value, effectiveKey); } finalValue = value; - callback.accept(finalValue); + callback.accept(finalValue, target); } public T getValue() { return finalValue; } - public void setCallback(Consumer<T> callback) { + public void setCallback(BiConsumer<T, Object> callback, Object target) { this.callback = callback; - callback.accept(finalValue); + callback.accept(finalValue, target); } } diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/PriorityPropertyManager.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/PriorityPropertyManager.java index 2bbceb2..a7d8544 100644 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/PriorityPropertyManager.java +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/PriorityPropertyManager.java @@ -23,25 +23,29 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.WeakHashMap; import org.apache.commons.configuration.event.ConfigurationEvent; import org.apache.commons.configuration.event.ConfigurationListener; import org.apache.servicecomb.config.inject.ConfigObjectFactory; import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; +import com.google.common.annotations.VisibleForTesting; import com.netflix.config.ConfigurationManager; import com.netflix.config.DynamicPropertyFactory; public class PriorityPropertyManager { private ConfigurationListener configurationListener = this::configurationListener; - private Map<PriorityProperty<?>, PriorityProperty<?>> priorityPropertyMap = new ConcurrentHashMapEx<>(); + private Map<PriorityProperty<?>, Boolean> priorityPropertyMap = + Collections.synchronizedMap(new WeakHashMap<>()); - private Map<Object, List<PriorityProperty<?>>> configObjectMap = new ConcurrentHashMapEx<>(); + private Map<Object, List<PriorityProperty<?>>> configObjectMap = + Collections.synchronizedMap(new WeakHashMap<>()); // will be reset to null after register or unregister // and build when configuration changed - private Map<String, List<PriorityProperty<?>>> keyCache; + private Map<Object, Map<String, List<PriorityProperty<?>>>> keyCache; public PriorityPropertyManager() { // make sure create a DynamicPropertyFactory instance @@ -62,30 +66,33 @@ public class PriorityPropertyManager { if (keyCache == null) { keyCache = new ConcurrentHashMapEx<>(); - updateCache(priorityPropertyMap.values()); - configObjectMap.values().stream().forEach(this::updateCache); + updateCache(new Object(), priorityPropertyMap.keySet()); + configObjectMap.forEach((k, v) -> updateCache(k, v)); } if (event.getPropertyName() != null) { - keyCache.getOrDefault(event.getPropertyName(), Collections.emptyList()).stream() - .forEach(p -> p.updateFinalValue(false)); + keyCache.forEach((k, v) -> v.getOrDefault(event.getPropertyName(), Collections.emptyList()).stream() + .forEach(p -> p.updateFinalValue(false, k))); return; } // event like add configuration source, need to make a global refresh - keyCache.values().stream().flatMap(Collection::stream).forEach(p -> p.updateFinalValue(false)); + keyCache.forEach( + (k, v) -> v.values().stream().flatMap(Collection::stream).forEach( + p -> p.updateFinalValue(false, k))); } - private void updateCache(Collection<PriorityProperty<?>> properties) { + private void updateCache(Object target, Collection<PriorityProperty<?>> properties) { + Map<String, List<PriorityProperty<?>>> targetMap = keyCache.computeIfAbsent(target, k -> new HashMap<>()); for (PriorityProperty<?> priorityProperty : properties) { for (String key : priorityProperty.getPriorityKeys()) { - keyCache.computeIfAbsent(key, k -> new ArrayList<>()).add(priorityProperty); + targetMap.computeIfAbsent(key, k -> new ArrayList<>()).add(priorityProperty); } - priorityProperty.updateFinalValue(false); + priorityProperty.updateFinalValue(false, target); } } - public Map<PriorityProperty<?>, PriorityProperty<?>> getPriorityPropertyMap() { + public Map<PriorityProperty<?>, Boolean> getPriorityPropertyMap() { return priorityPropertyMap; } @@ -94,7 +101,7 @@ public class PriorityPropertyManager { } private synchronized void registerPriorityProperty(PriorityProperty<?> property) { - priorityPropertyMap.put(property, property); + priorityPropertyMap.put(property, Boolean.TRUE); keyCache = null; } @@ -138,6 +145,7 @@ public class PriorityPropertyManager { return new PriorityProperty<>(cls, invalidValue, defaultValue, priorityKeys); } + @VisibleForTesting public <T> PriorityProperty<T> createPriorityProperty(Type cls, T invalidValue, T defaultValue, String... priorityKeys) { PriorityProperty<T> priorityProperty = new PriorityProperty<>(cls, invalidValue, defaultValue, priorityKeys); diff --git a/inspector/src/main/java/org/apache/servicecomb/inspector/internal/InspectorImpl.java b/inspector/src/main/java/org/apache/servicecomb/inspector/internal/InspectorImpl.java index e86ad2a..6e87be2 100644 --- a/inspector/src/main/java/org/apache/servicecomb/inspector/internal/InspectorImpl.java +++ b/inspector/src/main/java/org/apache/servicecomb/inspector/internal/InspectorImpl.java @@ -314,7 +314,8 @@ public class InspectorImpl { priorityPropertyManager.getConfigObjectMap().values().stream() .flatMap(Collection::stream) .forEach(p -> views.add(createPriorityPropertyView(p))); - priorityPropertyManager.getPriorityPropertyMap().values().forEach(p -> views.add(createPriorityPropertyView(p))); + priorityPropertyManager.getPriorityPropertyMap().keySet().forEach(p -> + views.add(createPriorityPropertyView(p))); return views; }