----初始化项目

This commit is contained in:
2025-09-19 20:49:14 +08:00
parent b345d2828d
commit df7765c400
2867 changed files with 359313 additions and 89 deletions

43
plugin/control/pom.xml Normal file
View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 1999-2020 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>nacos-plugin</artifactId>
<groupId>com.alibaba.nacos</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-control-plugin</artifactId>
<name>nacos-control-plugin ${project.version}</name>
<url>https://nacos.io</url>
<description>Nacos control plugin pom.xml file</description>
<dependencies>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-common</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,134 @@
/*
* Copyright 1999-2020 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.plugin.control;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.common.spi.NacosServiceLoader;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.plugin.control.configs.ControlConfigs;
import com.alibaba.nacos.plugin.control.connection.ConnectionControlManager;
import com.alibaba.nacos.plugin.control.connection.DefaultConnectionControlManager;
import com.alibaba.nacos.plugin.control.event.ConnectionLimitRuleChangeEvent;
import com.alibaba.nacos.plugin.control.event.TpsControlRuleChangeEvent;
import com.alibaba.nacos.plugin.control.rule.storage.RuleStorageProxy;
import com.alibaba.nacos.plugin.control.spi.ControlManagerBuilder;
import com.alibaba.nacos.plugin.control.tps.TpsControlManager;
import com.alibaba.nacos.plugin.control.tps.DefaultTpsControlManager;
import java.util.Optional;
/**
* control manager center.
*
* @author shiyiyue
*/
public class ControlManagerCenter {
static volatile ControlManagerCenter instance = null;
private final RuleStorageProxy ruleStorageProxy;
private TpsControlManager tpsControlManager;
private ConnectionControlManager connectionControlManager;
private ControlManagerCenter() {
ruleStorageProxy = RuleStorageProxy.getInstance();
Optional<ControlManagerBuilder> controlManagerBuilder = findTargetControlManagerBuilder();
if (controlManagerBuilder.isPresent()) {
initConnectionManager(controlManagerBuilder.get());
initTpsControlManager(controlManagerBuilder.get());
} else {
buildNoLimitControlManagers();
}
}
private void initConnectionManager(ControlManagerBuilder controlManagerBuilder) {
try {
connectionControlManager = controlManagerBuilder.buildConnectionControlManager();
Loggers.CONTROL.info("Build connection control manager, class={}",
connectionControlManager.getClass().getCanonicalName());
} catch (Exception e) {
Loggers.CONTROL.warn("Build connection control manager failed, use no limit manager replaced.", e);
connectionControlManager = new DefaultConnectionControlManager();
}
}
private void initTpsControlManager(ControlManagerBuilder controlManagerBuilder) {
try {
tpsControlManager = controlManagerBuilder.buildTpsControlManager();
Loggers.CONTROL
.info("Build tps control manager, class={}", tpsControlManager.getClass().getCanonicalName());
} catch (Exception e) {
Loggers.CONTROL.warn("Build tps control manager failed, use no limit manager replaced.", e);
tpsControlManager = new DefaultTpsControlManager();
}
}
private Optional<ControlManagerBuilder> findTargetControlManagerBuilder() {
String controlManagerType = ControlConfigs.getInstance().getControlManagerType();
if (StringUtils.isEmpty(controlManagerType)) {
Loggers.CONTROL.info("Not configure type of control plugin, no limit control for current node.");
return Optional.empty();
}
for (ControlManagerBuilder each : NacosServiceLoader.load(ControlManagerBuilder.class)) {
Loggers.CONTROL.info("Found control manager plugin of name={}", each.getName());
if (controlManagerType.equalsIgnoreCase(each.getName())) {
return Optional.of(each);
}
}
Loggers.CONTROL.warn("Not found control manager plugin of name");
return Optional.empty();
}
private void buildNoLimitControlManagers() {
connectionControlManager = new DefaultConnectionControlManager();
tpsControlManager = new DefaultTpsControlManager();
}
public RuleStorageProxy getRuleStorageProxy() {
return ruleStorageProxy;
}
public TpsControlManager getTpsControlManager() {
return tpsControlManager;
}
public ConnectionControlManager getConnectionControlManager() {
return connectionControlManager;
}
public static ControlManagerCenter getInstance() {
if (instance == null) {
synchronized (ControlManagerCenter.class) {
if (instance == null) {
instance = new ControlManagerCenter();
}
}
}
return instance;
}
public void reloadTpsControlRule(String pointName, boolean external) {
NotifyCenter.publishEvent(new TpsControlRuleChangeEvent(pointName, external));
}
public void reloadConnectionControlRule(boolean external) {
NotifyCenter.publishEvent(new ConnectionLimitRuleChangeEvent(external));
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 1999-2020 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.plugin.control;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* cotrol loggers.
*
* @author shiyiyue
*/
public class Loggers {
public static final Logger CONTROL = LoggerFactory.getLogger("com.alibaba.nacos.plugin.control");
public static final Logger TPS = LoggerFactory.getLogger("com.alibaba.nacos.plugin.control.tps");
public static final Logger CONNECTION = LoggerFactory.getLogger("com.alibaba.nacos.plugin.control.connection");
}

View File

@ -0,0 +1,92 @@
/*
* Copyright 1999-2020 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.plugin.control.configs;
import com.alibaba.nacos.common.spi.NacosServiceLoader;
import java.util.Collection;
/**
* control configs params.
*
* @author shiyiyue
*/
public class ControlConfigs {
private static volatile ControlConfigs instance = null;
public static ControlConfigs getInstance() {
if (instance == null) {
synchronized (ControlConfigs.class) {
if (instance == null) {
instance = new ControlConfigs();
Collection<ControlConfigsInitializer> load = NacosServiceLoader
.load(ControlConfigsInitializer.class);
for (ControlConfigsInitializer controlConfigsInitializer : load) {
controlConfigsInitializer.initialize(instance);
}
}
}
}
return instance;
}
public static void setInstance(ControlConfigs instance) {
ControlConfigs.instance = instance;
}
private String connectionRuntimeEjector = "nacos";
private String ruleExternalStorage = "";
private String localRuleStorageBaseDir = "";
private String controlManagerType = "";
public String getRuleExternalStorage() {
return ruleExternalStorage;
}
public void setRuleExternalStorage(String ruleExternalStorage) {
this.ruleExternalStorage = ruleExternalStorage;
}
public String getConnectionRuntimeEjector() {
return connectionRuntimeEjector;
}
public void setConnectionRuntimeEjector(String connectionRuntimeEjector) {
this.connectionRuntimeEjector = connectionRuntimeEjector;
}
public String getLocalRuleStorageBaseDir() {
return localRuleStorageBaseDir;
}
public void setLocalRuleStorageBaseDir(String localRuleStorageBaseDir) {
this.localRuleStorageBaseDir = localRuleStorageBaseDir;
}
public String getControlManagerType() {
return controlManagerType;
}
public void setControlManagerType(String controlManagerType) {
this.controlManagerType = controlManagerType;
}
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 1999-2020 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.plugin.control.configs;
/**
* control plugin configs initializer.
*
* @author shiyiyue
*/
public interface ControlConfigsInitializer {
/**
* init control configs.
*
* @param controlConfigs control configs.
*/
void initialize(ControlConfigs controlConfigs);
}

View File

@ -0,0 +1,145 @@
/*
* Copyright 1999-2020 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.plugin.control.connection;
import com.alibaba.nacos.common.executor.ExecutorFactory;
import com.alibaba.nacos.common.spi.NacosServiceLoader;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.plugin.control.Loggers;
import com.alibaba.nacos.plugin.control.connection.request.ConnectionCheckRequest;
import com.alibaba.nacos.plugin.control.connection.response.ConnectionCheckResponse;
import com.alibaba.nacos.plugin.control.connection.rule.ConnectionControlRule;
import com.alibaba.nacos.plugin.control.rule.parser.ConnectionControlRuleParser;
import com.alibaba.nacos.plugin.control.rule.parser.NacosConnectionControlRuleParser;
import com.alibaba.nacos.plugin.control.rule.storage.RuleStorageProxy;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* connection control manager.
*
* @author shiyiyue
*/
@SuppressWarnings("PMD.AbstractClassShouldStartWithAbstractNamingRule")
public abstract class ConnectionControlManager {
private final ConnectionControlRuleParser connectionControlRuleParser;
protected ConnectionControlRule connectionControlRule;
protected Collection<ConnectionMetricsCollector> metricsCollectorList;
private ScheduledExecutorService executorService;
public ConnectionControlManager() {
metricsCollectorList = NacosServiceLoader.load(ConnectionMetricsCollector.class);
Loggers.CONTROL.info("Load connection metrics collector,size={},{}", metricsCollectorList.size(),
metricsCollectorList);
this.connectionControlRuleParser = buildConnectionControlRuleParser();
initConnectionRule();
if (!metricsCollectorList.isEmpty()) {
initExecuteService();
startConnectionMetricsReport();
}
}
/**
* get manager name.
*
* @return
*/
public abstract String getName();
protected ConnectionControlRuleParser buildConnectionControlRuleParser() {
return new NacosConnectionControlRuleParser();
}
public ConnectionControlRuleParser getConnectionControlRuleParser() {
return connectionControlRuleParser;
}
private void initExecuteService() {
executorService = ExecutorFactory.newSingleScheduledExecutorService(r -> {
Thread thread = new Thread(r, "nacos.plugin.control.connection.reporter");
thread.setDaemon(true);
return thread;
});
}
private void initConnectionRule() {
RuleStorageProxy ruleStorageProxy = RuleStorageProxy.getInstance();
String localRuleContent = ruleStorageProxy.getLocalDiskStorage().getConnectionRule();
if (StringUtils.isNotBlank(localRuleContent)) {
Loggers.CONTROL.info("Found local disk connection rule content on start up,value ={}", localRuleContent);
} else if (ruleStorageProxy.getExternalStorage() != null
&& ruleStorageProxy.getExternalStorage().getConnectionRule() != null) {
localRuleContent = ruleStorageProxy.getExternalStorage().getConnectionRule();
if (StringUtils.isNotBlank(localRuleContent)) {
Loggers.CONTROL.info("Found persist disk connection rule content on start up ,value ={}",
localRuleContent);
}
}
if (StringUtils.isNotBlank(localRuleContent)) {
connectionControlRule = connectionControlRuleParser.parseRule(localRuleContent);
Loggers.CONTROL.info("init connection rule end");
} else {
Loggers.CONTROL.info("No connection rule content found ,use default empty rule ");
connectionControlRule = new ConnectionControlRule();
}
}
private void startConnectionMetricsReport() {
executorService.scheduleWithFixedDelay(new ConnectionMetricsReporter(), 0, 3000, TimeUnit.MILLISECONDS);
}
public ConnectionControlRule getConnectionLimitRule() {
return connectionControlRule;
}
/**
* apply connection rule.
*
* @param connectionControlRule not null.
*/
public abstract void applyConnectionLimitRule(ConnectionControlRule connectionControlRule);
/**
* check connection allowed.
*
* @param connectionCheckRequest connectionCheckRequest.
* @return
*/
public abstract ConnectionCheckResponse check(ConnectionCheckRequest connectionCheckRequest);
class ConnectionMetricsReporter implements Runnable {
@Override
public void run() {
Map<String, Integer> metricsTotalCount = metricsCollectorList.stream().collect(
Collectors.toMap(ConnectionMetricsCollector::getName, ConnectionMetricsCollector::getTotalCount));
int totalCount = metricsTotalCount.values().stream().mapToInt(Integer::intValue).sum();
Loggers.CONNECTION.info("ConnectionMetrics, totalCount = {}, detail = {}", totalCount, metricsTotalCount);
}
}
}

View File

@ -0,0 +1,47 @@
/*
* Copyright 1999-2020 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.plugin.control.connection;
/**
* connection count metrics collector.
*
* @author shiyiyue
*/
public interface ConnectionMetricsCollector {
/**
* get collector name.
*
* @return
*/
String getName();
/**
* get total count.
*
* @return
*/
int getTotalCount();
/**
* get count for ip.
*
* @param ip ip.
* @return
*/
int getCountForIp(String ip);
}

View File

@ -0,0 +1,58 @@
/*
* Copyright 1999-2023 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.plugin.control.connection;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.plugin.control.Loggers;
import com.alibaba.nacos.plugin.control.connection.request.ConnectionCheckRequest;
import com.alibaba.nacos.plugin.control.connection.response.ConnectionCheckCode;
import com.alibaba.nacos.plugin.control.connection.response.ConnectionCheckResponse;
import com.alibaba.nacos.plugin.control.connection.rule.ConnectionControlRule;
/**
* default connection control manager, no limit control.
*
* @author shiyiyue
*/
public class DefaultConnectionControlManager extends ConnectionControlManager {
@Override
public String getName() {
return "noLimit";
}
public DefaultConnectionControlManager() {
super();
}
@Override
public void applyConnectionLimitRule(ConnectionControlRule connectionControlRule) {
super.connectionControlRule = connectionControlRule;
Loggers.CONTROL.info("Connection control rule updated to -> {}",
(this.connectionControlRule == null ? null : JacksonUtils.toJson(this.connectionControlRule)));
Loggers.CONTROL.warn("Connection control updated, But connection control manager is no limit implementation.");
}
@Override
public ConnectionCheckResponse check(ConnectionCheckRequest connectionCheckRequest) {
ConnectionCheckResponse connectionCheckResponse = new ConnectionCheckResponse();
connectionCheckResponse.setSuccess(true);
connectionCheckResponse.setCode(ConnectionCheckCode.CHECK_SKIP);
return connectionCheckResponse;
}
}

View File

@ -0,0 +1,73 @@
/*
* Copyright 1999-2020 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.plugin.control.connection.request;
import java.util.Map;
/**
* connection check request.
*
* @author shiyiyue
*/
public class ConnectionCheckRequest {
String clientIp;
String appName;
String source;
Map<String, String> labels;
public ConnectionCheckRequest(String clientIp, String appName, String source) {
this.appName = appName;
this.clientIp = clientIp;
this.source = source;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public Map<String, String> getLabels() {
return labels;
}
public void setLabels(Map<String, String> labels) {
this.labels = labels;
}
public String getClientIp() {
return clientIp;
}
public void setClientIp(String clientIp) {
this.clientIp = clientIp;
}
public String getAppName() {
return appName;
}
public void setAppName(String appName) {
this.appName = appName;
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright 1999-2020 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.plugin.control.connection.response;
/**
* connection check code.
*
* @author shiyiyue
*/
public class ConnectionCheckCode {
/**
* check pass.
*/
public static final int PASS_BY_TOTAL = 200;
/**
* skip.
*/
public static final int CHECK_SKIP = 100;
/**
* deny by total over limit.
*/
public static final int DENY_BY_TOTAL_OVER = 300;
/**
* pass by monitor type.
*/
public static final int PASS_BY_MONITOR = 205;
}

View File

@ -0,0 +1,65 @@
/*
* Copyright 1999-2020 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.plugin.control.connection.response;
/**
* connection check response.
*
* @author shiyiyue
*/
public class ConnectionCheckResponse {
private boolean success;
private String message;
private int code;
private String limitMessage;
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getLimitMessage() {
return limitMessage;
}
public void setLimitMessage(String limitMessage) {
this.limitMessage = limitMessage;
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright 1999-2020 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.plugin.control.connection.rule;
import java.util.HashSet;
import java.util.Set;
/**
* connection control rule.
*
* @author shiyiyue
*/
public class ConnectionControlRule {
private Set<String> monitorIpList = new HashSet<>();
private int countLimit = -1;
public int getCountLimit() {
return countLimit;
}
public void setCountLimit(int countLimit) {
this.countLimit = countLimit;
}
public Set<String> getMonitorIpList() {
return monitorIpList;
}
public void setMonitorIpList(Set<String> monitorIpList) {
this.monitorIpList = monitorIpList;
}
}

View File

@ -0,0 +1,40 @@
/*
* Copyright 1999-2020 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.plugin.control.event;
import com.alibaba.nacos.common.notify.Event;
/**
* connection limit rule change event.
* @author zunfei.lzf
*/
public class ConnectionLimitRuleChangeEvent extends Event {
private boolean external;
public ConnectionLimitRuleChangeEvent(boolean external) {
this.external = external;
}
public boolean isExternal() {
return external;
}
public void setExternal(boolean external) {
this.external = external;
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright 1999-2020 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.plugin.control.event;
import com.alibaba.nacos.common.notify.Event;
/**
* tps control point.
*
* @author liuzunfei
* @version $Id: TpsControlPoint.java, v 0.1 2021年01月09日 12:38 PM liuzunfei Exp $
*/
public class TpsControlRuleChangeEvent extends Event {
private String pointName;
private boolean external;
public TpsControlRuleChangeEvent(String pointName, boolean external) {
this.pointName = pointName;
this.external = external;
}
public String getPointName() {
return pointName;
}
public void setPointName(String pointName) {
this.pointName = pointName;
}
public boolean isExternal() {
return external;
}
public void setExternal(boolean external) {
this.external = external;
}
}

View File

@ -0,0 +1,142 @@
/*
* Copyright 1999-2023 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.plugin.control.rule;
import com.alibaba.nacos.common.notify.Event;
import com.alibaba.nacos.common.notify.NotifyCenter;
import com.alibaba.nacos.common.notify.listener.Subscriber;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.plugin.control.ControlManagerCenter;
import com.alibaba.nacos.plugin.control.Loggers;
import com.alibaba.nacos.plugin.control.connection.ConnectionControlManager;
import com.alibaba.nacos.plugin.control.connection.rule.ConnectionControlRule;
import com.alibaba.nacos.plugin.control.event.ConnectionLimitRuleChangeEvent;
import com.alibaba.nacos.plugin.control.event.TpsControlRuleChangeEvent;
import com.alibaba.nacos.plugin.control.rule.storage.RuleStorageProxy;
import com.alibaba.nacos.plugin.control.tps.TpsControlManager;
import com.alibaba.nacos.plugin.control.tps.rule.TpsControlRule;
import org.slf4j.Logger;
/**
* control rule activator.
*
* @author shiyiyue
*/
public class ControlRuleChangeActivator {
private static final Logger LOGGER = Loggers.CONTROL;
TpsRuleChangeSubscriber tpsRuleChangeSubscriber = new TpsRuleChangeSubscriber();
ConnectionRuleChangeSubscriber connectionRuleChangeSubscriber = new ConnectionRuleChangeSubscriber();
public ControlRuleChangeActivator() {
NotifyCenter.registerSubscriber(tpsRuleChangeSubscriber);
NotifyCenter.registerSubscriber(connectionRuleChangeSubscriber);
}
static class TpsRuleChangeSubscriber extends Subscriber<TpsControlRuleChangeEvent> {
@Override
public void onEvent(TpsControlRuleChangeEvent event) {
String pointName = event.getPointName();
LOGGER.info("Tps control rule change event receive,pointName={}, external={} ", pointName,
event.isExternal());
if (event.getPointName() == null) {
return;
}
try {
RuleStorageProxy ruleStorageProxy = ControlManagerCenter.getInstance().getRuleStorageProxy();
if (event.isExternal()) {
if (ruleStorageProxy.getExternalStorage() != null) {
String persistTpsRule = ruleStorageProxy.getExternalStorage().getTpsRule(pointName);
ruleStorageProxy.getLocalDiskStorage().saveTpsRule(pointName, persistTpsRule);
} else {
Loggers.CONTROL.info(
"No external rule storage found,will load local disk instead,point name={}",
event.getPointName());
}
}
String tpsRuleContent = ruleStorageProxy.getLocalDiskStorage().getTpsRule(pointName);
TpsControlManager tpsControlManager = ControlManagerCenter.getInstance().getTpsControlManager();
TpsControlRule tpsControlRule = StringUtils.isBlank(tpsRuleContent) ? new TpsControlRule()
: tpsControlManager.getTpsControlRuleParser().parseRule(tpsRuleContent);
tpsControlManager.applyTpsRule(pointName, tpsControlRule);
} catch (Exception e) {
LOGGER.warn("Tps control rule apply error ,error= ", e);
}
}
@Override
public Class<? extends Event> subscribeType() {
return TpsControlRuleChangeEvent.class;
}
}
static class ConnectionRuleChangeSubscriber extends Subscriber<ConnectionLimitRuleChangeEvent> {
@Override
public void onEvent(ConnectionLimitRuleChangeEvent event) {
LOGGER.info("connection limit rule change event receive ,external:{}", event.isExternal());
try {
RuleStorageProxy ruleStorageProxy = ControlManagerCenter.getInstance().getRuleStorageProxy();
if (event.isExternal()) {
if (ruleStorageProxy.getExternalStorage() != null) {
String connectionRule = ruleStorageProxy.getExternalStorage().getConnectionRule();
ruleStorageProxy.getLocalDiskStorage().saveConnectionRule(connectionRule);
} else {
Loggers.CONTROL.info("No external rule storage found,will load local disk instead");
}
}
String limitRule = ruleStorageProxy.getLocalDiskStorage().getConnectionRule();
Loggers.CONTROL.info("start to apply connection rule content {}", limitRule);
ConnectionControlManager controlManager = ControlManagerCenter.getInstance()
.getConnectionControlManager();
ConnectionControlRule connectionControlRule =
StringUtils.isBlank(limitRule) ? new ConnectionControlRule()
: controlManager.getConnectionControlRuleParser().parseRule(limitRule);
Loggers.CONTROL.info("end to apply connection rule content ");
if (connectionControlRule != null) {
controlManager.applyConnectionLimitRule(connectionControlRule);
} else {
LOGGER.info("Parse rule is null,Ignore illegal rule :{}", limitRule);
}
} catch (Exception e) {
LOGGER.error("Fail to parse connection limit rule ,persit:{}", event.isExternal(), e);
}
}
@Override
public Class<? extends Event> subscribeType() {
return ConnectionLimitRuleChangeEvent.class;
}
}
}

View File

@ -0,0 +1,28 @@
/*
* Copyright 1999-2023 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.plugin.control.rule.parser;
import com.alibaba.nacos.plugin.control.connection.rule.ConnectionControlRule;
/**
* Connection control rule parser.
*
* @author xiweng.yy
*/
public interface ConnectionControlRuleParser extends RuleParser<ConnectionControlRule> {
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 1999-2023 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.plugin.control.rule.parser;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.plugin.control.connection.rule.ConnectionControlRule;
/**
* Nacos default connection control rule parser with json.
*
* @author xiweng.yy
*/
public class NacosConnectionControlRuleParser implements ConnectionControlRuleParser {
@Override
public ConnectionControlRule parseRule(String ruleContent) {
return StringUtils.isBlank(ruleContent) ? new ConnectionControlRule()
: JacksonUtils.toObj(ruleContent, ConnectionControlRule.class);
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 1999-2023 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.plugin.control.rule.parser;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.plugin.control.tps.rule.TpsControlRule;
/**
* Nacos default tps control rule parser with json.
*
* @author xiweng.yy
*/
public class NacosTpsControlRuleParser implements TpsControlRuleParser {
@Override
public TpsControlRule parseRule(String ruleContent) {
return StringUtils.isBlank(ruleContent) ? new TpsControlRule()
: JacksonUtils.toObj(ruleContent, TpsControlRule.class);
}
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 1999-2023 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.plugin.control.rule.parser;
/**
* parse rule content from raw string.
*
* @author shiyiyue
*/
public interface RuleParser<R> {
/**
* Parse control rule.
*
* @param ruleContent rule raw string
* @return target rule
*/
R parseRule(String ruleContent);
}

View File

@ -0,0 +1,28 @@
/*
* Copyright 1999-2023 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.plugin.control.rule.parser;
import com.alibaba.nacos.plugin.control.tps.rule.TpsControlRule;
/**
* Tps control rule parser.
*
* @author xiweng.yy
*/
public interface TpsControlRuleParser extends RuleParser<TpsControlRule> {
}

View File

@ -0,0 +1,26 @@
/*
* Copyright 1999-2023 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.plugin.control.rule.storage;
/**
* external rule storage.
*
* @author shiyiyue
*/
public interface ExternalRuleStorage extends RuleStorage {
}

View File

@ -0,0 +1,117 @@
/*
* Copyright 1999-2023 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.plugin.control.rule.storage;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.plugin.control.Loggers;
import com.alibaba.nacos.plugin.control.utils.DiskUtils;
import com.alibaba.nacos.plugin.control.utils.EnvUtils;
import org.slf4j.Logger;
import java.io.File;
import java.io.IOException;
/**
* local disk storage.
*
* @author shiyiyue
*/
public class LocalDiskRuleStorage implements RuleStorage {
LocalDiskRuleStorage() {
}
private static final Logger LOGGER = Loggers.CONTROL;
private String localRuleBaseDir = defaultBaseDir();
private File checkTpsBaseDir() {
File baseDir = new File(localRuleBaseDir, "data" + File.separator + "tps" + File.separator);
if (!baseDir.exists()) {
baseDir.mkdirs();
}
return baseDir;
}
public void setLocalRuleBaseDir(String localRruleBaseDir) {
this.localRuleBaseDir = localRruleBaseDir;
}
private static String defaultBaseDir() {
return EnvUtils.getNacosHome();
}
private File getConnectionRuleFile() {
File baseDir = new File(localRuleBaseDir, "data" + File.separator + "connection" + File.separator);
if (!baseDir.exists()) {
baseDir.mkdirs();
}
return new File(baseDir, "limitRule");
}
@Override
public String getName() {
return "localdisk";
}
@Override
public void saveConnectionRule(String ruleContent) throws IOException {
File pointFile = getConnectionRuleFile();
if (!pointFile.exists()) {
pointFile.createNewFile();
}
DiskUtils.writeFile(pointFile, ruleContent.getBytes(Constants.ENCODE), false);
LOGGER.info("Save connection rule to local, ruleContent ={} ", ruleContent);
}
@Override
public String getConnectionRule() {
File connectionRuleFile = getConnectionRuleFile();
if (!connectionRuleFile.exists()) {
return null;
}
return DiskUtils.readFile(connectionRuleFile);
}
@Override
public void saveTpsRule(String pointName, String ruleContent) throws IOException {
File file = checkTpsBaseDir();
File tpsFile = new File(file, pointName);
if (!tpsFile.exists()) {
tpsFile.createNewFile();
}
if (ruleContent == null) {
DiskUtils.deleteQuietly(tpsFile);
} else {
DiskUtils.writeFile(tpsFile, ruleContent.getBytes(Constants.ENCODE), false);
LOGGER.info("Save tps rule to local,pointName={}, ruleContent ={} ", pointName, ruleContent);
}
}
@Override
public String getTpsRule(String pointName) {
File file = checkTpsBaseDir();
File tpsFile = new File(file, pointName);
if (!tpsFile.exists()) {
return null;
}
return DiskUtils.readFile(tpsFile);
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright 1999-2023 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.plugin.control.rule.storage;
/**
* rule storage.
*
* @author shiyiyue
* @date 2022-10-26 11:43:00
*/
public interface RuleStorage {
/**
* get storage name.
*
* @return
*/
String getName();
/**
* save connection rule to storage.
*
* @param ruleContent rule content.
* @throws Exception exception.
*/
void saveConnectionRule(String ruleContent) throws Exception;
/**
* get connection rule.
*
* @return
*/
String getConnectionRule();
/**
* save tps rule.
*
* @param pointName point name.
* @param ruleContent rule content.
* @throws Exception exception.
*/
void saveTpsRule(String pointName, String ruleContent) throws Exception;
/**
* get tps rule.
*
* @param pointName point name.
* @return
*/
String getTpsRule(String pointName);
}

View File

@ -0,0 +1,93 @@
/*
* Copyright 1999-2023 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.plugin.control.rule.storage;
import com.alibaba.nacos.common.spi.NacosServiceLoader;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.plugin.control.Loggers;
import com.alibaba.nacos.plugin.control.configs.ControlConfigs;
import com.alibaba.nacos.plugin.control.rule.ControlRuleChangeActivator;
import com.alibaba.nacos.plugin.control.spi.ExternalRuleStorageBuilder;
import org.slf4j.Logger;
import java.util.Collection;
/**
* rule storage proxy.
*
* @author shiyiyue
*/
public class RuleStorageProxy {
private static final Logger LOGGER = Loggers.CONTROL;
private static final RuleStorageProxy INSTANCE = new RuleStorageProxy();
private LocalDiskRuleStorage localDiskRuleStorage = null;
private ExternalRuleStorage externalRuleStorage = null;
ControlRuleChangeActivator controlRuleChangeActivator = null;
private RuleStorageProxy() {
String externalStorageType = ControlConfigs.getInstance().getRuleExternalStorage();
if (StringUtils.isNotEmpty(externalStorageType)) {
buildExternalStorage(externalStorageType);
}
initLocalStorage();
controlRuleChangeActivator = new ControlRuleChangeActivator();
}
private void buildExternalStorage(String externalStorageType) {
Collection<ExternalRuleStorageBuilder> externalRuleStorageBuilders = NacosServiceLoader
.load(ExternalRuleStorageBuilder.class);
for (ExternalRuleStorageBuilder each : externalRuleStorageBuilders) {
LOGGER.info("Found persist rule storage of name : {}", externalStorageType);
if (externalStorageType.equalsIgnoreCase(each.getName())) {
try {
externalRuleStorage = each.buildExternalRuleStorage();
} catch (Exception e) {
LOGGER.warn("Build external rule storage failed, the rules will not be persisted", e);
}
LOGGER.info("Build external rule storage of name {} finished", externalStorageType);
break;
}
}
if (externalRuleStorage == null && StringUtils.isNotBlank(externalStorageType)) {
LOGGER.error("Fail to found persist rule storage of name : {}", externalStorageType);
}
}
private void initLocalStorage() {
localDiskRuleStorage = new LocalDiskRuleStorage();
if (StringUtils.isNotBlank(ControlConfigs.getInstance().getLocalRuleStorageBaseDir())) {
localDiskRuleStorage.setLocalRuleBaseDir(ControlConfigs.getInstance().getLocalRuleStorageBaseDir());
}
}
public RuleStorage getLocalDiskStorage() {
return localDiskRuleStorage;
}
public RuleStorage getExternalStorage() {
return externalRuleStorage;
}
public static RuleStorageProxy getInstance() {
return INSTANCE;
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright 1999-2023 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.plugin.control.spi;
import com.alibaba.nacos.plugin.control.connection.ConnectionControlManager;
import com.alibaba.nacos.plugin.control.tps.TpsControlManager;
/**
* Nacos control plugin manager builder SPI.
*
* @author xiweng.yy
*/
public interface ControlManagerBuilder {
/**
* Get plugin name.
*
* @return name of plugin
*/
String getName();
/**
* Build {@link ConnectionControlManager} implementation for current plugin.
*
* @return ConnectionControlManager implementation
*/
ConnectionControlManager buildConnectionControlManager();
/**
* Build {@link TpsControlManager} implementation for current plugin.
*
* @return TpsControlManager implementation
*/
TpsControlManager buildTpsControlManager();
}

View File

@ -0,0 +1,41 @@
/*
* Copyright 1999-2023 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.plugin.control.spi;
import com.alibaba.nacos.plugin.control.rule.storage.ExternalRuleStorage;
/**
* Nacos control plugin external rule storage builder SPI.
*
* @author xiweng.yy
*/
public interface ExternalRuleStorageBuilder {
/**
* Get plugin name.
*
* @return name of plugin
*/
String getName();
/**
* Build {@link ExternalRuleStorage} implementation for current plugin if necessary.
*
* @return ExternalRuleStorage implementation
*/
ExternalRuleStorage buildExternalRuleStorage();
}

View File

@ -0,0 +1,109 @@
/*
* Copyright 1999-2023 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.plugin.control.tps;
import com.alibaba.nacos.plugin.control.Loggers;
import com.alibaba.nacos.plugin.control.tps.barrier.TpsBarrier;
import com.alibaba.nacos.plugin.control.tps.request.TpsCheckRequest;
import com.alibaba.nacos.plugin.control.tps.response.TpsCheckResponse;
import com.alibaba.nacos.plugin.control.tps.response.TpsResultCode;
import com.alibaba.nacos.plugin.control.tps.rule.TpsControlRule;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* nacos tps control manager.
*
* @author shiyiyue
*/
public class DefaultTpsControlManager extends TpsControlManager {
/**
* point name -> tps barrier.
*/
protected final Map<String, TpsBarrier> points = new ConcurrentHashMap<>(16);
/**
* point name -> tps control rule.
*/
protected final Map<String, TpsControlRule> rules = new ConcurrentHashMap<>(16);
public DefaultTpsControlManager() {
}
/**
* apple tps rule.
*
* @param pointName pointName.
*/
public synchronized void registerTpsPoint(String pointName) {
if (!points.containsKey(pointName)) {
points.put(pointName, tpsBarrierCreator.createTpsBarrier(pointName));
if (rules.containsKey(pointName)) {
points.get(pointName).applyRule(rules.get(pointName));
} else {
initTpsRule(pointName);
}
}
Loggers.CONTROL
.warn("Tps point for {} registered, But tps control manager is no limit implementation.", pointName);
}
/**
* apple tps rule.
*
* @param pointName pointName.
* @param rule rule.
*/
public synchronized void applyTpsRule(String pointName, TpsControlRule rule) {
if (rule == null) {
rules.remove(pointName);
} else {
rules.put(pointName, rule);
}
if (points.containsKey(pointName)) {
points.get(pointName).applyRule(rule);
}
Loggers.CONTROL.warn("Tps rule for point name {} updated, But tps control manager is no limit implementation.",
pointName);
}
public Map<String, TpsBarrier> getPoints() {
return points;
}
public Map<String, TpsControlRule> getRules() {
return rules;
}
/**
* check tps result.
*
* @param tpsRequest TpsRequest.
* @return check current tps is allowed.
*/
public TpsCheckResponse check(TpsCheckRequest tpsRequest) {
return new TpsCheckResponse(true, TpsResultCode.CHECK_SKIP, "skip");
}
@Override
public String getName() {
return "noLimit";
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright 1999-2020 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.plugin.control.tps;
/**
* MonitorType.
*
* @author liuzunfei
* @version $Id: MonitorType.java, v 0.1 2021年01月12日 20:38 PM liuzunfei Exp $
*/
public enum MonitorType {
// monitor mode.
MONITOR("monitor", "only monitor ,not reject request."),
//intercept mode.
INTERCEPT("intercept", "reject request if tps over limit");
String type;
String desc;
MonitorType(String type, String desc) {
this.type = type;
this.desc = desc;
}
public String getType() {
return type;
}
}

View File

@ -0,0 +1,132 @@
/*
* Copyright 1999-2020 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.plugin.control.tps;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.plugin.control.Loggers;
import com.alibaba.nacos.plugin.control.rule.parser.NacosTpsControlRuleParser;
import com.alibaba.nacos.plugin.control.rule.parser.TpsControlRuleParser;
import com.alibaba.nacos.plugin.control.rule.storage.RuleStorageProxy;
import com.alibaba.nacos.plugin.control.tps.barrier.TpsBarrier;
import com.alibaba.nacos.plugin.control.tps.barrier.creator.DefaultNacosTpsBarrierCreator;
import com.alibaba.nacos.plugin.control.tps.barrier.creator.TpsBarrierCreator;
import com.alibaba.nacos.plugin.control.tps.request.TpsCheckRequest;
import com.alibaba.nacos.plugin.control.tps.response.TpsCheckResponse;
import com.alibaba.nacos.plugin.control.tps.rule.TpsControlRule;
import java.util.Map;
/**
* abstract tps control manager.
*
* @author shiyiyue
*/
@SuppressWarnings("PMD.AbstractClassShouldStartWithAbstractNamingRule")
public abstract class TpsControlManager {
private final TpsControlRuleParser tpsControlRuleParser;
protected final TpsBarrierCreator tpsBarrierCreator;
protected TpsControlManager() {
this.tpsControlRuleParser = buildTpsControlRuleParser();
this.tpsBarrierCreator = buildTpsBarrierCreator();
}
public TpsControlRuleParser getTpsControlRuleParser() {
return tpsControlRuleParser;
}
protected TpsControlRuleParser buildTpsControlRuleParser() {
return new NacosTpsControlRuleParser();
}
/**
* Build tps barrier creator to creator tps barrier for each point.
*
* @return TpsBarrierCreator implementation for current plugin
*/
protected TpsBarrierCreator buildTpsBarrierCreator() {
return new DefaultNacosTpsBarrierCreator();
}
protected void initTpsRule(String pointName) {
RuleStorageProxy ruleStorageProxy = RuleStorageProxy.getInstance();
String localRuleContent = ruleStorageProxy.getLocalDiskStorage().getTpsRule(pointName);
if (StringUtils.isNotBlank(localRuleContent)) {
Loggers.CONTROL.info("Found local disk tps control rule of {},content ={}", pointName, localRuleContent);
} else if (ruleStorageProxy.getExternalStorage() != null
&& ruleStorageProxy.getExternalStorage().getTpsRule(pointName) != null) {
localRuleContent = ruleStorageProxy.getExternalStorage().getTpsRule(pointName);
if (StringUtils.isNotBlank(localRuleContent)) {
Loggers.CONTROL.info("Found external tps control rule of {},content ={}", pointName, localRuleContent);
}
}
if (StringUtils.isNotBlank(localRuleContent)) {
TpsControlRule tpsLimitRule = tpsControlRuleParser.parseRule(localRuleContent);
this.applyTpsRule(pointName, tpsLimitRule);
} else {
Loggers.CONTROL.info("No tps control rule of {} found,content ={} ", pointName, localRuleContent);
}
}
/**
* apple tps rule.
*
* @param pointName pointName.
*/
public abstract void registerTpsPoint(String pointName);
/**
* get points.
*
* @return
*/
public abstract Map<String, TpsBarrier> getPoints();
/**
* get rules.
*
* @return
*/
public abstract Map<String, TpsControlRule> getRules();
/**
* apple tps rule.
*
* @param pointName pointName.
* @param rule rule.
*/
public abstract void applyTpsRule(String pointName, TpsControlRule rule);
/**
* check tps result.
*
* @param tpsRequest TpsRequest.
* @return check current tps is allowed.
*/
public abstract TpsCheckResponse check(TpsCheckRequest tpsRequest);
/**
* get control manager name.
*
* @return
*/
public abstract String getName();
}

View File

@ -0,0 +1,141 @@
/*
* Copyright 1999-2020 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.plugin.control.tps;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* tps metrics.
*
* @author shiyiyue
*/
public class TpsMetrics {
private String pointName;
private String type;
private long timeStamp;
private TimeUnit period;
private Counter counter;
public TpsMetrics(String pointName, String type, long timeStamp, TimeUnit period) {
this.pointName = pointName;
this.type = type;
this.timeStamp = timeStamp;
this.period = period;
}
@Override
public String toString() {
return "TpsMetrics{" + "pointName='" + pointName + '\'' + ", type='" + type + '\'' + ", timeStamp=" + timeStamp
+ ", period=" + period + ", counter=" + counter + '}';
}
public String getTimeFormatOfSecond(long timeStamp) {
String format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(timeStamp));
return format;
}
public String getMsg() {
return String.join("|", pointName, type, period.name(), getTimeFormatOfSecond(timeStamp),
String.valueOf(counter.passCount), String.valueOf(counter.deniedCount));
}
public String getPointName() {
return pointName;
}
public void setPointName(String pointName) {
this.pointName = pointName;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public long getTimeStamp() {
return timeStamp;
}
public void setTimeStamp(long timeStamp) {
this.timeStamp = timeStamp;
}
public TimeUnit getPeriod() {
return period;
}
public void setPeriod(TimeUnit period) {
this.period = period;
}
public Counter getCounter() {
return counter;
}
public void setCounter(Counter counter) {
this.counter = counter;
}
public static class Counter {
private long passCount;
private long deniedCount;
public Counter(long passCount, long deniedCount) {
this.passCount = passCount;
this.deniedCount = deniedCount;
}
public long getPassCount() {
return passCount;
}
public void setPassCount(long passCount) {
this.passCount = passCount;
}
public long getDeniedCount() {
return deniedCount;
}
public void setDeniedCount(long deniedCount) {
this.deniedCount = deniedCount;
}
@Override
public String toString() {
return "{" + "passCount=" + passCount + ", deniedCount=" + deniedCount + '}';
}
public String getSimpleLog() {
return String.join("|", String.valueOf(passCount), String.valueOf(deniedCount));
}
}
}

View File

@ -0,0 +1,79 @@
/*
* Copyright 1999-2023 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.plugin.control.tps.barrier;
import com.alibaba.nacos.plugin.control.Loggers;
import com.alibaba.nacos.plugin.control.tps.request.BarrierCheckRequest;
import com.alibaba.nacos.plugin.control.tps.request.TpsCheckRequest;
import com.alibaba.nacos.plugin.control.tps.response.TpsCheckResponse;
import com.alibaba.nacos.plugin.control.tps.rule.RuleDetail;
import com.alibaba.nacos.plugin.control.tps.rule.TpsControlRule;
/**
* tps barrier for tps point.
*
* @author shiyiyue
*/
public class DefaultNacosTpsBarrier extends TpsBarrier {
public DefaultNacosTpsBarrier(String pointName) {
super(pointName);
}
/**
* apply tps.
*
* @param tpsCheckRequest tpsCheckRequest.
* @return check current tps is allowed.
*/
public TpsCheckResponse applyTps(TpsCheckRequest tpsCheckRequest) {
BarrierCheckRequest pointCheckRequest = new BarrierCheckRequest();
pointCheckRequest.setCount(tpsCheckRequest.getCount());
pointCheckRequest.setPointName(super.getPointName());
pointCheckRequest.setTimestamp(tpsCheckRequest.getTimestamp());
return super.getPointBarrier().applyTps(pointCheckRequest);
}
/**
* apply rule.
*
* @param newControlRule newControlRule.
*/
public synchronized void applyRule(TpsControlRule newControlRule) {
Loggers.CONTROL.info("Apply tps control rule start,pointName=[{}] ", this.getPointName());
//1.reset all monitor point for null.
if (newControlRule == null || newControlRule.getPointRule() == null) {
Loggers.CONTROL.info("Clear all tps control rule ,pointName=[{}] ", this.getPointName());
super.getPointBarrier().clearLimitRule();
return;
}
//2.check point rule.
RuleDetail newPointRule = newControlRule.getPointRule();
Loggers.CONTROL.info("Update point control rule ,pointName=[{}],original maxTps={}, new maxTps={}"
+ ",original monitorType={}, original monitorType={}, ", this.getPointName(),
this.pointBarrier.getMaxCount(), newPointRule.getMaxCount(), this.pointBarrier.getMonitorType(),
newPointRule.getMonitorType());
this.pointBarrier.applyRuleDetail(newPointRule);
Loggers.CONTROL.info("Apply tps control rule end,pointName=[{}] ", this.getPointName());
}
}

View File

@ -0,0 +1,155 @@
/*
* Copyright 1999-2023 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.plugin.control.tps.barrier;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
/**
* local simple count rate counter.
*
* @author shiyiyue
*/
public class LocalSimpleCountRateCounter extends RateCounter {
private static final int DEFAULT_RECORD_SIZE = 10;
long startTime = System.currentTimeMillis();
private List<TpsSlot> slotList;
public LocalSimpleCountRateCounter(String name, TimeUnit period) {
super(name, period);
slotList = new ArrayList<>(DEFAULT_RECORD_SIZE);
for (int i = 0; i < DEFAULT_RECORD_SIZE; i++) {
slotList.add(new TpsSlot());
}
long now = System.currentTimeMillis();
if (period == TimeUnit.SECONDS) {
startTime = RateCounter.getTrimMillsOfSecond(now);
} else if (period == TimeUnit.MINUTES) {
startTime = RateCounter.getTrimMillsOfMinute(now);
} else if (period == TimeUnit.HOURS) {
startTime = RateCounter.getTrimMillsOfHour(now);
} else {
//second default
startTime = RateCounter.getTrimMillsOfSecond(now);
}
}
@Override
public long add(long timestamp, long count) {
return createSlotIfAbsent(timestamp).countHolder.count.addAndGet(count);
}
@Override
public boolean tryAdd(long timestamp, long countDelta, long upperLimit) {
if (createSlotIfAbsent(timestamp).countHolder.count.addAndGet(countDelta) <= upperLimit) {
return true;
} else {
createSlotIfAbsent(timestamp).countHolder.interceptedCount.addAndGet(countDelta);
return false;
}
}
public void minus(long timestamp, long count) {
AtomicLong currentCount = createSlotIfAbsent(timestamp).countHolder.count;
currentCount.addAndGet(count * -1);
}
public long getCount(long timestamp) {
TpsSlot point = getPoint(timestamp);
return point == null ? 0L : point.countHolder.count.longValue();
}
/**
* get slot of the timestamp second,read only ,return nul if not exist.
*
* @param timeStamp the timestamp second.
* @return tps slot.
*/
private TpsSlot getPoint(long timeStamp) {
long distance = timeStamp - startTime;
long diff = (distance < 0 ? distance + getPeriod().toMillis(1) * DEFAULT_RECORD_SIZE : distance) / getPeriod()
.toMillis(1);
long currentWindowTime = startTime + diff * getPeriod().toMillis(1);
int index = (int) diff % DEFAULT_RECORD_SIZE;
TpsSlot tpsSlot = slotList.get(index);
if (tpsSlot.time != currentWindowTime) {
return null;
}
return tpsSlot;
}
/**
* get slot of the timestamp second,create if not exist.
*
* @param timeStamp the timestamp second.
* @return tps slot.
*/
public TpsSlot createSlotIfAbsent(long timeStamp) {
long distance = timeStamp - startTime;
long diff = (distance < 0 ? distance + getPeriod().toMillis(1) * DEFAULT_RECORD_SIZE : distance) / getPeriod()
.toMillis(1);
long currentWindowTime = startTime + diff * getPeriod().toMillis(1);
int index = (int) diff % DEFAULT_RECORD_SIZE;
TpsSlot tpsSlot = slotList.get(index);
if (tpsSlot.time != currentWindowTime) {
tpsSlot.reset(currentWindowTime);
}
return slotList.get(index);
}
static class TpsSlot {
long time = 0L;
private SlotCountHolder countHolder = new SlotCountHolder();
public void reset(long second) {
synchronized (this) {
if (this.time != second) {
this.time = second;
countHolder.count.set(0L);
countHolder.interceptedCount.set(0);
}
}
}
@Override
public String toString() {
return "TpsSlot{" + "time=" + time + ", countHolder=" + countHolder + '}';
}
}
static class SlotCountHolder {
AtomicLong count = new AtomicLong();
AtomicLong interceptedCount = new AtomicLong();
@Override
public String toString() {
return "{" + count + "|" + interceptedCount + '}';
}
}
}

View File

@ -0,0 +1,40 @@
/*
* Copyright 1999-2023 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.plugin.control.tps.barrier;
import java.util.concurrent.TimeUnit;
/**
* local simple count rule barrier.
*
* @author shiyiyue
*/
public class LocalSimpleCountRuleBarrier extends SimpleCountRuleBarrier {
public LocalSimpleCountRuleBarrier(String pointName, String ruleName, TimeUnit period) {
super(pointName, ruleName, period);
}
public RateCounter createSimpleCounter(String name, TimeUnit period) {
return new LocalSimpleCountRateCounter(name, period);
}
@Override
public String getBarrierName() {
return "localsimplecount";
}
}

View File

@ -0,0 +1,114 @@
/*
* Copyright 1999-2023 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.plugin.control.tps.barrier;
import java.util.concurrent.TimeUnit;
/**
* abstract rate counter.
*
* @author zunfei.lzf
*/
@SuppressWarnings("PMD.AbstractClassShouldStartWithAbstractNamingRule")
public abstract class RateCounter {
/**
* rate count name.
*/
private String name;
/**
* rate period.
*/
private TimeUnit period;
public RateCounter(String name, TimeUnit period) {
this.name = name;
this.period = period;
}
public TimeUnit getPeriod() {
return period;
}
/**
* add count for the second of timestamp.
*
* @param timestamp timestamp.
* @param count count.
* @return
*/
public abstract long add(long timestamp, long count);
/**
* add intercepted count for the second of timestamp.
*
* @param timestamp timestamp
* @param countDelta count
* @param upperLimit upperLimit
* @return
*/
public abstract boolean tryAdd(long timestamp, long countDelta, long upperLimit);
/**
* get count of the second of timestamp.
*
* @param timestamp timestamp.
* @return
*/
public abstract long getCount(long timestamp);
public String getName() {
return name;
}
/**
* get trim mills of second.
*
* @param timeStamp timestamp milliseconds.
* @return
*/
public static long getTrimMillsOfMinute(long timeStamp) {
String millString = String.valueOf(timeStamp);
String substring = millString.substring(0, millString.length() - 3);
return Long.valueOf(Long.valueOf(substring) / 60 * 60 + "000");
}
/**
* get trim mills of second.
*
* @param timeStamp timestamp milliseconds.
* @return
*/
public static long getTrimMillsOfSecond(long timeStamp) {
String millString = String.valueOf(timeStamp);
String substring = millString.substring(0, millString.length() - 3);
return Long.valueOf(substring + "000");
}
/**
* get trim mills of second.
*
* @param timeStamp timestamp milliseconds.
* @return
*/
public static long getTrimMillsOfHour(long timeStamp) {
String millString = String.valueOf(timeStamp);
String substring = millString.substring(0, millString.length() - 3);
return Long.valueOf(Long.valueOf(substring) / (60 * 60) * (60 * 60) + "000");
}
}

View File

@ -0,0 +1,140 @@
/*
* Copyright 1999-2023 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.plugin.control.tps.barrier;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.plugin.control.tps.MonitorType;
import com.alibaba.nacos.plugin.control.tps.TpsMetrics;
import com.alibaba.nacos.plugin.control.tps.request.BarrierCheckRequest;
import com.alibaba.nacos.plugin.control.tps.response.TpsCheckResponse;
import com.alibaba.nacos.plugin.control.tps.rule.RuleDetail;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* rule barrier.
*
* @author shiyiyue
*/
@SuppressWarnings("PMD.AbstractClassShouldStartWithAbstractNamingRule")
public abstract class RuleBarrier {
private TimeUnit period;
private String pointName;
private long maxCount;
private String ruleName;
/**
* monitor/intercept.
*/
private String monitorType = MonitorType.MONITOR.getType();
public String getRuleName() {
return ruleName;
}
public void setRuleName(String ruleName) {
this.ruleName = ruleName;
}
public String getPointName() {
return pointName;
}
public void setPointName(String pointName) {
this.pointName = pointName;
}
public TimeUnit getPeriod() {
return period;
}
public void setPeriod(TimeUnit period) {
this.period = period;
}
/**
* get barrier name.
*
* @return
*/
public abstract String getBarrierName();
public long getMaxCount() {
return maxCount;
}
public void setMaxCount(long maxCount) {
this.maxCount = maxCount;
}
public String getMonitorType() {
return monitorType;
}
public void setMonitorType(String monitorType) {
this.monitorType = monitorType;
}
public boolean isMonitorType() {
return MonitorType.MONITOR.getType().equalsIgnoreCase(this.monitorType);
}
public String getLimitMsg() {
Map<String, String> limitMsg = new HashMap<>(3);
limitMsg.put("deniedType", "point");
limitMsg.put("period", period.toString());
limitMsg.put("limitCount", String.valueOf(maxCount));
return JacksonUtils.toJson(limitMsg);
}
/**
* apply tps.
*
* @param barrierCheckRequest barrierCheckRequest.
* @return
*/
public abstract TpsCheckResponse applyTps(BarrierCheckRequest barrierCheckRequest);
/**
* apply rule detail.
*
* @param ruleDetail ruleDetail.
*/
public abstract void applyRuleDetail(RuleDetail ruleDetail);
/**
* get metrics.
*
* @param timeStamp timeStamp.
* @return
*/
public abstract TpsMetrics getMetrics(long timeStamp);
/**
* clear limit rule.
*/
public void clearLimitRule() {
this.maxCount = -1;
this.monitorType = MonitorType.MONITOR.getType();
}
}

View File

@ -0,0 +1,117 @@
/*
* Copyright 1999-2023 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.plugin.control.tps.barrier;
import com.alibaba.nacos.plugin.control.tps.MonitorType;
import com.alibaba.nacos.plugin.control.tps.TpsMetrics;
import com.alibaba.nacos.plugin.control.tps.request.BarrierCheckRequest;
import com.alibaba.nacos.plugin.control.tps.response.TpsCheckResponse;
import com.alibaba.nacos.plugin.control.tps.response.TpsResultCode;
import com.alibaba.nacos.plugin.control.tps.rule.RuleDetail;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* simple count rule barrier.
*
* @author shiyiyue
*/
@SuppressWarnings("PMD.AbstractClassShouldStartWithAbstractNamingRule")
public abstract class SimpleCountRuleBarrier extends RuleBarrier {
RateCounter rateCounter;
public SimpleCountRuleBarrier(String pointName, String ruleName, TimeUnit period) {
super.setPointName(pointName);
super.setPeriod(period);
super.setRuleName(ruleName);
this.rateCounter = createSimpleCounter(ruleName, period);
}
/**
* create rate count.
*
* @param name name.
* @param period period.
* @return
*/
public abstract RateCounter createSimpleCounter(String name, TimeUnit period);
public void reCreateRaterCounter(String name, TimeUnit period) {
this.rateCounter = createSimpleCounter(name, period);
}
@Override
public TpsCheckResponse applyTps(BarrierCheckRequest barrierCheckRequest) {
if (MonitorType.INTERCEPT.getType().equals(getMonitorType())) {
long maxCount = getMaxCount();
boolean accepted = rateCounter.tryAdd(barrierCheckRequest.getTimestamp(), barrierCheckRequest.getCount(), maxCount);
return accepted ? new TpsCheckResponse(true, TpsResultCode.PASS_BY_POINT, "success") :
new TpsCheckResponse(false, TpsResultCode.DENY_BY_POINT, "tps over limit :" + maxCount);
} else {
rateCounter.add(barrierCheckRequest.getTimestamp(), barrierCheckRequest.getCount());
return new TpsCheckResponse(true, TpsResultCode.PASS_BY_POINT, "success");
}
}
long trimTimeStamp(long timeStamp) {
if (this.getPeriod() == TimeUnit.SECONDS) {
timeStamp = RateCounter.getTrimMillsOfSecond(timeStamp);
} else if (this.getPeriod() == TimeUnit.MINUTES) {
timeStamp = RateCounter.getTrimMillsOfMinute(timeStamp);
} else if (this.getPeriod() == TimeUnit.HOURS) {
timeStamp = RateCounter.getTrimMillsOfHour(timeStamp);
} else {
//second default
timeStamp = RateCounter.getTrimMillsOfSecond(timeStamp);
}
return timeStamp;
}
@Override
public TpsMetrics getMetrics(long timeStamp) {
timeStamp = trimTimeStamp(timeStamp);
TpsMetrics tpsMetrics = new TpsMetrics("", "", timeStamp, super.getPeriod());
long totalPass = rateCounter.getCount(timeStamp);
if (totalPass <= 0) {
return null;
}
tpsMetrics.setCounter(new TpsMetrics.Counter(totalPass, 0));
return tpsMetrics;
}
/**
* apply rule detail.
*
* @param ruleDetail ruleDetail.
*/
public void applyRuleDetail(RuleDetail ruleDetail) {
if (!Objects.equals(this.getPeriod(), ruleDetail.getPeriod())) {
this.setMaxCount(ruleDetail.getMaxCount());
this.setMonitorType(ruleDetail.getMonitorType());
this.setPeriod(ruleDetail.getPeriod());
reCreateRaterCounter(ruleDetail.getRuleName(), this.getPeriod());
} else {
this.setMaxCount(ruleDetail.getMaxCount());
this.setMonitorType(ruleDetail.getMonitorType());
}
}
}

View File

@ -0,0 +1,69 @@
/*
* Copyright 1999-2023 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.plugin.control.tps.barrier;
import com.alibaba.nacos.plugin.control.tps.barrier.creator.RuleBarrierCreator;
import com.alibaba.nacos.plugin.control.tps.barrier.creator.LocalSimpleCountBarrierCreator;
import com.alibaba.nacos.plugin.control.tps.request.TpsCheckRequest;
import com.alibaba.nacos.plugin.control.tps.response.TpsCheckResponse;
import com.alibaba.nacos.plugin.control.tps.rule.TpsControlRule;
import java.util.concurrent.TimeUnit;
/**
* tps barrier for tps point.
*
* @author shiyiyue
*/
@SuppressWarnings("PMD.AbstractClassShouldStartWithAbstractNamingRule")
public abstract class TpsBarrier {
protected RuleBarrierCreator ruleBarrierCreator;
protected String pointName;
protected RuleBarrier pointBarrier;
public TpsBarrier(String pointName) {
this.pointName = pointName;
this.ruleBarrierCreator = new LocalSimpleCountBarrierCreator();
this.pointBarrier = ruleBarrierCreator.createRuleBarrier(pointName, pointName, TimeUnit.SECONDS);
}
/**
* apply tps.
*
* @param tpsCheckRequest tpsCheckRequest.
* @return check current tps is allowed.
*/
public abstract TpsCheckResponse applyTps(TpsCheckRequest tpsCheckRequest);
public RuleBarrier getPointBarrier() {
return pointBarrier;
}
public String getPointName() {
return pointName;
}
/**
* apply rule.
*
* @param newControlRule newControlRule.
*/
public abstract void applyRule(TpsControlRule newControlRule);
}

View File

@ -0,0 +1,38 @@
/*
* Copyright 1999-2023 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.plugin.control.tps.barrier.creator;
import com.alibaba.nacos.plugin.control.tps.barrier.TpsBarrier;
import com.alibaba.nacos.plugin.control.tps.barrier.DefaultNacosTpsBarrier;
/**
* default nacos tps barrier creator.
*
* @author shiyiyue
*/
public class DefaultNacosTpsBarrierCreator implements TpsBarrierCreator {
@Override
public String getName() {
return "nacos";
}
@Override
public TpsBarrier createTpsBarrier(String pointName) {
return new DefaultNacosTpsBarrier(pointName);
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright 1999-2023 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.plugin.control.tps.barrier.creator;
import com.alibaba.nacos.plugin.control.tps.barrier.RuleBarrier;
import com.alibaba.nacos.plugin.control.tps.barrier.LocalSimpleCountRuleBarrier;
import java.util.concurrent.TimeUnit;
/**
* local simple count barrier creator.
*
* @author shiyiyue
*/
public class LocalSimpleCountBarrierCreator implements RuleBarrierCreator {
private static final LocalSimpleCountBarrierCreator INSTANCE = new LocalSimpleCountBarrierCreator();
public LocalSimpleCountBarrierCreator() {
}
public static final LocalSimpleCountBarrierCreator getInstance() {
return INSTANCE;
}
@Override
public RuleBarrier createRuleBarrier(String pointName, String ruleName, TimeUnit period) {
return new LocalSimpleCountRuleBarrier(pointName, ruleName, period);
}
@Override
public String name() {
return "localsimplecountor";
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright 1999-2023 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.plugin.control.tps.barrier.creator;
import com.alibaba.nacos.plugin.control.tps.barrier.RuleBarrier;
import java.util.concurrent.TimeUnit;
/**
* rule barrier creator.
*
* @author shiyiyue
*/
public interface RuleBarrierCreator {
/**
* create a count for time unit period.
*
* @param pointName pointName.
* @param ruleName ruleName.
* @param period period.
* @return
*/
RuleBarrier createRuleBarrier(String pointName, String ruleName, TimeUnit period);
/**
* rate count creator name.
*
* @return name.
*/
String name();
}

View File

@ -0,0 +1,42 @@
/*
* Copyright 1999-2023 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.plugin.control.tps.barrier.creator;
import com.alibaba.nacos.plugin.control.tps.barrier.TpsBarrier;
/**
* tps barrier creator.
*
* @author shiyiyue
*/
public interface TpsBarrierCreator {
/**
* get name.
*
* @return
*/
String getName();
/**
* create tps barrier.
*
* @param pointName pointName.
* @return
*/
TpsBarrier createTpsBarrier(String pointName);
}

View File

@ -0,0 +1,56 @@
/*
* Copyright 1999-2020 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.plugin.control.tps.request;
/**
* barrier check request.
*
* @author shiyiyue
*/
public class BarrierCheckRequest {
private String pointName;
private long timestamp = System.currentTimeMillis();
private long count = 1;
public String getPointName() {
return pointName;
}
public void setPointName(String pointName) {
this.pointName = pointName;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public long getCount() {
return count;
}
public void setCount(long count) {
this.count = count;
}
}

View File

@ -0,0 +1,86 @@
/*
* Copyright 1999-2020 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.plugin.control.tps.request;
/**
* tps request.
*
* @author shiyiyue
*/
public class TpsCheckRequest {
private String pointName;
private long timestamp = System.currentTimeMillis();
private String connectionId;
private String clientIp;
private long count = 1;
public TpsCheckRequest() {
}
public TpsCheckRequest(String pointName, String connectionId, String clientIp) {
this.connectionId = connectionId;
this.clientIp = clientIp;
this.pointName = pointName;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public String getConnectionId() {
return connectionId;
}
public long getCount() {
return count;
}
public void setCount(long count) {
this.count = count;
}
public void setConnectionId(String connectionId) {
this.connectionId = connectionId;
}
public String getClientIp() {
return clientIp;
}
public void setClientIp(String clientIp) {
this.clientIp = clientIp;
}
public String getPointName() {
return pointName;
}
public void setPointName(String pointName) {
this.pointName = pointName;
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright 1999-2020 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.plugin.control.tps.response;
/**
* tps response.
* @author shiyiyue
*/
public class TpsCheckResponse {
private boolean success;
private int code;
private String message;
public TpsCheckResponse(boolean success, int code, String message) {
this.success = success;
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public void setSuccess(boolean success) {
this.success = success;
}
public void setMessage(String message) {
this.message = message;
}
public boolean isSuccess() {
return success;
}
public String getMessage() {
return message;
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright 1999-2020 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.plugin.control.tps.response;
/**
* tps result code.
*
* @author shiyiyue
*/
public class TpsResultCode {
public static final int PASS_BY_POINT = 200;
/**
* rule denied,but pass by monitor.
*/
public static final int PASS_BY_MONITOR = 201;
/**
* deny by point rule.
*/
public static final int DENY_BY_POINT = 300;
/**
* skip.
*/
public static final int CHECK_SKIP = 100;
}

View File

@ -0,0 +1,79 @@
/*
* Copyright 1999-2020 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.plugin.control.tps.rule;
import java.util.concurrent.TimeUnit;
/**
* rule detail.
*
* @author shiyiyue
*/
public class RuleDetail {
String ruleName;
long maxCount = -1;
TimeUnit period = TimeUnit.SECONDS;
/**
* monitor/intercept.
*/
String monitorType = "";
public RuleDetail() {
}
public String getRuleName() {
return ruleName;
}
public void setRuleName(String ruleName) {
this.ruleName = ruleName;
}
public TimeUnit getPeriod() {
return period;
}
public void setPeriod(TimeUnit period) {
this.period = period;
}
public long getMaxCount() {
return maxCount;
}
public void setMaxCount(long maxCount) {
this.maxCount = maxCount;
}
public String getMonitorType() {
return monitorType;
}
public void setMonitorType(String monitorType) {
this.monitorType = monitorType;
}
@Override
public String toString() {
return "Rule{" + "maxTps=" + maxCount + ", monitorType='" + monitorType + '\'' + '}';
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright 1999-2020 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.plugin.control.tps.rule;
/**
* rule model.
*
* @author shiyiyue
*/
public enum RuleModel {
/**
* every single monitor key will be counted as one counter.
*/
FUZZY("FUZZY", "every single monitor key will be counted as one counter"),
/**
* every single monitor key will be counted as different counter.
*/
PROTO("PROTO", "every single monitor key will be counted as different counter");
private String model;
private String desc;
RuleModel(String model, String desc) {
this.model = model;
this.desc = desc;
}
}

View File

@ -0,0 +1,51 @@
/*
* Copyright 1999-2020 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.plugin.control.tps.rule;
/**
* tps control point.
*
* @author liuzunfei
* @version $Id: TpsControlPoint.java, v 0.1 2021年01月09日 12:38 PM liuzunfei Exp $
*/
public class TpsControlRule {
private String pointName;
private RuleDetail pointRule;
public String getPointName() {
return pointName;
}
public void setPointName(String pointName) {
this.pointName = pointName;
}
public RuleDetail getPointRule() {
return pointRule;
}
public void setPointRule(RuleDetail pointRule) {
this.pointRule = pointRule;
}
@Override
public String toString() {
return "TpsControlRule{" + "pointName='" + pointName + '\'' + ", pointRule=" + pointRule + "}'";
}
}

View File

@ -0,0 +1,556 @@
/*
* Copyright 1999-2023 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.plugin.control.utils;
import com.alibaba.nacos.common.utils.ByteUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.NullOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.zip.CheckedInputStream;
import java.util.zip.CheckedOutputStream;
import java.util.zip.Checksum;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
/**
* IO operates on the utility class.
*
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
*/
public final class DiskUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(DiskUtils.class);
private static final String NO_SPACE_CN = "设备上没有空间";
private static final String NO_SPACE_EN = "No space left on device";
private static final String DISK_QUOTA_CN = "超出磁盘限额";
private static final String DISK_QUOTA_EN = "Disk quota exceeded";
private static final Charset CHARSET = StandardCharsets.UTF_8;
private static final CharsetDecoder DECODER = CHARSET.newDecoder();
public static void touch(String path, String fileName) throws IOException {
FileUtils.touch(Paths.get(path, fileName).toFile());
}
/**
* Implements the same behaviour as the "touch" utility on Unix. It creates a new file with size 0 or, if the file
* exists already, it is opened and closed without modifying it, but updating the file date and time.
*
* <p>NOTE: As from v1.3, this method throws an IOException if the last
* modified date of the file cannot be set. Also, as from v1.3 this method creates parent directories if they do not
* exist.
*
* @param file the File to touch
* @throws IOException If an I/O problem occurs
*/
public static void touch(File file) throws IOException {
FileUtils.touch(file);
}
/**
* Creates a new empty file in the specified directory, using the given prefix and suffix strings to generate its
* name. The resulting {@code Path} is associated with the same {@code FileSystem} as the given directory.
*
* <p>The details as to how the name of the file is constructed is
* implementation dependent and therefore not specified. Where possible the {@code prefix} and {@code suffix} are
* used to construct candidate names in the same manner as the {@link File#createTempFile(String, String,
* File)} method.
*
* @param dir the path to directory in which to create the file
* @param prefix the prefix string to be used in generating the file's name; may be {@code null}
* @param suffix the suffix string to be used in generating the file's name; may be {@code null}, in which case
* "{@code .tmp}" is used
* @return the path to the newly created file that did not exist before this method was invoked
* @throws IllegalArgumentException if the prefix or suffix parameters cannot be used to generate a candidate
* file name
* @throws UnsupportedOperationException if the array contains an attribute that cannot be set atomically when
* creating the directory
* @throws IOException if an I/O error occurs or {@code dir} does not exist
* @throws SecurityException In the case of the default provider, and a security manager is installed,
* the {@link SecurityManager#checkWrite(String) checkWrite} method is invoked
* to check write access to the file.
*/
public static File createTmpFile(String dir, String prefix, String suffix) throws IOException {
return Files.createTempFile(Paths.get(dir), prefix, suffix).toFile();
}
/**
* Creates an empty file in the default temporary-file directory, using the given prefix and suffix to generate its
* name. The resulting {@code Path} is associated with the default {@code FileSystem}.
*
* @param prefix the prefix string to be used in generating the file's name; may be {@code null}
* @param suffix the suffix string to be used in generating the file's name; may be {@code null}, in which case
* "{@code .tmp}" is used
* @return the path to the newly created file that did not exist before this method was invoked
* @throws IllegalArgumentException if the prefix or suffix parameters cannot be used to generate a candidate
* file name
* @throws UnsupportedOperationException if the array contains an attribute that cannot be set atomically when
* creating the directory
* @throws IOException if an I/O error occurs or the temporary-file directory does not exist
* @throws SecurityException In the case of the default provider, and a security manager is installed,
* the {@link SecurityManager#checkWrite(String) checkWrite} method is invoked
* to check write access to the file.
*/
public static File createTmpFile(String prefix, String suffix) throws IOException {
return Files.createTempFile(prefix, suffix).toFile();
}
/**
* read file which under the path.
*
* @param path directory
* @param fileName filename
* @return content
*/
public static String readFile(String path, String fileName) {
File file = openFile(path, fileName);
if (file.exists()) {
return readFile(file);
}
return null;
}
/**
* read file content by {@link InputStream}.
*
* @param is {@link InputStream}
* @return content
*/
public static String readFile(InputStream is) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
StringBuilder textBuilder = new StringBuilder();
String lineTxt = null;
while ((lineTxt = reader.readLine()) != null) {
textBuilder.append(lineTxt);
}
return textBuilder.toString();
} catch (IOException e) {
return null;
}
}
/**
* read this file content.
*
* @param file {@link File}
* @return content
*/
public static String readFile(File file) {
try (FileChannel fileChannel = new FileInputStream(file).getChannel()) {
StringBuilder text = new StringBuilder();
ByteBuffer buffer = ByteBuffer.allocate(4096);
CharBuffer charBuffer = CharBuffer.allocate(4096);
while (fileChannel.read(buffer) != -1) {
buffer.flip();
DECODER.decode(buffer, charBuffer, false);
charBuffer.flip();
while (charBuffer.hasRemaining()) {
text.append(charBuffer.get());
}
buffer.clear();
charBuffer.clear();
}
return text.toString();
} catch (IOException e) {
return null;
}
}
/**
* read this file content then return bytes.
*
* @param file {@link File}
* @return content bytes
*/
public static byte[] readFileBytes(File file) {
if (file.exists()) {
String result = readFile(file);
if (result != null) {
return ByteUtils.toBytes(result);
}
}
return null;
}
public static byte[] readFileBytes(String path, String fileName) {
File file = openFile(path, fileName);
return readFileBytes(file);
}
/**
* Writes the contents to the target file.
*
* @param file target file
* @param content content
* @param append write append mode
* @return write success
*/
public static boolean writeFile(File file, byte[] content, boolean append) {
try (FileChannel fileChannel = new FileOutputStream(file, append).getChannel()) {
ByteBuffer buffer = ByteBuffer.wrap(content);
fileChannel.write(buffer);
return true;
} catch (IOException ioe) {
if (ioe.getMessage() != null) {
String errMsg = ioe.getMessage();
if (NO_SPACE_CN.equals(errMsg) || NO_SPACE_EN.equals(errMsg) || errMsg.contains(DISK_QUOTA_CN) || errMsg
.contains(DISK_QUOTA_EN)) {
LOGGER.warn("磁盘满,自杀退出");
System.exit(0);
}
}
}
return false;
}
public static void deleteQuietly(File file) {
Objects.requireNonNull(file, "file");
FileUtils.deleteQuietly(file);
}
public static void deleteQuietly(Path path) {
Objects.requireNonNull(path, "path");
FileUtils.deleteQuietly(path.toFile());
}
/**
* delete target file.
*
* @param path directory
* @param fileName filename
* @return delete success
*/
public static boolean deleteFile(String path, String fileName) {
File file = Paths.get(path, fileName).toFile();
if (file.exists()) {
return file.delete();
}
return false;
}
public static void deleteDirectory(String path) throws IOException {
FileUtils.deleteDirectory(new File(path));
}
public static void forceMkdir(String path) throws IOException {
FileUtils.forceMkdir(new File(path));
}
public static void forceMkdir(File file) throws IOException {
FileUtils.forceMkdir(file);
}
public static void deleteDirThenMkdir(String path) throws IOException {
deleteDirectory(path);
forceMkdir(path);
}
public static void copyDirectory(File srcDir, File destDir) throws IOException {
FileUtils.copyDirectory(srcDir, destDir);
}
public static void copyFile(File src, File target) throws IOException {
FileUtils.copyFile(src, target);
}
public static File openFile(String path, String fileName) {
return openFile(path, fileName, false);
}
/**
* open file.
*
* @param path directory
* @param fileName filename
* @param rewrite if rewrite is true, will delete old file and create new one
* @return {@link File}
*/
public static File openFile(String path, String fileName, boolean rewrite) {
File directory = new File(path);
boolean mkdirs = true;
if (!directory.exists()) {
mkdirs = directory.mkdirs();
}
if (!mkdirs) {
LOGGER.error("[DiskUtils] can't create directory");
return null;
}
File file = new File(path, fileName);
try {
boolean create = true;
if (!file.exists()) {
file.createNewFile();
}
if (file.exists()) {
if (rewrite) {
file.delete();
} else {
create = false;
}
}
if (create) {
file.createNewFile();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return file;
}
// copy from sofa-jraft
/**
* Compress a folder in a directory.
*
* @param rootDir directory
* @param sourceDir folder
* @param outputFile output file
* @param checksum checksum
* @throws IOException IOException
*/
public static void compress(final String rootDir, final String sourceDir, final String outputFile,
final Checksum checksum) throws IOException {
try (final FileOutputStream fos = new FileOutputStream(outputFile);
final CheckedOutputStream cos = new CheckedOutputStream(fos, checksum);
final ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(cos))) {
compressDirectoryToZipFile(rootDir, sourceDir, zos);
zos.flush();
fos.getFD().sync();
}
}
// copy from sofa-jraft
private static void compressDirectoryToZipFile(final String rootDir, final String sourceDir,
final ZipOutputStream zos) throws IOException {
final String dir = Paths.get(rootDir, sourceDir).toString();
final File[] files = Objects.requireNonNull(new File(dir).listFiles(), "files");
for (final File file : files) {
final String child = Paths.get(sourceDir, file.getName()).toString();
if (file.isDirectory()) {
compressDirectoryToZipFile(rootDir, child, zos);
} else {
try (final FileInputStream fis = new FileInputStream(file);
final BufferedInputStream bis = new BufferedInputStream(fis)) {
compressIntoZipFile(child, bis, zos);
}
}
}
}
/**
* Compress an input stream to zip file.
*
* @param childName child name in zip file
* @param inputStream input stream needed compress
* @param outputFile output file
* @param checksum check sum
* @throws IOException IOException during compress
*/
public static void compressIntoZipFile(final String childName, final InputStream inputStream,
final String outputFile, final Checksum checksum) throws IOException {
try (final FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
final CheckedOutputStream checkedOutputStream = new CheckedOutputStream(fileOutputStream, checksum);
final ZipOutputStream zipStream = new ZipOutputStream(new BufferedOutputStream(checkedOutputStream))) {
compressIntoZipFile(childName, inputStream, zipStream);
zipStream.flush();
fileOutputStream.getFD().sync();
}
}
private static void compressIntoZipFile(final String childName, final InputStream inputStream,
final ZipOutputStream zipOutputStream) throws IOException {
zipOutputStream.putNextEntry(new ZipEntry(childName));
IOUtils.copy(inputStream, zipOutputStream);
}
// copy from sofa-jraft
/**
* Unzip the target file to the specified folder.
*
* @param sourceFile target file
* @param outputDir specified folder
* @param checksum checksum
* @throws IOException IOException
*/
public static void decompress(final String sourceFile, final String outputDir, final Checksum checksum)
throws IOException {
try (final FileInputStream fis = new FileInputStream(sourceFile);
final CheckedInputStream cis = new CheckedInputStream(fis, checksum);
final ZipInputStream zis = new ZipInputStream(new BufferedInputStream(cis))) {
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
final String fileName = entry.getName();
final File entryFile = new File(Paths.get(outputDir, fileName).toString());
FileUtils.forceMkdir(entryFile.getParentFile());
try (final FileOutputStream fos = new FileOutputStream(entryFile);
final BufferedOutputStream bos = new BufferedOutputStream(fos)) {
IOUtils.copy(zis, bos);
bos.flush();
fos.getFD().sync();
}
}
// Continue to read all remaining bytes(extra metadata of ZipEntry) directly from the checked stream,
// Otherwise, the checksum value maybe unexpected.
//
// See https://coderanch.com/t/279175/java/ZipInputStream
IOUtils.copy(cis, NullOutputStream.NULL_OUTPUT_STREAM);
}
}
/**
* Unzip the target file to byte array.
*
* @param sourceFile target file
* @param checksum checksum
* @return decompress byte array
* @throws IOException IOException during decompress
*/
public static byte[] decompress(final String sourceFile, final Checksum checksum) throws IOException {
byte[] result;
try (final FileInputStream fis = new FileInputStream(sourceFile);
final CheckedInputStream cis = new CheckedInputStream(fis, checksum);
final ZipInputStream zis = new ZipInputStream(new BufferedInputStream(cis));
final ByteArrayOutputStream bos = new ByteArrayOutputStream(1024)) {
while (zis.getNextEntry() != null) {
IOUtils.copy(zis, bos);
bos.flush();
}
IOUtils.copy(cis, NullOutputStream.NULL_OUTPUT_STREAM);
result = bos.toByteArray();
}
return result;
}
/**
* Returns an Iterator for the lines in a <code>File</code>.
* <p>
* This method opens an <code>InputStream</code> for the file. When you have finished with the iterator you should
* close the stream to free internal resources. This can be done by calling the {@link
* org.apache.commons.io.LineIterator#close()} or {@link org.apache.commons.io.LineIterator#closeQuietly(org.apache.commons.io.LineIterator)}
* method.
* </p>
* The recommended usage pattern is:
* <pre>
* LineIterator it = FileUtils.lineIterator(file, "UTF-8");
* try {
* while (it.hasNext()) {
* String line = it.nextLine();
* /// do something with line
* }
* } finally {
* LineIterator.closeQuietly(iterator);
* }
* </pre>
* <p>
* If an exception occurs during the creation of the iterator, the underlying stream is closed.
* </p>
*
* @param file the file to open for input, must not be <code>null</code>
* @param encoding the encoding to use, <code>null</code> means platform default
* @return an Iterator of the lines in the file, never <code>null</code>
* @throws IOException in case of an I/O error (file closed)
* @since 1.2
*/
public static LineIterator lineIterator(File file, String encoding) throws IOException {
return new LineIterator(FileUtils.lineIterator(file, encoding));
}
/**
* Returns an Iterator for the lines in a <code>File</code> using the default encoding for the VM.
*
* @param file the file to open for input, must not be <code>null</code>
* @return an Iterator of the lines in the file, never <code>null</code>
* @throws IOException in case of an I/O error (file closed)
* @see #lineIterator(File, String)
* @since 1.3
*/
public static LineIterator lineIterator(File file) throws IOException {
return new LineIterator(FileUtils.lineIterator(file, null));
}
public static class LineIterator implements AutoCloseable {
private final org.apache.commons.io.LineIterator target;
/**
* Constructs an iterator of the lines for a <code>Reader</code>.
*
* @param target {@link org.apache.commons.io.LineIterator}
*/
LineIterator(org.apache.commons.io.LineIterator target) {
this.target = target;
}
public boolean hasNext() {
return target.hasNext();
}
public String next() {
return target.next();
}
public String nextLine() {
return target.nextLine();
}
@Override
public void close() throws IOException {
target.close();
}
public void remove() {
target.remove();
}
public void forEachRemaining(Consumer<? super String> action) {
target.forEachRemaining(action);
}
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright 1999-2023 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.plugin.control.utils;
import com.alibaba.nacos.common.utils.StringUtils;
import java.nio.file.Paths;
/**
* Control plugin env utils.
*
* @author xiweng.yy
*/
public class EnvUtils {
public static final String NACOS_HOME_KEY = "nacos.home";
private static final String NACOS_HOME_PROPERTY = "user.home";
private static final String NACOS_HOME_ADDITIONAL_FILEPATH = "nacos";
private static String nacosHomePath = null;
public static String getNacosHome() {
if (StringUtils.isBlank(nacosHomePath)) {
String nacosHome = System.getProperty(NACOS_HOME_KEY);
if (StringUtils.isBlank(nacosHome)) {
nacosHome = Paths.get(System.getProperty(NACOS_HOME_PROPERTY), NACOS_HOME_ADDITIONAL_FILEPATH)
.toString();
}
return nacosHome;
}
return nacosHomePath;
}
}

View File

@ -0,0 +1,100 @@
/*
* Copyright 1999-2024 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.plugin.control;
import com.alibaba.nacos.plugin.control.connection.ConnectionControlManager;
import com.alibaba.nacos.plugin.control.connection.request.ConnectionCheckRequest;
import com.alibaba.nacos.plugin.control.connection.response.ConnectionCheckCode;
import com.alibaba.nacos.plugin.control.connection.response.ConnectionCheckResponse;
import com.alibaba.nacos.plugin.control.connection.rule.ConnectionControlRule;
import com.alibaba.nacos.plugin.control.spi.ControlManagerBuilder;
import com.alibaba.nacos.plugin.control.tps.TpsControlManager;
import com.alibaba.nacos.plugin.control.tps.barrier.TpsBarrier;
import com.alibaba.nacos.plugin.control.tps.request.TpsCheckRequest;
import com.alibaba.nacos.plugin.control.tps.response.TpsCheckResponse;
import com.alibaba.nacos.plugin.control.tps.response.TpsResultCode;
import com.alibaba.nacos.plugin.control.tps.rule.TpsControlRule;
import java.util.Map;
public class ControlManagerBuilderTest implements ControlManagerBuilder {
@Override
public String getName() {
return "test";
}
@Override
public ConnectionControlManager buildConnectionControlManager() {
return new ConnectionControlManager() {
@Override
public String getName() {
return "testConnection";
}
@Override
public void applyConnectionLimitRule(ConnectionControlRule connectionControlRule) {
}
@Override
public ConnectionCheckResponse check(ConnectionCheckRequest connectionCheckRequest) {
ConnectionCheckResponse connectionCheckResponse = new ConnectionCheckResponse();
connectionCheckResponse.setSuccess(true);
connectionCheckResponse.setCode(ConnectionCheckCode.PASS_BY_TOTAL);
return connectionCheckResponse;
}
};
}
@Override
public TpsControlManager buildTpsControlManager() {
return new TpsControlManager() {
@Override
public void registerTpsPoint(String pointName) {
}
@Override
public Map<String, TpsBarrier> getPoints() {
return null;
}
@Override
public Map<String, TpsControlRule> getRules() {
return null;
}
@Override
public void applyTpsRule(String pointName, TpsControlRule rule) {
}
@Override
public TpsCheckResponse check(TpsCheckRequest tpsRequest) {
return new TpsCheckResponse(true, TpsResultCode.CHECK_SKIP, "skip");
}
@Override
public String getName() {
return "testTps";
}
};
}
}

View File

@ -0,0 +1,241 @@
/*
* Copyright 1999-2024 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.plugin.control;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.plugin.control.configs.ControlConfigs;
import com.alibaba.nacos.plugin.control.connection.ConnectionControlManager;
import com.alibaba.nacos.plugin.control.connection.rule.ConnectionControlRule;
import com.alibaba.nacos.plugin.control.rule.storage.RuleStorageProxy;
import com.alibaba.nacos.plugin.control.tps.MonitorType;
import com.alibaba.nacos.plugin.control.tps.TpsControlManager;
import com.alibaba.nacos.plugin.control.tps.rule.RuleDetail;
import com.alibaba.nacos.plugin.control.tps.rule.TpsControlRule;
import com.alibaba.nacos.plugin.control.utils.EnvUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.concurrent.TimeUnit;
public class ControlManagerCenterTest {
@Before
public void initInstance() throws NoSuchFieldException, IllegalAccessException {
//reset instance for reload spi
Field instanceControlConfigs = ControlConfigs.class.getDeclaredField("instance");
instanceControlConfigs.setAccessible(true);
instanceControlConfigs.set(null, null);
Field instanceControlManagerCenter = ControlManagerCenter.class.getDeclaredField("instance");
instanceControlManagerCenter.setAccessible(true);
instanceControlManagerCenter.set(null, null);
}
private void resetRuleStorageProxy() {
try {
//reset instance for reload spi
Field instanceRuleStorageProxy = RuleStorageProxy.class.getDeclaredField("INSTANCE");
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(instanceRuleStorageProxy, instanceRuleStorageProxy.getModifiers() & ~Modifier.FINAL);
instanceRuleStorageProxy.setAccessible(true);
Constructor<RuleStorageProxy> constructor = RuleStorageProxy.class.getDeclaredConstructor();
constructor.setAccessible(true);
Field modifiersFieldConstructor = Constructor.class.getDeclaredField("modifiers");
modifiersFieldConstructor.setAccessible(true);
modifiersFieldConstructor.setInt(constructor, constructor.getModifiers() & ~Modifier.PRIVATE);
instanceRuleStorageProxy.set(null, constructor.newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void testGetInstance() {
ControlConfigs.getInstance().setControlManagerType("test");
ControlManagerCenter controlManagerCenter = ControlManagerCenter.getInstance();
ConnectionControlManager connectionControlManager = controlManagerCenter.getConnectionControlManager();
Assert.assertEquals("testConnection", connectionControlManager.getName());
TpsControlManager tpsControlManager = controlManagerCenter.getTpsControlManager();
Assert.assertEquals("testTps", tpsControlManager.getName());
Assert.assertNotNull(controlManagerCenter.getRuleStorageProxy());
}
@Test
public void testGetInstanceWithDefault() {
ControlManagerCenter controlManagerCenter = ControlManagerCenter.getInstance();
ConnectionControlManager connectionControlManager = controlManagerCenter.getConnectionControlManager();
Assert.assertEquals("noLimit", connectionControlManager.getName());
TpsControlManager tpsControlManager = controlManagerCenter.getTpsControlManager();
Assert.assertEquals("noLimit", tpsControlManager.getName());
}
@Test
public void testReloadTpsControlRule() throws Exception {
String localRuleStorageBaseDir =
EnvUtils.getNacosHome() + File.separator + "tmpTps" + File.separator + "tps" + File.separator;
ControlConfigs.getInstance().setLocalRuleStorageBaseDir(localRuleStorageBaseDir);
resetRuleStorageProxy();
final ControlManagerCenter controlManagerCenter = ControlManagerCenter.getInstance();
TpsControlRule tpsControlRule = new TpsControlRule();
tpsControlRule.setPointName("test");
RuleDetail ruleDetail = new RuleDetail();
ruleDetail.setMaxCount(100);
ruleDetail.setRuleName("test");
ruleDetail.setMonitorType(MonitorType.INTERCEPT.getType());
ruleDetail.setPeriod(TimeUnit.SECONDS);
tpsControlRule.setPointRule(ruleDetail);
String ruleContent = JacksonUtils.toJson(tpsControlRule);
controlManagerCenter.getRuleStorageProxy().getLocalDiskStorage().saveTpsRule("test", ruleContent);
controlManagerCenter.getTpsControlManager().applyTpsRule("test", tpsControlRule);
TpsControlRule testTpsControlRule = controlManagerCenter.getTpsControlManager().getRules().get("test");
Assert.assertEquals(100, testTpsControlRule.getPointRule().getMaxCount());
Assert.assertEquals("test", testTpsControlRule.getPointRule().getRuleName());
TpsControlRule tpsControlRule2 = new TpsControlRule();
tpsControlRule2.setPointName("test");
RuleDetail ruleDetail2 = new RuleDetail();
ruleDetail2.setMaxCount(200);
ruleDetail2.setRuleName("test2");
ruleDetail2.setMonitorType(MonitorType.INTERCEPT.getType());
ruleDetail2.setPeriod(TimeUnit.SECONDS);
tpsControlRule2.setPointRule(ruleDetail2);
String ruleContent2 = JacksonUtils.toJson(tpsControlRule2);
controlManagerCenter.getRuleStorageProxy().getLocalDiskStorage().saveTpsRule("test", ruleContent2);
controlManagerCenter.reloadTpsControlRule("test", false);
//wait event
TimeUnit.SECONDS.sleep(1);
TpsControlRule testTpsControlRule2 = controlManagerCenter.getTpsControlManager().getRules().get("test");
Assert.assertEquals(200, testTpsControlRule2.getPointRule().getMaxCount());
Assert.assertEquals("test2", testTpsControlRule2.getPointRule().getRuleName());
}
@Test
public void testReloadTpsControlRuleExternal() throws Exception {
String localRuleStorageBaseDir =
EnvUtils.getNacosHome() + File.separator + "tmpTps" + File.separator + "tpsExternal" + File.separator;
ControlConfigs.getInstance().setLocalRuleStorageBaseDir(localRuleStorageBaseDir);
ControlConfigs.getInstance().setRuleExternalStorage("test");
resetRuleStorageProxy();
final ControlManagerCenter controlManagerCenter = ControlManagerCenter.getInstance();
TpsControlRule tpsControlRule = new TpsControlRule();
tpsControlRule.setPointName("test");
RuleDetail ruleDetail = new RuleDetail();
ruleDetail.setMaxCount(100);
ruleDetail.setRuleName("test");
ruleDetail.setMonitorType(MonitorType.INTERCEPT.getType());
ruleDetail.setPeriod(TimeUnit.SECONDS);
tpsControlRule.setPointRule(ruleDetail);
String ruleContent = JacksonUtils.toJson(tpsControlRule);
controlManagerCenter.getRuleStorageProxy().getExternalStorage().saveTpsRule("test", ruleContent);
controlManagerCenter.getTpsControlManager().applyTpsRule("test", tpsControlRule);
TpsControlRule testTpsControlRule = controlManagerCenter.getTpsControlManager().getRules().get("test");
Assert.assertEquals(100, testTpsControlRule.getPointRule().getMaxCount());
Assert.assertEquals("test", testTpsControlRule.getPointRule().getRuleName());
TpsControlRule tpsControlRule2 = new TpsControlRule();
tpsControlRule2.setPointName("test");
RuleDetail ruleDetail2 = new RuleDetail();
ruleDetail2.setMaxCount(200);
ruleDetail2.setRuleName("test2");
ruleDetail2.setMonitorType(MonitorType.INTERCEPT.getType());
ruleDetail2.setPeriod(TimeUnit.SECONDS);
tpsControlRule2.setPointRule(ruleDetail2);
String ruleContent2 = JacksonUtils.toJson(tpsControlRule2);
controlManagerCenter.getRuleStorageProxy().getExternalStorage().saveTpsRule("test", ruleContent2);
controlManagerCenter.reloadTpsControlRule("test", true);
//wait event
TimeUnit.SECONDS.sleep(1);
TpsControlRule testTpsControlRule2 = controlManagerCenter.getTpsControlManager().getRules().get("test");
Assert.assertEquals(200, testTpsControlRule2.getPointRule().getMaxCount());
Assert.assertEquals("test2", testTpsControlRule2.getPointRule().getRuleName());
}
@Test
public void testReloadConnectionControlRule() throws Exception {
String localRuleStorageBaseDir =
EnvUtils.getNacosHome() + File.separator + "tmpConnection" + File.separator + "connection"
+ File.separator;
ControlConfigs.getInstance().setLocalRuleStorageBaseDir(localRuleStorageBaseDir);
resetRuleStorageProxy();
ConnectionControlRule connectionLimitRule = new ConnectionControlRule();
connectionLimitRule.setCountLimit(100);
String ruleContent = JacksonUtils.toJson(connectionLimitRule);
ControlManagerCenter controlManagerCenter = ControlManagerCenter.getInstance();
controlManagerCenter.getRuleStorageProxy().getLocalDiskStorage().saveConnectionRule(ruleContent);
ConnectionControlManager connectionControlManager = controlManagerCenter.getConnectionControlManager();
//apply rule
connectionControlManager.applyConnectionLimitRule(connectionLimitRule);
ConnectionControlRule connectionLimitRule1 = connectionControlManager.getConnectionLimitRule();
Assert.assertEquals(100, connectionLimitRule1.getCountLimit());
ConnectionControlRule connectionLimitRule2 = new ConnectionControlRule();
connectionLimitRule2.setCountLimit(200);
String ruleContent2 = JacksonUtils.toJson(connectionLimitRule2);
controlManagerCenter.getRuleStorageProxy().getLocalDiskStorage().saveConnectionRule(ruleContent2);
//reload new rule
controlManagerCenter.reloadConnectionControlRule(false);
//wait event
TimeUnit.SECONDS.sleep(1);
ConnectionControlRule connectionLimitRule3 = connectionControlManager.getConnectionLimitRule();
Assert.assertEquals(200, connectionLimitRule3.getCountLimit());
}
@Test
public void testReloadConnectionControlRuleExternal() throws Exception {
String localRuleStorageBaseDir =
EnvUtils.getNacosHome() + File.separator + "tmpConnection" + File.separator + "connectionExternal"
+ File.separator;
ControlConfigs.getInstance().setLocalRuleStorageBaseDir(localRuleStorageBaseDir);
ControlConfigs.getInstance().setRuleExternalStorage("test");
resetRuleStorageProxy();
ConnectionControlRule connectionLimitRule = new ConnectionControlRule();
connectionLimitRule.setCountLimit(100);
String ruleContent = JacksonUtils.toJson(connectionLimitRule);
ControlManagerCenter controlManagerCenter = ControlManagerCenter.getInstance();
controlManagerCenter.getRuleStorageProxy().getExternalStorage().saveConnectionRule(ruleContent);
ConnectionControlManager connectionControlManager = controlManagerCenter.getConnectionControlManager();
//apply rule
connectionControlManager.applyConnectionLimitRule(connectionLimitRule);
ConnectionControlRule connectionLimitRule1 = connectionControlManager.getConnectionLimitRule();
Assert.assertEquals(100, connectionLimitRule1.getCountLimit());
ConnectionControlRule connectionLimitRule2 = new ConnectionControlRule();
connectionLimitRule2.setCountLimit(200);
String ruleContent2 = JacksonUtils.toJson(connectionLimitRule2);
controlManagerCenter.getRuleStorageProxy().getExternalStorage().saveConnectionRule(ruleContent2);
//reload new rule
controlManagerCenter.reloadConnectionControlRule(true);
//wait event
TimeUnit.SECONDS.sleep(1);
ConnectionControlRule connectionLimitRule3 = connectionControlManager.getConnectionLimitRule();
Assert.assertEquals(200, connectionLimitRule3.getCountLimit());
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright 1999-2020 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.plugin.control.connection;
import com.alibaba.nacos.plugin.control.connection.request.ConnectionCheckRequest;
import com.alibaba.nacos.plugin.control.connection.response.ConnectionCheckCode;
import com.alibaba.nacos.plugin.control.connection.response.ConnectionCheckResponse;
import com.alibaba.nacos.plugin.control.connection.rule.ConnectionControlRule;
import org.junit.Assert;
import org.junit.Test;
/**
* two fixed metrics, total 30, iptotal 15, detail is testa(total-20,iptotal-10),testb(total-10,iptotal-5).
*/
public class DefaultConnectionControlManagerTest {
DefaultConnectionControlManager connectionControlManager = new DefaultConnectionControlManager();
@Test
public void test() {
ConnectionControlRule connectionControlRule = new ConnectionControlRule();
ConnectionCheckRequest connectionCheckRequest = new ConnectionCheckRequest("127.0.0.1", "test", "sdk");
ConnectionCheckResponse check = connectionControlManager.check(connectionCheckRequest);
connectionControlRule.setCountLimit(40);
connectionControlManager.applyConnectionLimitRule(connectionControlRule);
check = connectionControlManager.check(connectionCheckRequest);
Assert.assertTrue(check.isSuccess());
Assert.assertEquals(ConnectionCheckCode.CHECK_SKIP, check.getCode());
}
}

View File

@ -0,0 +1,35 @@
/*
* Copyright 1999-2020 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.plugin.control.connection;
public class TestAConnectionMetricsCollector implements ConnectionMetricsCollector {
@Override
public String getName() {
return "testa";
}
@Override
public int getTotalCount() {
return 20;
}
@Override
public int getCountForIp(String ip) {
return 10;
}
}

View File

@ -0,0 +1,35 @@
/*
* Copyright 1999-2020 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.plugin.control.connection;
public class TestBConnectionMetricsCollector implements ConnectionMetricsCollector {
@Override
public String getName() {
return "testb";
}
@Override
public int getTotalCount() {
return 10;
}
@Override
public int getCountForIp(String ip) {
return 5;
}
}

View File

@ -0,0 +1,32 @@
/*
* Copyright 1999-2024 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.plugin.control.spi;
import com.alibaba.nacos.plugin.control.rule.storage.ExternalRuleStorage;
public class ExternalRuleStorageBuilderTest implements ExternalRuleStorageBuilder {
@Override
public String getName() {
return "test";
}
@Override
public ExternalRuleStorage buildExternalRuleStorage() {
return new ExternalRuleStorageTest();
}
}

View File

@ -0,0 +1,54 @@
/*
* Copyright 1999-2024 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.plugin.control.spi;
import com.alibaba.nacos.plugin.control.rule.storage.ExternalRuleStorage;
import java.util.HashMap;
import java.util.Map;
public class ExternalRuleStorageTest implements ExternalRuleStorage {
private String ruleContent;
private Map<String, String> tpsRuleMap = new HashMap<>(1);
@Override
public String getName() {
return "testExternal";
}
@Override
public void saveConnectionRule(String ruleContent) throws Exception {
this.ruleContent = ruleContent;
}
@Override
public String getConnectionRule() {
return ruleContent;
}
@Override
public void saveTpsRule(String pointName, String ruleContent) throws Exception {
tpsRuleMap.put(pointName, ruleContent);
}
@Override
public String getTpsRule(String pointName) {
return tpsRuleMap.get(pointName);
}
}

View File

@ -0,0 +1,71 @@
/*
* Copyright 1999-2020 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.plugin.control.tps;
import com.alibaba.nacos.plugin.control.tps.barrier.TpsBarrier;
import com.alibaba.nacos.plugin.control.tps.barrier.DefaultNacosTpsBarrier;
import com.alibaba.nacos.plugin.control.tps.request.TpsCheckRequest;
import com.alibaba.nacos.plugin.control.tps.response.TpsCheckResponse;
import com.alibaba.nacos.plugin.control.tps.rule.RuleDetail;
import com.alibaba.nacos.plugin.control.tps.rule.TpsControlRule;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.util.concurrent.TimeUnit;
public class DefaultNacosTpsBarrierTest {
@Before
public void setUp() {
}
@After
public void after() {
}
@Test
public void testNormalPointPassAndDeny() {
String testTpsBarrier = "test_barrier";
// max 5tps
TpsControlRule tpsControlRule = new TpsControlRule();
tpsControlRule.setPointName(testTpsBarrier);
RuleDetail ruleDetail = new RuleDetail();
ruleDetail.setMaxCount(5);
ruleDetail.setMonitorType(MonitorType.INTERCEPT.getType());
ruleDetail.setPeriod(TimeUnit.SECONDS);
tpsControlRule.setPointRule(ruleDetail);
TpsBarrier tpsBarrier = new DefaultNacosTpsBarrier(testTpsBarrier);
tpsBarrier.applyRule(tpsControlRule);
//test point keys
long timeMillis = System.currentTimeMillis();
TpsCheckRequest tpsCheckRequest = new TpsCheckRequest();
tpsCheckRequest.setTimestamp(timeMillis);
// 5tps check pass
for (int i = 0; i < 5; i++) {
TpsCheckResponse tpsCheckResponse = tpsBarrier.applyTps(tpsCheckRequest);
Assert.assertTrue(tpsCheckResponse.isSuccess());
}
}
}

View File

@ -0,0 +1,242 @@
/*
* Copyright 1999-2024 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.plugin.control.utils;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;
public class DiskUtilsTest {
private static File testFile;
private static final String TMP_PATH = EnvUtils.getNacosHome() + File.separator + "data" + File.separator + "tmp" + File.separator;
@BeforeClass
public static void setup() throws IOException {
testFile = DiskUtils.createTmpFile("nacostmp", ".ut");
}
@AfterClass
public static void tearDown() throws IOException {
testFile.deleteOnExit();
}
@Test
public void testTouch() throws IOException {
File file = Paths.get(TMP_PATH, "touch.ut").toFile();
Assert.assertFalse(file.exists());
DiskUtils.touch(file);
Assert.assertTrue(file.exists());
file.deleteOnExit();
}
@Test
public void testTouchWithFileName() throws IOException {
File file = Paths.get(TMP_PATH, UUID.randomUUID().toString()).toFile();
Assert.assertFalse(file.exists());
DiskUtils.touch(file.getParent(), file.getName());
Assert.assertTrue(file.exists());
file.deleteOnExit();
}
@Test
public void testCreateTmpFile() throws IOException {
File tmpFile = null;
try {
tmpFile = DiskUtils.createTmpFile("nacos1", ".ut");
Assert.assertTrue(tmpFile.getName().startsWith("nacos1"));
Assert.assertTrue(tmpFile.getName().endsWith(".ut"));
} finally {
if (tmpFile != null) {
tmpFile.deleteOnExit();
}
}
}
@Test
public void testCreateTmpFileWithPath() throws IOException {
File tmpFile = null;
try {
tmpFile = DiskUtils.createTmpFile(TMP_PATH, "nacos1", ".ut");
Assert.assertEquals(TMP_PATH, tmpFile.getParent() + File.separator);
Assert.assertTrue(tmpFile.getName().startsWith("nacos1"));
Assert.assertTrue(tmpFile.getName().endsWith(".ut"));
} finally {
if (tmpFile != null) {
tmpFile.deleteOnExit();
}
}
}
@Test
public void testReadFile() {
Assert.assertNotNull(DiskUtils.readFile(testFile));
}
@Test
public void testReadFileWithInputStream() throws FileNotFoundException {
Assert.assertNotNull(DiskUtils.readFile(new FileInputStream(testFile)));
}
@Test
public void testReadFileWithPath() {
Assert.assertNotNull(DiskUtils.readFile(testFile.getParent(), testFile.getName()));
}
@Test
public void testReadFileBytes() {
Assert.assertNotNull(DiskUtils.readFileBytes(testFile));
}
@Test
public void testReadFileBytesWithPath() {
Assert.assertNotNull(DiskUtils.readFileBytes(testFile.getParent(), testFile.getName()));
}
@Test
public void writeFile() {
Assert.assertTrue(DiskUtils.writeFile(testFile, "unit test".getBytes(StandardCharsets.UTF_8), false));
Assert.assertEquals("unit test", DiskUtils.readFile(testFile));
}
@Test
public void deleteQuietly() throws IOException {
File tmpFile = DiskUtils.createTmpFile(UUID.randomUUID().toString(), ".ut");
DiskUtils.deleteQuietly(tmpFile);
Assert.assertFalse(tmpFile.exists());
}
@Test
public void testDeleteQuietlyWithPath() throws IOException {
String dir = TMP_PATH + "/" + "diskutils";
DiskUtils.forceMkdir(dir);
DiskUtils.createTmpFile(dir, "nacos", ".ut");
Path path = Paths.get(dir);
DiskUtils.deleteQuietly(path);
Assert.assertFalse(path.toFile().exists());
}
@Test
public void testDeleteFile() throws IOException {
File tmpFile = DiskUtils.createTmpFile(UUID.randomUUID().toString(), ".ut");
Assert.assertTrue(DiskUtils.deleteFile(tmpFile.getParent(), tmpFile.getName()));
Assert.assertFalse(DiskUtils.deleteFile(tmpFile.getParent(), tmpFile.getName()));
}
@Test
public void deleteDirectory() throws IOException {
Path diskutils = Paths.get(TMP_PATH, "diskutils");
File file = diskutils.toFile();
if (!file.exists()) {
file.mkdir();
}
Assert.assertTrue(file.exists());
DiskUtils.deleteDirectory(diskutils.toString());
Assert.assertFalse(file.exists());
}
@Test
public void testForceMkdir() throws IOException {
File dir = Paths.get(TMP_PATH, UUID.randomUUID().toString(), UUID.randomUUID().toString())
.toFile();
DiskUtils.forceMkdir(dir);
Assert.assertTrue(dir.exists());
dir.deleteOnExit();
}
@Test
public void testForceMkdirWithPath() throws IOException {
Path path = Paths.get(TMP_PATH, UUID.randomUUID().toString(), UUID.randomUUID().toString());
DiskUtils.forceMkdir(path.toString());
File file = path.toFile();
Assert.assertTrue(file.exists());
file.deleteOnExit();
}
@Test
public void deleteDirThenMkdir() throws IOException {
Path path = Paths.get(TMP_PATH, UUID.randomUUID().toString());
DiskUtils.forceMkdir(path.toString());
DiskUtils.createTmpFile(path.toString(), UUID.randomUUID().toString(), ".ut");
DiskUtils.createTmpFile(path.toString(), UUID.randomUUID().toString(), ".ut");
DiskUtils.deleteDirThenMkdir(path.toString());
File file = path.toFile();
Assert.assertTrue(file.exists());
Assert.assertTrue(file.isDirectory());
Assert.assertTrue(file.list() == null || file.list().length == 0);
file.deleteOnExit();
}
@Test
public void testCopyDirectory() throws IOException {
Path srcPath = Paths.get(TMP_PATH, UUID.randomUUID().toString());
DiskUtils.forceMkdir(srcPath.toString());
File nacos = DiskUtils.createTmpFile(srcPath.toString(), "nacos", ".ut");
Path destPath = Paths.get(TMP_PATH, UUID.randomUUID().toString());
DiskUtils.copyDirectory(srcPath.toFile(), destPath.toFile());
File file = Paths.get(destPath.toString(), nacos.getName()).toFile();
Assert.assertTrue(file.exists());
DiskUtils.deleteDirectory(srcPath.toString());
DiskUtils.deleteDirectory(destPath.toString());
}
@Test
public void testCopyFile() throws IOException {
File nacos = DiskUtils.createTmpFile("nacos", ".ut");
DiskUtils.copyFile(testFile, nacos);
Assert.assertEquals(DiskUtils.readFile(testFile), DiskUtils.readFile(nacos));
nacos.deleteOnExit();
}
@Test
public void openFile() {
File file = DiskUtils.openFile(testFile.getParent(), testFile.getName());
Assert.assertNotNull(file);
Assert.assertEquals(testFile.getPath(), file.getPath());
Assert.assertEquals(testFile.getName(), file.getName());
}
@Test
public void testOpenFileWithPath() {
File file = DiskUtils.openFile(testFile.getParent(), testFile.getName(), false);
Assert.assertNotNull(file);
Assert.assertEquals(testFile.getPath(), file.getPath());
Assert.assertEquals(testFile.getName(), file.getName());
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright 1999-2024 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.plugin.control.utils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import java.io.File;
public class EnvUtilsTest {
@After
public void tearDown() throws Exception {
System.clearProperty("nacos.home");
}
@Test
public void test() {
String nacosHome = EnvUtils.getNacosHome();
Assert.assertEquals(System.getProperty("user.home") + File.separator + "nacos", nacosHome);
System.setProperty("nacos.home", "test");
String testHome = EnvUtils.getNacosHome();
Assert.assertEquals("test", testHome);
}
}

View File

@ -0,0 +1,36 @@
#
# Copyright 1999-2020 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.
#
#
#
# Copyright 1999-2021 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.
#
#
com.alibaba.nacos.plugin.control.connection.TestAConnectionMetricsCollector
com.alibaba.nacos.plugin.control.connection.TestBConnectionMetricsCollector

View File

@ -0,0 +1,17 @@
#
# Copyright 1999-2024 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.
#
com.alibaba.nacos.plugin.control.ControlManagerBuilderTest

View File

@ -0,0 +1,17 @@
#
# Copyright 1999-2024 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.
#
com.alibaba.nacos.plugin.control.spi.ExternalRuleStorageBuilderTest

View File

@ -0,0 +1,35 @@
#
# Copyright 1999-2020 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.
#
#
#
# Copyright 1999-2021 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.
#
#
com.alibaba.nacos.plugin.control.tps.barrier.creator.LocalSimpleCountBarrierCreator