
com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager Maven / Gradle / Ivy
/*
* Copyright 1999-2019 Alibaba Group Holding Ltd.
*
* Licensed 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
*
* https://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 com.alibaba.csp.sentinel.adapter.gateway.common.api;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import com.alibaba.csp.sentinel.log.RecordLog;
import com.alibaba.csp.sentinel.property.DynamicSentinelProperty;
import com.alibaba.csp.sentinel.property.PropertyListener;
import com.alibaba.csp.sentinel.property.SentinelProperty;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.csp.sentinel.spi.SpiLoader;
import com.alibaba.csp.sentinel.util.StringUtil;
/**
* Manager for gateway API definitions.
*
* @author Eric Zhao
* @since 1.6.0
*/
public final class GatewayApiDefinitionManager {
private static final Map API_MAP = new ConcurrentHashMap<>();
private static final ApiDefinitionPropertyListener LISTENER = new ApiDefinitionPropertyListener();
private static SentinelProperty> currentProperty = new DynamicSentinelProperty<>();
/**
* The map keeps all found ApiDefinitionChangeObserver (class name as key).
*/
private static final Map API_CHANGE_OBSERVERS = new ConcurrentHashMap<>();
static {
try {
currentProperty.addListener(LISTENER);
initializeApiChangeObserverSpi();
} catch (Throwable ex) {
RecordLog.warn("[GatewayApiDefinitionManager] Failed to initialize", ex);
ex.printStackTrace();
}
}
private static void initializeApiChangeObserverSpi() {
List listeners = SpiLoader.of(ApiDefinitionChangeObserver.class).loadInstanceList();
for (ApiDefinitionChangeObserver e : listeners) {
API_CHANGE_OBSERVERS.put(e.getClass().getCanonicalName(), e);
RecordLog.info("[GatewayApiDefinitionManager] ApiDefinitionChangeObserver added: {}"
, e.getClass().getCanonicalName());
}
}
public static void register2Property(SentinelProperty> property) {
AssertUtil.notNull(property, "property cannot be null");
synchronized (LISTENER) {
RecordLog.info("[GatewayApiDefinitionManager] Registering new property to gateway API definition manager");
currentProperty.removeListener(LISTENER);
property.addListener(LISTENER);
currentProperty = property;
}
}
/**
* Load given gateway API definitions and apply to downstream observers.
*
* @param apiDefinitions set of gateway API definitions
* @return true if updated, or else false
*/
public static boolean loadApiDefinitions(Set apiDefinitions) {
return currentProperty.updateValue(apiDefinitions);
}
public static ApiDefinition getApiDefinition(final String apiName) {
if (apiName == null) {
return null;
}
return API_MAP.get(apiName);
}
public static Set getApiDefinitions() {
return new HashSet<>(API_MAP.values());
}
private static final class ApiDefinitionPropertyListener implements PropertyListener> {
@Override
public void configUpdate(Set set) {
applyApiUpdateInternal(set);
RecordLog.info("[GatewayApiDefinitionManager] Api definition updated: {}", API_MAP);
}
@Override
public void configLoad(Set set) {
applyApiUpdateInternal(set);
RecordLog.info("[GatewayApiDefinitionManager] Api definition loaded: {}", API_MAP);
}
private static synchronized void applyApiUpdateInternal(Set set) {
if (set == null || set.isEmpty()) {
API_MAP.clear();
notifyDownstreamListeners(new HashSet());
return;
}
Map map = new HashMap<>(set.size());
Set validSet = new HashSet<>();
for (ApiDefinition definition : set) {
if (isValidApi(definition)) {
map.put(definition.getApiName(), definition);
validSet.add(definition);
}
}
API_MAP.clear();
API_MAP.putAll(map);
// propagate to downstream.
notifyDownstreamListeners(validSet);
}
}
private static void notifyDownstreamListeners(/*@Valid*/ final Set definitions) {
try {
for (Map.Entry, ApiDefinitionChangeObserver> entry : API_CHANGE_OBSERVERS.entrySet()) {
entry.getValue().onChange(definitions);
}
} catch (Exception ex) {
RecordLog.warn("[GatewayApiDefinitionManager] WARN: failed to notify downstream api listeners", ex);
}
}
public static boolean isValidApi(ApiDefinition apiDefinition) {
return apiDefinition != null && StringUtil.isNotBlank(apiDefinition.getApiName())
&& apiDefinition.getPredicateItems() != null;
}
static void addApiChangeListener(ApiDefinitionChangeObserver listener) {
AssertUtil.notNull(listener, "listener cannot be null");
API_CHANGE_OBSERVERS.put(listener.getClass().getCanonicalName(), listener);
}
static void removeApiChangeListener(Class> clazz) {
AssertUtil.notNull(clazz, "class cannot be null");
API_CHANGE_OBSERVERS.remove(clazz.getCanonicalName());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy