
com.alibaba.nacos.naming.misc.SwitchManager Maven / Gradle / Ivy
/*
* Copyright 1999-2018 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
*
* 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 com.alibaba.nacos.naming.misc;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.common.utils.ConvertUtils;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.naming.consistency.ConsistencyService;
import com.alibaba.nacos.naming.consistency.Datum;
import com.alibaba.nacos.naming.consistency.KeyBuilder;
import com.alibaba.nacos.naming.consistency.RecordListener;
import com.alibaba.nacos.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
/**
* Switch manager.
*
* @author nkorange
* @since 1.0.0
*/
@Component
public class SwitchManager implements RecordListener {
@Autowired
private SwitchDomain switchDomain;
@Resource(name = "consistencyDelegate")
private ConsistencyService consistencyService;
ReentrantLock lock = new ReentrantLock();
/**
* Init switch manager.
*/
@PostConstruct
public void init() {
try {
consistencyService.listen(KeyBuilder.getSwitchDomainKey(), this);
} catch (NacosException e) {
Loggers.SRV_LOG.error("listen switch service failed.", e);
}
}
/**
* Update switch information.
*
* @param entry item entry of switch, {@link SwitchEntry}
* @param value switch value
* @param debug whether debug
* @throws Exception exception
*/
public void update(String entry, String value, boolean debug) throws Exception {
lock.lock();
try {
Datum datum = consistencyService.get(KeyBuilder.getSwitchDomainKey());
SwitchDomain switchDomain;
if (datum != null && datum.value != null) {
switchDomain = (SwitchDomain) datum.value;
} else {
switchDomain = this.switchDomain.clone();
}
if (SwitchEntry.BATCH.equals(entry)) {
//batch update
SwitchDomain dom = JacksonUtils.toObj(value, SwitchDomain.class);
dom.setEnableStandalone(switchDomain.isEnableStandalone());
if (dom.getHttpHealthParams().getMin() < SwitchDomain.HttpHealthParams.MIN_MIN
|| dom.getTcpHealthParams().getMin() < SwitchDomain.HttpHealthParams.MIN_MIN) {
throw new IllegalArgumentException("min check time for http or tcp is too small(<500)");
}
if (dom.getHttpHealthParams().getMax() < SwitchDomain.HttpHealthParams.MIN_MAX
|| dom.getTcpHealthParams().getMax() < SwitchDomain.HttpHealthParams.MIN_MAX) {
throw new IllegalArgumentException("max check time for http or tcp is too small(<3000)");
}
if (dom.getHttpHealthParams().getFactor() < 0 || dom.getHttpHealthParams().getFactor() > 1
|| dom.getTcpHealthParams().getFactor() < 0 || dom.getTcpHealthParams().getFactor() > 1) {
throw new IllegalArgumentException("malformed factor");
}
switchDomain = dom;
}
if (entry.equals(SwitchEntry.DISTRO_THRESHOLD)) {
float threshold = Float.parseFloat(value);
if (threshold <= 0) {
throw new IllegalArgumentException("distroThreshold can not be zero or negative: " + threshold);
}
switchDomain.setDistroThreshold(threshold);
}
if (entry.equals(SwitchEntry.CLIENT_BEAT_INTERVAL)) {
long clientBeatInterval = Long.parseLong(value);
switchDomain.setClientBeatInterval(clientBeatInterval);
}
if (entry.equals(SwitchEntry.PUSH_VERSION)) {
String type = value.split(":")[0];
String version = value.split(":")[1];
if (!version.matches(UtilsAndCommons.VERSION_STRING_SYNTAX)) {
throw new IllegalArgumentException(
"illegal version, must match: " + UtilsAndCommons.VERSION_STRING_SYNTAX);
}
if (StringUtils.equals(SwitchEntry.CLIENT_JAVA, type)) {
switchDomain.setPushJavaVersion(version);
} else if (StringUtils.equals(SwitchEntry.CLIENT_PYTHON, type)) {
switchDomain.setPushPythonVersion(version);
} else if (StringUtils.equals(SwitchEntry.CLIENT_C, type)) {
switchDomain.setPushCVersion(version);
} else if (StringUtils.equals(SwitchEntry.CLIENT_GO, type)) {
switchDomain.setPushGoVersion(version);
} else {
throw new IllegalArgumentException("unsupported client type: " + type);
}
}
if (entry.equals(SwitchEntry.PUSH_CACHE_MILLIS)) {
long cacheMillis = Long.parseLong(value);
if (cacheMillis < SwitchEntry.MIN_PUSH_CACHE_TIME_MIILIS) {
throw new IllegalArgumentException("min cache time for http or tcp is too small(<10000)");
}
switchDomain.setDefaultPushCacheMillis(cacheMillis);
}
// extremely careful while modifying this, cause it will affect all clients without pushing enabled
if (entry.equals(SwitchEntry.DEFAULT_CACHE_MILLIS)) {
long cacheMillis = Long.parseLong(value);
if (cacheMillis < SwitchEntry.MIN_CACHE_TIME_MIILIS) {
throw new IllegalArgumentException("min default cache time is too small(<1000)");
}
switchDomain.setDefaultCacheMillis(cacheMillis);
}
if (entry.equals(SwitchEntry.MASTERS)) {
List masters = Arrays.asList(value.split(","));
switchDomain.setMasters(masters);
}
if (entry.equals(SwitchEntry.DISTRO)) {
boolean enabled = Boolean.parseBoolean(value);
switchDomain.setDistroEnabled(enabled);
}
if (entry.equals(SwitchEntry.CHECK)) {
boolean enabled = Boolean.parseBoolean(value);
switchDomain.setHealthCheckEnabled(enabled);
}
if (entry.equals(SwitchEntry.PUSH_ENABLED)) {
boolean enabled = Boolean.parseBoolean(value);
switchDomain.setPushEnabled(enabled);
}
if (entry.equals(SwitchEntry.SERVICE_STATUS_SYNC_PERIOD)) {
long millis = Long.parseLong(value);
if (millis < SwitchEntry.MIN_SERVICE_SYNC_TIME_MIILIS) {
throw new IllegalArgumentException("serviceStatusSynchronizationPeriodMillis is too small(<5000)");
}
switchDomain.setServiceStatusSynchronizationPeriodMillis(millis);
}
if (entry.equals(SwitchEntry.SERVER_STATUS_SYNC_PERIOD)) {
long millis = Long.parseLong(value);
if (millis < SwitchEntry.MIN_SERVER_SYNC_TIME_MIILIS) {
throw new IllegalArgumentException("serverStatusSynchronizationPeriodMillis is too small(<15000)");
}
switchDomain.setServerStatusSynchronizationPeriodMillis(millis);
}
if (entry.equals(SwitchEntry.HEALTH_CHECK_TIMES)) {
int times = Integer.parseInt(value);
switchDomain.setCheckTimes(times);
}
if (entry.equals(SwitchEntry.DISABLE_ADD_IP)) {
boolean disableAddIp = Boolean.parseBoolean(value);
switchDomain.setDisableAddIP(disableAddIp);
}
if (entry.equals(SwitchEntry.SEND_BEAT_ONLY)) {
boolean sendBeatOnly = Boolean.parseBoolean(value);
switchDomain.setSendBeatOnly(sendBeatOnly);
}
if (entry.equals(SwitchEntry.LIMITED_URL_MAP)) {
Map limitedUrlMap = new HashMap<>(16);
if (!StringUtils.isEmpty(value)) {
String[] entries = value.split(",");
for (String each : entries) {
String[] parts = each.split(":");
if (parts.length < 2) {
throw new IllegalArgumentException("invalid input for limited urls");
}
String limitedUrl = parts[0];
if (StringUtils.isEmpty(limitedUrl)) {
throw new IllegalArgumentException("url can not be empty, url: " + limitedUrl);
}
int statusCode = Integer.parseInt(parts[1]);
if (statusCode <= 0) {
throw new IllegalArgumentException("illegal normal status code: " + statusCode);
}
limitedUrlMap.put(limitedUrl, statusCode);
}
switchDomain.setLimitedUrlMap(limitedUrlMap);
}
}
if (entry.equals(SwitchEntry.ENABLE_STANDALONE)) {
if (!StringUtils.isNotEmpty(value)) {
switchDomain.setEnableStandalone(Boolean.parseBoolean(value));
}
}
if (entry.equals(SwitchEntry.OVERRIDDEN_SERVER_STATUS)) {
String status = value;
if (Constants.NULL_STRING.equals(status)) {
status = StringUtils.EMPTY;
}
switchDomain.setOverriddenServerStatus(status);
}
if (entry.equals(SwitchEntry.DEFAULT_INSTANCE_EPHEMERAL)) {
switchDomain.setDefaultInstanceEphemeral(Boolean.parseBoolean(value));
}
if (entry.equals(SwitchEntry.DISTRO_SERVER_EXPIRED_MILLIS)) {
switchDomain.setDistroServerExpiredMillis(Long.parseLong(value));
}
if (entry.equals(SwitchEntry.LIGHT_BEAT_ENABLED)) {
switchDomain.setLightBeatEnabled(ConvertUtils.toBoolean(value));
}
if (entry.equals(SwitchEntry.AUTO_CHANGE_HEALTH_CHECK_ENABLED)) {
switchDomain.setAutoChangeHealthCheckEnabled(ConvertUtils.toBoolean(value));
}
if (entry.equals(SwitchEntry.DOUBLE_WRITE_ENABLED)) {
switchDomain.setDoubleWriteEnabled(ConvertUtils.toBoolean(value));
}
if (debug) {
update(switchDomain);
} else {
consistencyService.put(KeyBuilder.getSwitchDomainKey(), switchDomain);
}
} finally {
lock.unlock();
}
}
/**
* Update switch information from new switch domain.
*
* @param newSwitchDomain new switch domain
*/
public void update(SwitchDomain newSwitchDomain) {
switchDomain.setMasters(newSwitchDomain.getMasters());
switchDomain.setAdWeightMap(newSwitchDomain.getAdWeightMap());
switchDomain.setDefaultPushCacheMillis(newSwitchDomain.getDefaultPushCacheMillis());
switchDomain.setClientBeatInterval(newSwitchDomain.getClientBeatInterval());
switchDomain.setDefaultCacheMillis(newSwitchDomain.getDefaultCacheMillis());
switchDomain.setDistroThreshold(newSwitchDomain.getDistroThreshold());
switchDomain.setHealthCheckEnabled(newSwitchDomain.isHealthCheckEnabled());
switchDomain.setAutoChangeHealthCheckEnabled(newSwitchDomain.isAutoChangeHealthCheckEnabled());
switchDomain.setDistroEnabled(newSwitchDomain.isDistroEnabled());
switchDomain.setPushEnabled(newSwitchDomain.isPushEnabled());
switchDomain.setEnableStandalone(newSwitchDomain.isEnableStandalone());
switchDomain.setCheckTimes(newSwitchDomain.getCheckTimes());
switchDomain.setHttpHealthParams(newSwitchDomain.getHttpHealthParams());
switchDomain.setTcpHealthParams(newSwitchDomain.getTcpHealthParams());
switchDomain.setMysqlHealthParams(newSwitchDomain.getMysqlHealthParams());
switchDomain.setIncrementalList(newSwitchDomain.getIncrementalList());
switchDomain.setServerStatusSynchronizationPeriodMillis(
newSwitchDomain.getServerStatusSynchronizationPeriodMillis());
switchDomain.setServiceStatusSynchronizationPeriodMillis(
newSwitchDomain.getServiceStatusSynchronizationPeriodMillis());
switchDomain.setDisableAddIP(newSwitchDomain.isDisableAddIP());
switchDomain.setSendBeatOnly(newSwitchDomain.isSendBeatOnly());
switchDomain.setLimitedUrlMap(newSwitchDomain.getLimitedUrlMap());
switchDomain.setDistroServerExpiredMillis(newSwitchDomain.getDistroServerExpiredMillis());
switchDomain.setPushGoVersion(newSwitchDomain.getPushGoVersion());
switchDomain.setPushJavaVersion(newSwitchDomain.getPushJavaVersion());
switchDomain.setPushPythonVersion(newSwitchDomain.getPushPythonVersion());
switchDomain.setPushCVersion(newSwitchDomain.getPushCVersion());
switchDomain.setEnableAuthentication(newSwitchDomain.isEnableAuthentication());
switchDomain.setOverriddenServerStatus(newSwitchDomain.getOverriddenServerStatus());
switchDomain.setDefaultInstanceEphemeral(newSwitchDomain.isDefaultInstanceEphemeral());
switchDomain.setLightBeatEnabled(newSwitchDomain.isLightBeatEnabled());
switchDomain.setDoubleWriteEnabled(newSwitchDomain.isDoubleWriteEnabled());
}
public SwitchDomain getSwitchDomain() {
return switchDomain;
}
@Override
public boolean interests(String key) {
return KeyBuilder.matchSwitchKey(key);
}
@Override
public boolean matchUnlistenKey(String key) {
return KeyBuilder.matchSwitchKey(key);
}
@Override
public void onChange(String key, SwitchDomain domain) throws Exception {
update(domain);
}
@Override
public void onDelete(String key) throws Exception {
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy