chore(project): 添加项目配置文件和忽略规则

- 添加 Babel 配置文件支持 ES6+ 语法转换
- 添加 ESLint 忽略规则和配置文件
- 添加 Git 忽略规则文件
- 添加 Travis CI 配置文件
- 添加 1.4.2 版本变更日志文件
- 添加 Helm 图表辅助模板文件
- 添加 Helm 忽略规则文件
This commit is contained in:
2026-03-27 17:36:48 +08:00
commit c2453d6434
1703 changed files with 277582 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 1999-2019 Seata.io Group.
~
~ 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>
<groupId>io.seata</groupId>
<artifactId>seata-config</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>seata-config-core</artifactId>
<name>seata-config-core ${project.version}</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>seata-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.typesafe</groupId>
<artifactId>config</artifactId>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,154 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config;
import java.time.Duration;
import io.seata.common.util.DurationUtil;
/**
* The type Abstract configuration.
*
* @author slievrly
*/
public abstract class AbstractConfiguration implements Configuration {
/**
* The constant DEFAULT_CONFIG_TIMEOUT.
*/
protected static final long DEFAULT_CONFIG_TIMEOUT = 5 * 1000;
@Override
public short getShort(String dataId, int defaultValue, long timeoutMills) {
String result = getConfig(dataId, String.valueOf(defaultValue), timeoutMills);
return Short.parseShort(result);
}
@Override
public short getShort(String dataId, short defaultValue) {
return getShort(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT);
}
@Override
public short getShort(String dataId) {
return getShort(dataId, (short) 0);
}
@Override
public int getInt(String dataId, int defaultValue, long timeoutMills) {
String result = getConfig(dataId, String.valueOf(defaultValue), timeoutMills);
return Integer.parseInt(result);
}
@Override
public int getInt(String dataId, int defaultValue) {
return getInt(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT);
}
@Override
public int getInt(String dataId) {
return getInt(dataId, 0);
}
@Override
public long getLong(String dataId, long defaultValue, long timeoutMills) {
String result = getConfig(dataId, String.valueOf(defaultValue), timeoutMills);
return Long.parseLong(result);
}
@Override
public long getLong(String dataId, long defaultValue) {
return getLong(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT);
}
@Override
public long getLong(String dataId) {
return getLong(dataId, 0L);
}
@Override
public Duration getDuration(String dataId) {
return getDuration(dataId, Duration.ZERO);
}
@Override
public Duration getDuration(String dataId, Duration defaultValue) {
return getDuration(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT);
}
@Override
public Duration getDuration(String dataId, Duration defaultValue, long timeoutMills) {
String result = getConfig(dataId, defaultValue.toMillis() + "ms", timeoutMills);
return DurationUtil.parse(result);
}
@Override
public boolean getBoolean(String dataId, boolean defaultValue, long timeoutMills) {
String result = getConfig(dataId, String.valueOf(defaultValue), timeoutMills);
return Boolean.parseBoolean(result);
}
@Override
public boolean getBoolean(String dataId, boolean defaultValue) {
return getBoolean(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT);
}
@Override
public boolean getBoolean(String dataId) {
return getBoolean(dataId, false);
}
@Override
public String getConfig(String dataId, String defaultValue) {
return getConfig(dataId, defaultValue, DEFAULT_CONFIG_TIMEOUT);
}
@Override
public String getConfig(String dataId, long timeoutMills) {
return getConfig(dataId, null, timeoutMills);
}
@Override
public String getConfig(String dataId, String content, long timeoutMills) {
return getLatestConfig(dataId, content, timeoutMills);
}
@Override
public String getConfig(String dataId) {
return getConfig(dataId, DEFAULT_CONFIG_TIMEOUT);
}
@Override
public boolean putConfig(String dataId, String content) {
return putConfig(dataId, content, DEFAULT_CONFIG_TIMEOUT);
}
@Override
public boolean putConfigIfAbsent(String dataId, String content) {
return putConfigIfAbsent(dataId, content, DEFAULT_CONFIG_TIMEOUT);
}
@Override
public boolean removeConfig(String dataId) {
return removeConfig(dataId, DEFAULT_CONFIG_TIMEOUT);
}
/**
* Gets type name.
*
* @return the type name
*/
public abstract String getTypeName();
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config;
import java.util.concurrent.ExecutorService;
/**
* The interface Config change listener.
*
* @author slievrly
*/
public interface ConfigChangeListener {
/**
* Gets executor.
*
* @return the executor
*/
ExecutorService getExecutor();
/**
* Receive config info.
*
* @param configInfo the config info
*/
void receiveConfigInfo(final String configInfo);
}

View File

@@ -0,0 +1,207 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config;
import io.seata.common.exception.ShouldNeverHappenException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* The type Config future.
*
* @author slievrly
*/
public class ConfigFuture {
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigFuture.class);
private static final long DEFAULT_CONFIG_TIMEOUT = 5 * 1000;
private long timeoutMills;
private long start = System.currentTimeMillis();
private String dataId;
private String content;
private ConfigOperation operation;
private transient CompletableFuture<Object> origin = new CompletableFuture<>();
/**
* Instantiates a new Config future.
*
* @param dataId the data id
* @param content the content
* @param operation the operation
*/
public ConfigFuture(String dataId, String content, ConfigOperation operation) {
this(dataId, content, operation, DEFAULT_CONFIG_TIMEOUT);
}
/**
* Instantiates a new Config future.
*
* @param dataId the data id
* @param content the content
* @param operation the operation
* @param timeoutMills the timeout mills
*/
public ConfigFuture(String dataId, String content, ConfigOperation operation, long timeoutMills) {
this.dataId = dataId;
this.content = content;
this.operation = operation;
this.timeoutMills = timeoutMills;
}
/**
* Gets timeout mills.
*
* @return the timeout mills
*/
public boolean isTimeout() {
return System.currentTimeMillis() - start > timeoutMills;
}
/**
* Get object.
*
* @return the object
*/
public Object get() {
return get(this.timeoutMills, TimeUnit.MILLISECONDS);
}
/**
* Get object.
*
* @param timeout the timeout
* @param unit the unit
* @return the object
*/
public Object get(long timeout, TimeUnit unit) {
this.timeoutMills = unit.toMillis(timeout);
Object result;
try {
result = origin.get(timeout, unit);
} catch (ExecutionException e) {
throw new ShouldNeverHappenException("Should not get results in a multi-threaded environment", e);
} catch (TimeoutException e) {
LOGGER.error("config operation timeout,cost:{} ms,op:{},dataId:{}", System.currentTimeMillis() - start, operation.name(), dataId);
return getFailResult();
} catch (InterruptedException exx) {
LOGGER.error("config operate interrupted,error:{}", exx.getMessage(), exx);
return getFailResult();
}
if (operation == ConfigOperation.GET) {
return result == null ? content : result;
} else {
return result == null ? Boolean.FALSE : result;
}
}
private Object getFailResult() {
if (operation == ConfigOperation.GET) {
return content;
} else {
return Boolean.FALSE;
}
}
/**
* Sets result.
*
* @param result the result
*/
public void setResult(Object result) {
origin.complete(result);
}
/**
* Gets data id.
*
* @return the data id
*/
public String getDataId() {
return dataId;
}
/**
* Sets data id.
*
* @param dataId the data id
*/
public void setDataId(String dataId) {
this.dataId = dataId;
}
/**
* Gets content.
*
* @return the content
*/
public String getContent() {
return content;
}
/**
* Sets content.
*
* @param content the content
*/
public void setContent(String content) {
this.content = content;
}
/**
* Gets operation.
*
* @return the operation
*/
public ConfigOperation getOperation() {
return operation;
}
/**
* Sets operation.
*
* @param operation the operation
*/
public void setOperation(ConfigOperation operation) {
this.operation = operation;
}
/**
* The enum Config operation.
*/
public enum ConfigOperation {
/**
* Get config operation.
*/
GET,
/**
* Put config operation.
*/
PUT,
/**
* Putifabsent config operation.
*/
PUTIFABSENT,
/**
* Remove config operation.
*/
REMOVE
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config;
/**
* The enum Config type.
*
* @author slievrly
*/
public enum ConfigType {
/**
* File config type.
*/
File,
/**
* zookeeper config type.
*/
ZK,
/**
* Nacos config type.
*/
Nacos,
/**
* Apollo config type.
*/
Apollo,
/**
* Consul config type
*/
Consul,
/**
* Etcd3 config type
*/
Etcd3,
/**
* spring cloud config type
*/
SpringCloudConfig,
/**
* Custom config type
*/
Custom;
/**
* Gets type.
*
* @param name the name
* @return the type
*/
public static ConfigType getType(String name) {
for (ConfigType configType : values()) {
if (configType.name().equalsIgnoreCase(name)) {
return configType;
}
}
throw new IllegalArgumentException("not support config type: " + name);
}
}

View File

@@ -0,0 +1,297 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config;
import java.time.Duration;
import java.util.Set;
/**
* The interface Configuration.
*
* @author slievrly
*/
public interface Configuration {
/**
* Gets short.
*
* @param dataId the data id
* @param defaultValue the default value
* @param timeoutMills the timeout mills
* @return the short
*/
short getShort(String dataId, int defaultValue, long timeoutMills);
/**
* Gets short.
*
* @param dataId the data id
* @param defaultValue the default value
* @return the int
*/
short getShort(String dataId, short defaultValue);
/**
* Gets short.
*
* @param dataId the data id
* @return the int
*/
short getShort(String dataId);
/**
* Gets int.
*
* @param dataId the data id
* @param defaultValue the default value
* @param timeoutMills the timeout mills
* @return the int
*/
int getInt(String dataId, int defaultValue, long timeoutMills);
/**
* Gets int.
*
* @param dataId the data id
* @param defaultValue the default value
* @return the int
*/
int getInt(String dataId, int defaultValue);
/**
* Gets int.
*
* @param dataId the data id
* @return the int
*/
int getInt(String dataId);
/**
* Gets long.
*
* @param dataId the data id
* @param defaultValue the default value
* @param timeoutMills the timeout mills
* @return the long
*/
long getLong(String dataId, long defaultValue, long timeoutMills);
/**
* Gets long.
*
* @param dataId the data id
* @param defaultValue the default value
* @return the long
*/
long getLong(String dataId, long defaultValue);
/**
* Gets long.
*
* @param dataId the data id
* @return the long
*/
long getLong(String dataId);
/**
* Gets duration.
*
* @param dataId the data id
* @return the duration
*/
Duration getDuration(String dataId);
/**
* Gets duration.
*
* @param dataId the data id
* @param defaultValue the default value
* @return the duration
*/
Duration getDuration(String dataId, Duration defaultValue);
/**
* Gets duration.
*
* @param dataId the data id
* @param defaultValue the default value
* @param timeoutMills the timeout mills
* @return he duration
*/
Duration getDuration(String dataId, Duration defaultValue, long timeoutMills);
/**
* Gets boolean.
*
* @param dataId the data id
* @param defaultValue the default value
* @param timeoutMills the timeout mills
* @return the boolean
*/
boolean getBoolean(String dataId, boolean defaultValue, long timeoutMills);
/**
* Gets boolean.
*
* @param dataId the data id
* @param defaultValue the default value
* @return the boolean
*/
boolean getBoolean(String dataId, boolean defaultValue);
/**
* Gets boolean.
*
* @param dataId the data id
* @return the boolean
*/
boolean getBoolean(String dataId);
/**
* Gets config.
*
* @param dataId the data id
* @param defaultValue the default value
* @param timeoutMills the timeout mills
* @return the config
*/
String getConfig(String dataId, String defaultValue, long timeoutMills);
/**
* Gets config.
*
* @param dataId the data id
* @param defaultValue the default value
* @return the config
*/
String getConfig(String dataId, String defaultValue);
/**
* Gets config.
*
* @param dataId the data id
* @param timeoutMills the timeout mills
* @return the config
*/
String getConfig(String dataId, long timeoutMills);
/**
* Gets config.
*
* @param dataId the data id
* @return the config
*/
String getConfig(String dataId);
/**
* Put config boolean.
*
* @param dataId the data id
* @param content the content
* @param timeoutMills the timeout mills
* @return the boolean
*/
boolean putConfig(String dataId, String content, long timeoutMills);
/**
*
* @param dataId the data id
* @param defaultValue the default value
* @param timeoutMills the timeout mills
* @return the Latest config
*/
String getLatestConfig(String dataId, String defaultValue, long timeoutMills);
/**
* Put config boolean.
*
* @param dataId the data id
* @param content the content
* @return the boolean
*/
boolean putConfig(String dataId, String content);
/**
* Put config if absent boolean.
*
* @param dataId the data id
* @param content the content
* @param timeoutMills the timeout mills
* @return the boolean
*/
boolean putConfigIfAbsent(String dataId, String content, long timeoutMills);
/**
* Put config if absent boolean.
*
* @param dataId the data id
* @param content the content
* @return the boolean
*/
boolean putConfigIfAbsent(String dataId, String content);
/**
* Remove config boolean.
*
* @param dataId the data id
* @param timeoutMills the timeout mills
* @return the boolean
*/
boolean removeConfig(String dataId, long timeoutMills);
/**
* Remove config boolean.
*
* @param dataId the data id
* @return the boolean
*/
boolean removeConfig(String dataId);
/**
* Add config listener.
*
* @param dataId the data id
* @param listener the listener
*/
void addConfigListener(String dataId, ConfigurationChangeListener listener);
/**
* Remove config listener.
*
* @param dataId the data id
* @param listener the listener
*/
void removeConfigListener(String dataId, ConfigurationChangeListener listener);
/**
* Gets config listeners.
*
* @param dataId the data id
* @return the config listeners
*/
Set<ConfigurationChangeListener> getConfigListeners(String dataId);
/**
* Gets config from sys pro.
*
* @param dataId the data id
* @return the config from sys pro
*/
default String getConfigFromSysPro(String dataId) {
return System.getProperty(dataId);
}
}

View File

@@ -0,0 +1,174 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import io.seata.common.util.DurationUtil;
import io.seata.common.util.StringUtils;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
/**
* @author funkye
*/
public class ConfigurationCache implements ConfigurationChangeListener {
private static final String METHOD_PREFIX = "get";
private static final String METHOD_LATEST_CONFIG = METHOD_PREFIX + "LatestConfig";
private static final ConcurrentHashMap<String, ObjectWrapper> CONFIG_CACHE = new ConcurrentHashMap<>();
private Map<String, HashSet<ConfigurationChangeListener>> configListenersMap = new HashMap<>();
public static void addConfigListener(String dataId, ConfigurationChangeListener... listeners) {
if (StringUtils.isBlank(dataId)) {
return;
}
synchronized (ConfigurationCache.class) {
HashSet<ConfigurationChangeListener> listenerHashSet =
getInstance().configListenersMap.computeIfAbsent(dataId, key -> new HashSet<>());
if (!listenerHashSet.contains(getInstance())) {
ConfigurationFactory.getInstance().addConfigListener(dataId, getInstance());
listenerHashSet.add(getInstance());
}
if (null != listeners && listeners.length > 0) {
for (ConfigurationChangeListener listener : listeners) {
if (!listenerHashSet.contains(listener)) {
listenerHashSet.add(listener);
ConfigurationFactory.getInstance().addConfigListener(dataId, listener);
}
}
}
}
}
public static ConfigurationCache getInstance() {
return ConfigurationCacheInstance.INSTANCE;
}
@Override
public void onChangeEvent(ConfigurationChangeEvent event) {
ObjectWrapper wrapper = CONFIG_CACHE.get(event.getDataId());
// The wrapper.data only exists in the cache when it is not null.
if (StringUtils.isNotBlank(event.getNewValue())) {
if (wrapper == null) {
CONFIG_CACHE.put(event.getDataId(), new ObjectWrapper(event.getNewValue(), null));
} else {
Object newValue = new ObjectWrapper(event.getNewValue(), null).convertData(wrapper.getType());
if (!Objects.equals(wrapper.getData(), newValue)) {
CONFIG_CACHE.put(event.getDataId(), new ObjectWrapper(newValue, wrapper.getType()));
}
}
} else {
CONFIG_CACHE.remove(event.getDataId());
}
}
public Configuration proxy(Configuration originalConfiguration) {
return (Configuration)Enhancer.create(Configuration.class,
(MethodInterceptor)(proxy, method, args, methodProxy) -> {
if (method.getName().startsWith(METHOD_PREFIX)
&& !method.getName().equalsIgnoreCase(METHOD_LATEST_CONFIG)) {
String rawDataId = (String)args[0];
ObjectWrapper wrapper = CONFIG_CACHE.get(rawDataId);
String type = method.getName().substring(METHOD_PREFIX.length());
if (!ObjectWrapper.supportType(type)) {
type = null;
}
if (null == wrapper) {
Object result = method.invoke(originalConfiguration, args);
// The wrapper.data only exists in the cache when it is not null.
if (result != null) {
wrapper = new ObjectWrapper(result, type);
CONFIG_CACHE.put(rawDataId, wrapper);
}
}
return wrapper == null ? null : wrapper.convertData(type);
}
return method.invoke(originalConfiguration, args);
});
}
private static class ConfigurationCacheInstance {
private static final ConfigurationCache INSTANCE = new ConfigurationCache();
}
public void clear() {
CONFIG_CACHE.clear();
}
private static class ObjectWrapper {
static final String INT = "Int";
static final String BOOLEAN = "Boolean";
static final String DURATION = "Duration";
static final String LONG = "Long";
static final String SHORT = "Short";
private final Object data;
private final String type;
ObjectWrapper(Object data, String type) {
this.data = data;
this.type = type;
}
public Object getData() {
return data;
}
public String getType() {
return type;
}
public Object convertData(String aType) {
if (data != null && Objects.equals(type, aType)) {
return data;
}
if (data != null) {
if (INT.equals(aType)) {
return Integer.parseInt(data.toString());
} else if (BOOLEAN.equals(aType)) {
return Boolean.parseBoolean(data.toString());
} else if (DURATION.equals(aType)) {
return DurationUtil.parse(data.toString());
} else if (LONG.equals(aType)) {
return Long.parseLong(data.toString());
} else if (SHORT.equals(aType)) {
return Short.parseShort(data.toString());
}
return String.valueOf(data);
}
return null;
}
public static boolean supportType(String type) {
return INT.equalsIgnoreCase(type)
|| BOOLEAN.equalsIgnoreCase(type)
|| DURATION.equalsIgnoreCase(type)
|| LONG.equalsIgnoreCase(type)
|| SHORT.equalsIgnoreCase(type);
}
}
}

View File

@@ -0,0 +1,144 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config;
/**
* The type Configuration change event.
*
* @author slievrly
*/
public class ConfigurationChangeEvent {
private String dataId;
private String oldValue;
private String newValue;
private String namespace;
private ConfigurationChangeType changeType;
private static final String DEFAULT_NAMESPACE = "DEFAULT";
public ConfigurationChangeEvent(){
}
public ConfigurationChangeEvent(String dataId, String newValue) {
this(dataId, DEFAULT_NAMESPACE, null, newValue, ConfigurationChangeType.MODIFY);
}
public ConfigurationChangeEvent(String dataId, String namespace, String oldValue, String newValue,
ConfigurationChangeType type) {
this.dataId = dataId;
this.namespace = namespace;
this.oldValue = oldValue;
this.newValue = newValue;
this.changeType = type;
}
/**
* Gets data id.
*
* @return the data id
*/
public String getDataId() {
return dataId;
}
/**
* Sets data id.
*
* @param dataId the data id
*/
public ConfigurationChangeEvent setDataId(String dataId) {
this.dataId = dataId;
return this;
}
/**
* Gets old value.
*
* @return the old value
*/
public String getOldValue() {
return oldValue;
}
/**
* Sets old value.
*
* @param oldValue the old value
*/
public ConfigurationChangeEvent setOldValue(String oldValue) {
this.oldValue = oldValue;
return this;
}
/**
* Gets new value.
*
* @return the new value
*/
public String getNewValue() {
return newValue;
}
/**
* Sets new value.
*
* @param newValue the new value
*/
public ConfigurationChangeEvent setNewValue(String newValue) {
this.newValue = newValue;
return this;
}
/**
* Gets change type.
*
* @return the change type
*/
public ConfigurationChangeType getChangeType() {
return changeType;
}
/**
* Sets change type.
*
* @param changeType the change type
*/
public ConfigurationChangeEvent setChangeType(ConfigurationChangeType changeType) {
this.changeType = changeType;
return this;
}
/**
* Gets namespace.
*
* @return the namespace
*/
public String getNamespace() {
return namespace;
}
/**
* Sets namespace.
*
* @param namespace the namespace
*/
public ConfigurationChangeEvent setNamespace(String namespace) {
this.namespace = namespace;
return this;
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import io.seata.common.thread.NamedThreadFactory;
/**
* The interface Configuration change listener.
*
* @author slievrly
*/
public interface ConfigurationChangeListener {
/**
* The constant CORE_LISTENER_THREAD.
*/
int CORE_LISTENER_THREAD = 1;
/**
* The constant MAX_LISTENER_THREAD.
*/
int MAX_LISTENER_THREAD = 1;
/**
* The constant EXECUTOR_SERVICE.
*/
ExecutorService EXECUTOR_SERVICE = new ThreadPoolExecutor(CORE_LISTENER_THREAD, MAX_LISTENER_THREAD,
Integer.MAX_VALUE, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(),
new NamedThreadFactory("configListenerOperate", MAX_LISTENER_THREAD));
/**
* Process.
*
* @param event the event
*/
void onChangeEvent(ConfigurationChangeEvent event);
/**
* On process event.
*
* @param event the event
*/
default void onProcessEvent(ConfigurationChangeEvent event) {
getExecutorService().submit(() -> {
beforeEvent();
onChangeEvent(event);
afterEvent();
});
}
/**
* On shut down.
*/
default void onShutDown() {
getExecutorService().shutdownNow();
}
/**
* Gets executor service.
*
* @return the executor service
*/
default ExecutorService getExecutorService() {
return EXECUTOR_SERVICE;
}
/**
* Before event.
*/
default void beforeEvent() {
}
/**
* After event.
*/
default void afterEvent() {
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config;
/**
* The enum Configuration change type.
*
* @author slievrly
*/
public enum ConfigurationChangeType {
/**
* Add configuration change type.
*/
ADD,
/**
* Modify configuration change type.
*/
MODIFY,
/**
* Delete configuration change type.
*/
DELETE
}

View File

@@ -0,0 +1,157 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config;
import java.util.Objects;
import io.seata.common.exception.NotSupportYetException;
import io.seata.common.loader.EnhancedServiceLoader;
import io.seata.common.loader.EnhancedServiceNotFoundException;
import io.seata.common.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The type Configuration factory.
*
* @author slievrly
* @author Geng Zhang
*/
public final class ConfigurationFactory {
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationFactory.class);
private static final String REGISTRY_CONF_DEFAULT = "registry";
private static final String ENV_SYSTEM_KEY = "SEATA_ENV";
public static final String ENV_PROPERTY_KEY = "seataEnv";
private static final String SYSTEM_PROPERTY_SEATA_CONFIG_NAME = "seata.config.name";
private static final String ENV_SEATA_CONFIG_NAME = "SEATA_CONFIG_NAME";
public static Configuration CURRENT_FILE_INSTANCE;
static {
load();
}
private static void load() {
String seataConfigName = System.getProperty(SYSTEM_PROPERTY_SEATA_CONFIG_NAME);
if (seataConfigName == null) {
seataConfigName = System.getenv(ENV_SEATA_CONFIG_NAME);
}
if (seataConfigName == null) {
seataConfigName = REGISTRY_CONF_DEFAULT;
}
String envValue = System.getProperty(ENV_PROPERTY_KEY);
if (envValue == null) {
envValue = System.getenv(ENV_SYSTEM_KEY);
}
Configuration configuration = (envValue == null) ? new FileConfiguration(seataConfigName,
false) : new FileConfiguration(seataConfigName + "-" + envValue, false);
Configuration extConfiguration = null;
try {
extConfiguration = EnhancedServiceLoader.load(ExtConfigurationProvider.class).provide(configuration);
if (LOGGER.isInfoEnabled()) {
LOGGER.info("load Configuration:{}", extConfiguration == null ? configuration.getClass().getSimpleName()
: extConfiguration.getClass().getSimpleName());
}
} catch (EnhancedServiceNotFoundException ignore) {
} catch (Exception e) {
LOGGER.error("failed to load extConfiguration:{}", e.getMessage(), e);
}
CURRENT_FILE_INSTANCE = extConfiguration == null ? configuration : extConfiguration;
}
private static final String NAME_KEY = "name";
private static final String FILE_TYPE = "file";
private static volatile Configuration instance = null;
/**
* Gets instance.
*
* @return the instance
*/
public static Configuration getInstance() {
if (instance == null) {
synchronized (Configuration.class) {
if (instance == null) {
instance = buildConfiguration();
}
}
}
return instance;
}
private static Configuration buildConfiguration() {
String configTypeName = CURRENT_FILE_INSTANCE.getConfig(
ConfigurationKeys.FILE_ROOT_CONFIG + ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR
+ ConfigurationKeys.FILE_ROOT_TYPE);
if (StringUtils.isBlank(configTypeName)) {
throw new NotSupportYetException("config type can not be null");
}
ConfigType configType = ConfigType.getType(configTypeName);
Configuration extConfiguration = null;
Configuration configuration;
if (ConfigType.File == configType) {
String pathDataId = String.join(ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR,
ConfigurationKeys.FILE_ROOT_CONFIG, FILE_TYPE, NAME_KEY);
String name = CURRENT_FILE_INSTANCE.getConfig(pathDataId);
configuration = new FileConfiguration(name);
try {
extConfiguration = EnhancedServiceLoader.load(ExtConfigurationProvider.class).provide(configuration);
if (LOGGER.isInfoEnabled()) {
LOGGER.info("load Configuration:{}", extConfiguration == null
? configuration.getClass().getSimpleName() : extConfiguration.getClass().getSimpleName());
}
} catch (EnhancedServiceNotFoundException ignore) {
} catch (Exception e) {
LOGGER.error("failed to load extConfiguration:{}", e.getMessage(), e);
}
} else {
configuration = EnhancedServiceLoader
.load(ConfigurationProvider.class, Objects.requireNonNull(configType).name()).provide();
}
try {
Configuration configurationCache;
if (null != extConfiguration) {
configurationCache = ConfigurationCache.getInstance().proxy(extConfiguration);
} else {
configurationCache = ConfigurationCache.getInstance().proxy(configuration);
}
if (null != configurationCache) {
extConfiguration = configurationCache;
}
} catch (EnhancedServiceNotFoundException ignore) {
} catch (Exception e) {
LOGGER.error("failed to load configurationCacheProvider:{}", e.getMessage(), e);
}
return null == extConfiguration ? configuration : extConfiguration;
}
protected static void reload() {
ConfigurationCache.getInstance().clear();
load();
instance = null;
getInstance();
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config;
/**
* The type Configuration keys.
*
* @author slievrly
*/
public interface ConfigurationKeys {
/**
* The constant FILE_ROOT_REGISTRY.
*/
String FILE_ROOT_REGISTRY = "registry";
/**
* The constant FILE_ROOT_CONFIG.
*/
String FILE_ROOT_CONFIG = "config";
/**
* The constant SEATA_FILE_ROOT_CONFIG
*/
String SEATA_FILE_ROOT_CONFIG = "seata";
/**
* The constant FILE_CONFIG_SPLIT_CHAR.
*/
String FILE_CONFIG_SPLIT_CHAR = ".";
/**
* The constant FILE_ROOT_TYPE.
*/
String FILE_ROOT_TYPE = "type";
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config;
/**
* the interface configuration provider
* @author xingfudeshi@gmail.com
*/
public interface ConfigurationProvider {
/**
* provide a AbstractConfiguration implementation instance
* @return Configuration
*/
Configuration provide();
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config;
/**
* the interface ext configuration provider
* @author xingfudeshi@gmail.com
*/
public interface ExtConfigurationProvider {
/**
* provide a AbstractConfiguration implementation instance
* @param originalConfiguration
* @return configuration
*/
Configuration provide(Configuration originalConfiguration);
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config;
import io.seata.common.loader.EnhancedServiceLoader;
import io.seata.config.file.FileConfig;
import java.io.File;
import java.util.LinkedHashMap;
import java.util.Set;
/**
* @author wangwei-ying
*/
public class FileConfigFactory {
public static final String DEFAULT_TYPE = "CONF";
public static final String YAML_TYPE = "YAML";
private static final LinkedHashMap<String, String> SUFFIX_MAP = new LinkedHashMap<String, String>(4) {
{
put("conf", DEFAULT_TYPE);
put("properties", DEFAULT_TYPE);
put("yml", YAML_TYPE);
}
};
public static FileConfig load() {
return loadService(DEFAULT_TYPE, null, null);
}
public static FileConfig load(File targetFile, String name) {
String fileName = targetFile.getName();
String configType = getConfigType(fileName);
return loadService(configType, new Class[]{File.class, String.class}, new Object[]{targetFile, name});
}
private static String getConfigType(String fileName) {
String configType = DEFAULT_TYPE;
int suffixIndex = fileName.lastIndexOf(".");
if (suffixIndex > 0) {
configType = SUFFIX_MAP.getOrDefault(fileName.substring(suffixIndex + 1), DEFAULT_TYPE);
}
return configType;
}
private static FileConfig loadService(String name, Class[] argsType, Object[] args) {
FileConfig fileConfig = EnhancedServiceLoader.load(FileConfig.class, name, argsType, args);
return fileConfig;
}
public static Set<String> getSuffixSet() {
return SUFFIX_MAP.keySet();
}
public synchronized static void register(String suffix, String beanActiveName) {
SUFFIX_MAP.put(suffix, beanActiveName);
}
}

View File

@@ -0,0 +1,429 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import io.netty.util.internal.ConcurrentSet;
import io.seata.common.thread.NamedThreadFactory;
import io.seata.common.util.CollectionUtils;
import io.seata.common.util.StringUtils;
import io.seata.config.ConfigFuture.ConfigOperation;
import io.seata.config.file.FileConfig;
import org.apache.commons.lang.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The type FileConfiguration.
*
* @author slievrly
*/
public class FileConfiguration extends AbstractConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(FileConfiguration.class);
private FileConfig fileConfig;
private ExecutorService configOperateExecutor;
private static final int CORE_CONFIG_OPERATE_THREAD = 1;
private static final int MAX_CONFIG_OPERATE_THREAD = 2;
private static final long LISTENER_CONFIG_INTERVAL = 1 * 1000;
private static final String REGISTRY_TYPE = "file";
public static final String SYS_FILE_RESOURCE_PREFIX = "file:";
private final ConcurrentMap<String, Set<ConfigurationChangeListener>> configListenersMap = new ConcurrentHashMap<>(
8);
private final Map<String, String> listenedConfigMap = new HashMap<>(8);
private final String targetFilePath;
private volatile long targetFileLastModified;
private final String name;
private final FileListener fileListener = new FileListener();
private final boolean allowDynamicRefresh;
/**
* Note that:this constructor is only used to create proxy with CGLIB
* see io.seata.spring.boot.autoconfigure.provider.SpringBootConfigurationProvider#provide
*/
public FileConfiguration() {
this.name = null;
this.targetFilePath = null;
this.allowDynamicRefresh = false;
}
/**
* Instantiates a new File configuration.
*
* @param name the name
*/
public FileConfiguration(String name) {
this(name, true);
}
/**
* Instantiates a new File configuration.
*
* @param name the name
* @param allowDynamicRefresh the allow dynamic refresh
*/
public FileConfiguration(String name, boolean allowDynamicRefresh) {
LOGGER.info("The file name of the operation is {}", name);
File file = getConfigFile(name);
if (file == null) {
targetFilePath = null;
} else {
targetFilePath = file.getPath();
fileConfig = FileConfigFactory.load(file, name);
}
/*
* For seata-server side the conf file should always exists.
* For application(or client) side,conf file may not exists when using seata-spring-boot-starter
*/
if (targetFilePath == null) {
fileConfig = FileConfigFactory.load();
this.allowDynamicRefresh = false;
} else {
targetFileLastModified = new File(targetFilePath).lastModified();
this.allowDynamicRefresh = allowDynamicRefresh;
}
this.name = name;
configOperateExecutor = new ThreadPoolExecutor(CORE_CONFIG_OPERATE_THREAD, MAX_CONFIG_OPERATE_THREAD,
Integer.MAX_VALUE, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(),
new NamedThreadFactory("configOperate", MAX_CONFIG_OPERATE_THREAD));
}
private File getConfigFile(String name) {
try {
if (name == null) {
throw new IllegalArgumentException("name can't be null");
}
boolean filePathCustom = name.startsWith(SYS_FILE_RESOURCE_PREFIX);
String filePath = filePathCustom ? name.substring(SYS_FILE_RESOURCE_PREFIX.length()) : name;
String decodedPath = URLDecoder.decode(filePath, StandardCharsets.UTF_8.name());
File targetFile = getFileFromFileSystem(decodedPath);
if (targetFile != null) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("The configuration file used is {}", targetFile.getPath());
}
return targetFile;
}
if (!filePathCustom) {
File classpathFile = getFileFromClasspath(name);
if (classpathFile != null) {
return classpathFile;
}
}
} catch (UnsupportedEncodingException e) {
LOGGER.error("decode name error: {}", e.getMessage(), e);
}
return null;
}
private File getFileFromFileSystem(String decodedPath) {
// run with jar file and not package third lib into jar file, this.getClass().getClassLoader() will be null
URL resourceUrl = this.getClass().getClassLoader().getResource("");
String[] tryPaths = null;
if (resourceUrl != null) {
tryPaths = new String[]{
// first: project dir
resourceUrl.getPath() + decodedPath,
// second: system path
decodedPath
};
} else {
tryPaths = new String[]{
decodedPath
};
}
for (String tryPath : tryPaths) {
File targetFile = new File(tryPath);
if (targetFile.exists()) {
return targetFile;
}
// try to append config suffix
for (String s : FileConfigFactory.getSuffixSet()) {
targetFile = new File(tryPath + ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR + s);
if (targetFile.exists()) {
return targetFile;
}
}
}
return null;
}
private File getFileFromClasspath(String name) throws UnsupportedEncodingException {
URL resource = this.getClass().getClassLoader().getResource(name);
if (resource == null) {
for (String s : FileConfigFactory.getSuffixSet()) {
resource = this.getClass().getClassLoader().getResource(name + ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR + s);
if (resource != null) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("The configuration file used is {}", resource.getPath());
}
String path = resource.getPath();
path = URLDecoder.decode(path, StandardCharsets.UTF_8.name());
return new File(path);
}
}
} else {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("The configuration file used is {}", name);
}
String path = resource.getPath();
path = URLDecoder.decode(path, StandardCharsets.UTF_8.name());
return new File(path);
}
return null;
}
@Override
public String getLatestConfig(String dataId, String defaultValue, long timeoutMills) {
String value = getConfigFromSysPro(dataId);
if (value != null) {
return value;
}
ConfigFuture configFuture = new ConfigFuture(dataId, defaultValue, ConfigOperation.GET, timeoutMills);
configOperateExecutor.submit(new ConfigOperateRunnable(configFuture));
Object getValue = configFuture.get();
return getValue == null ? null : String.valueOf(getValue);
}
@Override
public boolean putConfig(String dataId, String content, long timeoutMills) {
ConfigFuture configFuture = new ConfigFuture(dataId, content, ConfigOperation.PUT, timeoutMills);
configOperateExecutor.submit(new ConfigOperateRunnable(configFuture));
return (Boolean) configFuture.get();
}
@Override
public boolean putConfigIfAbsent(String dataId, String content, long timeoutMills) {
ConfigFuture configFuture = new ConfigFuture(dataId, content, ConfigOperation.PUTIFABSENT, timeoutMills);
configOperateExecutor.submit(new ConfigOperateRunnable(configFuture));
return (Boolean) configFuture.get();
}
@Override
public boolean removeConfig(String dataId, long timeoutMills) {
ConfigFuture configFuture = new ConfigFuture(dataId, null, ConfigOperation.REMOVE, timeoutMills);
configOperateExecutor.submit(new ConfigOperateRunnable(configFuture));
return (Boolean) configFuture.get();
}
@Override
public void addConfigListener(String dataId, ConfigurationChangeListener listener) {
if (StringUtils.isBlank(dataId) || listener == null) {
return;
}
configListenersMap.computeIfAbsent(dataId, key -> new ConcurrentSet<>())
.add(listener);
listenedConfigMap.put(dataId, ConfigurationFactory.getInstance().getConfig(dataId));
// Start config change listener for the dataId.
fileListener.addListener(dataId, listener);
}
@Override
public void removeConfigListener(String dataId, ConfigurationChangeListener listener) {
if (StringUtils.isBlank(dataId) || listener == null) {
return;
}
Set<ConfigurationChangeListener> configListeners = getConfigListeners(dataId);
if (CollectionUtils.isNotEmpty(configListeners)) {
configListeners.remove(listener);
if (configListeners.isEmpty()) {
configListenersMap.remove(dataId);
listenedConfigMap.remove(dataId);
}
}
listener.onShutDown();
}
@Override
public Set<ConfigurationChangeListener> getConfigListeners(String dataId) {
return configListenersMap.get(dataId);
}
@Override
public String getTypeName() {
return REGISTRY_TYPE;
}
/**
* The type Config operate runnable.
*/
class ConfigOperateRunnable implements Runnable {
private ConfigFuture configFuture;
/**
* Instantiates a new Config operate runnable.
*
* @param configFuture the config future
*/
public ConfigOperateRunnable(ConfigFuture configFuture) {
this.configFuture = configFuture;
}
@Override
public void run() {
if (configFuture != null) {
if (configFuture.isTimeout()) {
setFailResult(configFuture);
return;
}
try {
if (allowDynamicRefresh) {
long tempLastModified = new File(targetFilePath).lastModified();
if (tempLastModified > targetFileLastModified) {
FileConfig tempConfig = FileConfigFactory.load(new File(targetFilePath), name);
if (tempConfig != null) {
fileConfig = tempConfig;
targetFileLastModified = tempLastModified;
}
}
}
if (configFuture.getOperation() == ConfigOperation.GET) {
String result = fileConfig.getString(configFuture.getDataId());
configFuture.setResult(result);
} else if (configFuture.getOperation() == ConfigOperation.PUT) {
//todo
configFuture.setResult(Boolean.TRUE);
} else if (configFuture.getOperation() == ConfigOperation.PUTIFABSENT) {
//todo
configFuture.setResult(Boolean.TRUE);
} else if (configFuture.getOperation() == ConfigOperation.REMOVE) {
//todo
configFuture.setResult(Boolean.TRUE);
}
} catch (Exception e) {
setFailResult(configFuture);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Could not found property {}, try to use default value instead. exception:{}",
configFuture.getDataId(), e.getMessage());
}
}
}
}
private void setFailResult(ConfigFuture configFuture) {
if (configFuture.getOperation() == ConfigOperation.GET) {
String result = configFuture.getContent();
configFuture.setResult(result);
} else {
configFuture.setResult(Boolean.FALSE);
}
}
}
/**
* The type FileListener.
*/
class FileListener implements ConfigurationChangeListener {
private final Map<String, Set<ConfigurationChangeListener>> dataIdMap = new HashMap<>();
private final ExecutorService executor = new ThreadPoolExecutor(CORE_LISTENER_THREAD, MAX_LISTENER_THREAD, 0L,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(),
new NamedThreadFactory("fileListener", MAX_LISTENER_THREAD));
/**
* Instantiates a new FileListener.
*/
FileListener() {}
public synchronized void addListener(String dataId, ConfigurationChangeListener listener) {
// only the first time add listener will trigger on process event
if (dataIdMap.isEmpty()) {
fileListener.onProcessEvent(new ConfigurationChangeEvent());
}
dataIdMap.computeIfAbsent(dataId, value -> new HashSet<>()).add(listener);
}
@Override
public void onChangeEvent(ConfigurationChangeEvent event) {
while (true) {
for (String dataId : dataIdMap.keySet()) {
try {
String currentConfig =
ConfigurationFactory.getInstance().getLatestConfig(dataId, null, DEFAULT_CONFIG_TIMEOUT);
if (StringUtils.isNotBlank(currentConfig)) {
String oldConfig = listenedConfigMap.get(dataId);
if (ObjectUtils.notEqual(currentConfig, oldConfig)) {
listenedConfigMap.put(dataId, currentConfig);
event.setDataId(dataId).setNewValue(currentConfig).setOldValue(oldConfig);
for (ConfigurationChangeListener listener : dataIdMap.get(dataId)) {
listener.onChangeEvent(event);
}
}
}
} catch (Exception exx) {
LOGGER.error("fileListener execute error, dataId :{}", dataId, exx);
}
}
try {
Thread.sleep(LISTENER_CONFIG_INTERVAL);
} catch (InterruptedException e) {
LOGGER.error("fileListener thread sleep error:{}", e.getMessage());
}
}
}
@Override
public ExecutorService getExecutorService() {
return executor;
}
}
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config.file;
/**
* @author wangwei-ying
*/
public interface FileConfig {
/**
* @param path path expression
*/
String getString(String path);
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config.file;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import io.seata.common.loader.LoadLevel;
import io.seata.common.loader.Scope;
import io.seata.config.FileConfigFactory;
import io.seata.config.FileConfiguration;
import java.io.File;
/**
* @author wangwei-ying
*/
@LoadLevel(name = FileConfigFactory.DEFAULT_TYPE,scope = Scope.PROTOTYPE)
public class SimpleFileConfig implements FileConfig {
private Config fileConfig;
public SimpleFileConfig() {
fileConfig = ConfigFactory.load();
}
public SimpleFileConfig(File file, String name) {
if (name.startsWith(FileConfiguration.SYS_FILE_RESOURCE_PREFIX)) {
Config appConfig = ConfigFactory.parseFileAnySyntax(file);
fileConfig = ConfigFactory.load(appConfig);
} else {
fileConfig = ConfigFactory.load(file.getName());
}
}
@Override
public String getString(String path) {
return fileConfig.getString(path);
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config.file;
import io.seata.common.loader.LoadLevel;
import io.seata.common.loader.Scope;
import io.seata.config.FileConfigFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.Yaml;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Map;
/**
* @author wangwei-ying
*/
@LoadLevel(name = FileConfigFactory.YAML_TYPE, order = 1, scope = Scope.PROTOTYPE)
public class YamlFileConfig implements FileConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(YamlFileConfig.class);
private Map configMap;
public YamlFileConfig(File file, String name) {
Yaml yaml = new Yaml();
try {
configMap = (Map) yaml.load(new FileInputStream(file));
} catch (FileNotFoundException e) {
throw new IllegalArgumentException("file not found");
}
}
@Override
public String getString(String path) {
try {
Map config = configMap;
String[] dataId = path.split("\\.");
for (int i = 0; i < dataId.length - 1; i++) {
if (config.containsKey(dataId[i])) {
config = (Map) config.get(dataId[i]);
} else {
return null;
}
}
Object value = config.get(dataId[dataId.length - 1]);
return value == null ? null : String.valueOf(value);
} catch (Exception e) {
LOGGER.warn("get config data error" + path, e);
return null;
}
}
}

View File

@@ -0,0 +1,2 @@
io.seata.config.file.SimpleFileConfig
io.seata.config.file.YamlFileConfig

View File

@@ -0,0 +1,8 @@
service {
#transaction service group mapping
vgroupMapping.my_test_tx_group = "default"
#only support when registry.type=file, please don't set multiple addresses
default.grouplist = "127.0.0.1:8091"
#disable seata
disableGlobalTransaction = false
}

View File

@@ -0,0 +1,76 @@
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "file"
nacos {
application = "seata-server"
serverAddr = "localhost"
namespace = ""
cluster = "default"
}
eureka {
serviceUrl = "http://localhost:8761/eureka"
application = "default"
weight = "1"
}
redis {
serverAddr = "localhost:6379"
db = "0"
}
zk {
cluster = "default"
serverAddr = "127.0.0.1:2181"
sessionTimeout = 6000
connectTimeout = 2000
}
consul {
cluster = "default"
serverAddr = "127.0.0.1:8500"
}
etcd3 {
cluster = "default"
serverAddr = "http://localhost:2379"
}
sofa {
serverAddr = "127.0.0.1:9603"
application = "default"
region = "DEFAULT_ZONE"
datacenter = "DefaultDataCenter"
cluster = "default"
group = "SEATA_GROUP"
addressWaitTime = "3000"
}
file {
name = "file.conf"
}
}
config {
# file、nacos 、apollo、zk、consul、etcd3
type = "file"
nacos {
serverAddr = "localhost"
namespace = ""
group = "SEATA_GROUP"
}
consul {
serverAddr = "127.0.0.1:8500"
}
apollo {
appId = "seata-server"
apolloMeta = "http://192.168.1.204:8801"
namespace = "application"
}
zk {
serverAddr = "127.0.0.1:2181"
sessionTimeout = 6000
connectTimeout = 2000
}
etcd3 {
serverAddr = "http://localhost:2379"
}
file {
name = "file.conf"
}
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config;
/**
* @author wangwei-ying
*/
public interface ConfigProperty {
final String ENV_PROPERTY_KEY = "seataEnv";
final String SYSTEM_PROPERTY_SEATA_CONFIG_NAME = "seata.config.name";
final String REGISTRY_CONF_DEFAULT = "registry";
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config;
import io.seata.common.util.DurationUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.time.Duration;
/**
* @author jsbxyyx
*/
public class ConfigurationCacheTests {
@Test
public void testChangeValue() throws Exception {
Configuration configuration = new FileConfiguration("registry");
configuration = ConfigurationCache.getInstance().proxy(configuration);
configuration.getBoolean("aaa", false);
ConfigurationCache.getInstance().onChangeEvent(new ConfigurationChangeEvent("aaa", "true"));
boolean aaa = configuration.getBoolean("aaa", false);
Assertions.assertTrue(aaa);
configuration.getShort("bbb", (short) 0);
ConfigurationCache.getInstance().onChangeEvent(new ConfigurationChangeEvent("bbb", "1"));
short bbb = configuration.getShort("bbb", (short) 0);
Assertions.assertEquals((short) 1, bbb);
configuration.getDuration("ccc", Duration.ZERO);
ConfigurationCache.getInstance().onChangeEvent(new ConfigurationChangeEvent("ccc", "1s"));
Duration ccc = configuration.getDuration("ccc", Duration.ZERO);
Assertions.assertEquals(ccc, DurationUtil.parse("1s"));
configuration.getInt("ddd", 0);
ConfigurationCache.getInstance().onChangeEvent(new ConfigurationChangeEvent("ddd", "1"));
int ddd = configuration.getInt("ddd", 0);
Assertions.assertEquals(1, ddd);
configuration.getLong("eee", 0);
ConfigurationCache.getInstance().onChangeEvent(new ConfigurationChangeEvent("eee", "1"));
long eee = configuration.getLong("eee", 0);
Assertions.assertEquals((long) 1, eee);
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/**
* @author slievrly
*/
class FileConfigurationTest {
@BeforeEach
void setUp() {
}
@AfterEach
void tearDown() {
}
@Test
void addConfigListener() throws InterruptedException {
Configuration fileConfig = ConfigurationFactory.getInstance();
CountDownLatch countDownLatch = new CountDownLatch(1);
boolean value = fileConfig.getBoolean("service.disableGlobalTransaction");
fileConfig.addConfigListener("service.disableGlobalTransaction", (event) -> {
Assertions.assertEquals(Boolean.parseBoolean(event.getNewValue()), !Boolean.parseBoolean(event.getOldValue()));
countDownLatch.countDown();
});
System.setProperty("service.disableGlobalTransaction", String.valueOf(!value));
Assertions.assertTrue(countDownLatch.await(2000, TimeUnit.MILLISECONDS));
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import static io.seata.config.ConfigProperty.ENV_PROPERTY_KEY;
import static io.seata.config.ConfigProperty.SYSTEM_PROPERTY_SEATA_CONFIG_NAME;
import static io.seata.config.ConfigProperty.REGISTRY_CONF_DEFAULT;
/**
* @author wangwei-ying
*/
class ProConfigurationFactoryTest {
@Test
void getInstance() {
System.setProperty(ENV_PROPERTY_KEY, "test-pro");
System.setProperty(SYSTEM_PROPERTY_SEATA_CONFIG_NAME, REGISTRY_CONF_DEFAULT);
ConfigurationFactory.reload();
Assertions.assertEquals(ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig("config.file.name"), "file-test-pro.conf");
Assertions.assertEquals(ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig("config.file.testBlank"), "");
Assertions.assertEquals(ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig("config.file.testNull"), null);
Assertions.assertEquals(ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig("config.file.testExist"), null);
Configuration instance = ConfigurationFactory.getInstance();
Assertions.assertEquals(instance.getConfig("service.disableGlobalTransaction"), "true");
Assertions.assertEquals(instance.getConfig("service.default.grouplist"), "127.0.0.1:8092");
}
@AfterAll
public static void afterAll() {
System.clearProperty(ENV_PROPERTY_KEY);
System.clearProperty(SYSTEM_PROPERTY_SEATA_CONFIG_NAME);
ConfigurationFactory.reload();
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import static io.seata.config.ConfigProperty.ENV_PROPERTY_KEY;
import static io.seata.config.ConfigProperty.SYSTEM_PROPERTY_SEATA_CONFIG_NAME;
import static io.seata.config.ConfigProperty.REGISTRY_CONF_DEFAULT;
/**
* @author wangwei-ying
*/
class RegistryConfigurationFactoryTest {
@Test
void getInstance() {
System.setProperty(ENV_PROPERTY_KEY,"test");
System.setProperty(SYSTEM_PROPERTY_SEATA_CONFIG_NAME,REGISTRY_CONF_DEFAULT);
ConfigurationFactory.reload();
Assertions.assertEquals(ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig("config.file.name"),"file-test.conf");
Configuration instance = ConfigurationFactory.getInstance();
Assertions.assertEquals(instance.getConfig("service.disableGlobalTransaction"),"true");
Assertions.assertEquals(instance.getConfig("service.default.grouplist"), "127.0.0.1:8091");
}
@AfterAll
public static void afterAll(){
System.clearProperty(ENV_PROPERTY_KEY);
System.clearProperty(SYSTEM_PROPERTY_SEATA_CONFIG_NAME);
ConfigurationFactory.reload();
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* 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 io.seata.config;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import static io.seata.config.ConfigProperty.ENV_PROPERTY_KEY;
import static io.seata.config.ConfigProperty.SYSTEM_PROPERTY_SEATA_CONFIG_NAME;
import static io.seata.config.ConfigProperty.REGISTRY_CONF_DEFAULT;
/**
* @author wangwei-ying
*/
class YamlConfigurationFactoryTest {
@Test
public void getInstance() {
System.setProperty(ENV_PROPERTY_KEY, "test-yaml");
System.setProperty(SYSTEM_PROPERTY_SEATA_CONFIG_NAME, REGISTRY_CONF_DEFAULT);
ConfigurationFactory.reload();
Assertions.assertEquals(ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig("config.file.name"), "file-test-yaml.conf");
Assertions.assertEquals(ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig("config.file.testBlank"), "");
Assertions.assertEquals(ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig("config.file.testNull"), null);
Assertions.assertEquals(ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig("config.file.testExist"), null);
Configuration instance = ConfigurationFactory.getInstance();
Assertions.assertEquals(instance.getConfig("service.disableGlobalTransaction"), "true");
Assertions.assertEquals(instance.getConfig("service.default.grouplist"), "127.0.0.1:8093");
}
@AfterAll
public static void afterAll() {
System.clearProperty(ENV_PROPERTY_KEY);
System.clearProperty(SYSTEM_PROPERTY_SEATA_CONFIG_NAME);
ConfigurationFactory.reload();
}
}

View File

@@ -0,0 +1,8 @@
service {
#transaction service group mapping
vgroupMapping.my_test_tx_group = "default"
#only support when registry.type=file, please don't set multiple addresses
default.grouplist = "127.0.0.1:8092"
#disable seata
disableGlobalTransaction = true
}

View File

@@ -0,0 +1,8 @@
service {
#transaction service group mapping
vgroupMapping.my_test_tx_group = "default"
#only support when registry.type=file, please don't set multiple addresses
default.grouplist = "127.0.0.1:8093"
#disable seata
disableGlobalTransaction = true
}

View File

@@ -0,0 +1,8 @@
service {
#transaction service group mapping
vgroupMapping.my_test_tx_group = "default"
#only support when registry.type=file, please don't set multiple addresses
default.grouplist = "127.0.0.1:8091"
#disable seata
disableGlobalTransaction = true
}

View File

@@ -0,0 +1,8 @@
service {
#transaction service group mapping
vgroupMapping.my_test_tx_group = "default"
#only support when registry.type=file, please don't set multiple addresses
default.grouplist = "127.0.0.1:8091"
#disable seata
disableGlobalTransaction = false
}

View File

@@ -0,0 +1,21 @@
#Copyright 1999-2019 Seata.io Group.
#
#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.
registry.type=file
registry.file.name=file-test-pro.conf
config.type=file
config.file.name=file-test-pro.conf
config.file.testBlank=

View File

@@ -0,0 +1,11 @@
registry:
type: file
file:
name: file.conf
config:
type: file
file:
name: file-test-yaml.conf
# for test
testBlank: ''
testNull:

View File

@@ -0,0 +1,73 @@
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "file"
nacos {
serverAddr = "localhost"
namespace = ""
cluster = "default"
}
eureka {
serviceUrl = "http://localhost:8761/eureka"
application = "default"
weight = "1"
}
redis {
serverAddr = "localhost:6379"
db = "0"
}
zk {
cluster = "default"
serverAddr = "127.0.0.1:2181"
sessionTimeout = 6000
connectTimeout = 2000
}
consul {
cluster = "default"
serverAddr = "127.0.0.1:8500"
}
etcd3 {
cluster = "default"
serverAddr = "http://localhost:2379"
}
sofa {
serverAddr = "127.0.0.1:9603"
application = "default"
region = "DEFAULT_ZONE"
datacenter = "DefaultDataCenter"
cluster = "default"
group = "SEATA_GROUP"
addressWaitTime = "3000"
}
file {
name = "file-test.conf"
}
}
config {
# file、nacos 、apollo、zk、consul、etcd3
type = "file"
nacos {
serverAddr = "localhost"
namespace = ""
}
consul {
serverAddr = "127.0.0.1:8500"
}
apollo {
appId = "seata-server"
apolloMeta = "http://192.168.1.204:8801"
}
zk {
serverAddr = "127.0.0.1:2181"
sessionTimeout = 6000
connectTimeout = 2000
}
etcd3 {
serverAddr = "http://localhost:2379"
}
file {
name = "file-test.conf"
}
}

View File

@@ -0,0 +1,73 @@
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "file"
nacos {
serverAddr = "localhost"
namespace = ""
cluster = "default"
}
eureka {
serviceUrl = "http://localhost:8761/eureka"
application = "default"
weight = "1"
}
redis {
serverAddr = "localhost:6379"
db = "0"
}
zk {
cluster = "default"
serverAddr = "127.0.0.1:2181"
sessionTimeout = 6000
connectTimeout = 2000
}
consul {
cluster = "default"
serverAddr = "127.0.0.1:8500"
}
etcd3 {
cluster = "default"
serverAddr = "http://localhost:2379"
}
sofa {
serverAddr = "127.0.0.1:9603"
application = "default"
region = "DEFAULT_ZONE"
datacenter = "DefaultDataCenter"
cluster = "default"
group = "SEATA_GROUP"
addressWaitTime = "3000"
}
file {
name = "file.conf"
}
}
config {
# file、nacos 、apollo、zk、consul、etcd3
type = "file"
nacos {
serverAddr = "localhost"
namespace = ""
}
consul {
serverAddr = "127.0.0.1:8500"
}
apollo {
appId = "seata-server"
apolloMeta = "http://192.168.1.204:8801"
}
zk {
serverAddr = "127.0.0.1:2181"
sessionTimeout = 6000
connectTimeout = 2000
}
etcd3 {
serverAddr = "http://localhost:2379"
}
file {
name = "file.conf"
}
}