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,35 @@
<?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-discovery</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>seata-discovery-core</artifactId>
<name>seata-discovery-core ${project.version}</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>seata-config-core</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

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.discovery.loadbalance;
import java.util.List;
import io.seata.common.util.CollectionUtils;
/**
* The type Abstract load balance.
*
* @author slievrly
*/
public abstract class AbstractLoadBalance implements LoadBalance {
@Override
public <T> T select(List<T> invokers, String xid) {
if (CollectionUtils.isEmpty(invokers)) {
return null;
}
if (invokers.size() == 1) {
return invokers.get(0);
}
return doSelect(invokers, xid);
}
/**
* Do select t.
*
* @param <T> the type parameter
* @param invokers the invokers
* @param xid the xid
* @return the t
*/
protected abstract <T> T doSelect(List<T> invokers, String xid);
}

View File

@@ -0,0 +1,102 @@
/*
* 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.discovery.loadbalance;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import io.seata.common.loader.LoadLevel;
import io.seata.config.ConfigurationFactory;
import static io.seata.common.DefaultValues.VIRTUAL_NODES_DEFAULT;
import static io.seata.discovery.loadbalance.LoadBalanceFactory.CONSISTENT_HASH_LOAD_BALANCE;
import static io.seata.discovery.loadbalance.LoadBalanceFactory.LOAD_BALANCE_PREFIX;
/**
* The type consistent hash load balance.
*
* @author ph3636
*/
@LoadLevel(name = CONSISTENT_HASH_LOAD_BALANCE)
public class ConsistentHashLoadBalance extends AbstractLoadBalance {
/**
* The constant LOAD_BALANCE_CONSISTENT_HASH_VISUAL_NODES.
*/
public static final String LOAD_BALANCE_CONSISTENT_HASH_VISUAL_NODES = LOAD_BALANCE_PREFIX + "visualNodes";
/**
* The constant VIRTUAL_NODES_NUM.
*/
private static final int VIRTUAL_NODES_NUM = ConfigurationFactory.getInstance().getInt(LOAD_BALANCE_CONSISTENT_HASH_VISUAL_NODES, VIRTUAL_NODES_DEFAULT);
@Override
protected <T> T doSelect(List<T> invokers, String xid) {
return new ConsistentHashSelector<>(invokers, VIRTUAL_NODES_NUM).select(xid);
}
private static final class ConsistentHashSelector<T> {
private final SortedMap<Long, T> virtualInvokers = new TreeMap<>();
private final HashFunction hashFunction = new MD5Hash();
ConsistentHashSelector(List<T> invokers, int virtualNodes) {
for (T invoker : invokers) {
for (int i = 0; i < virtualNodes; i++) {
virtualInvokers.put(hashFunction.hash(invoker.toString() + i), invoker);
}
}
}
public T select(String objectKey) {
SortedMap<Long, T> tailMap = virtualInvokers.tailMap(hashFunction.hash(objectKey));
Long nodeHashVal = tailMap.isEmpty() ? virtualInvokers.firstKey() : tailMap.firstKey();
return virtualInvokers.get(nodeHashVal);
}
}
private static class MD5Hash implements HashFunction {
MessageDigest instance;
public MD5Hash() {
try {
instance = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
@Override
public long hash(String key) {
instance.reset();
instance.update(key.getBytes());
byte[] digest = instance.digest();
long h = 0;
for (int i = 0; i < 4; i++) {
h <<= 8;
h |= ((int) digest[i]) & 0xFF;
}
return h;
}
}
/**
* Hash String to long value
*/
public interface HashFunction {
long hash(String key);
}
}

View File

@@ -0,0 +1,55 @@
/*
* 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.discovery.loadbalance;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import io.seata.common.loader.LoadLevel;
import io.seata.common.rpc.RpcStatus;
import static io.seata.discovery.loadbalance.LoadBalanceFactory.LEAST_ACTIVE_LOAD_BALANCE;
/**
* The type Least Active load balance.
*
* @author ph3636
*/
@LoadLevel(name = LEAST_ACTIVE_LOAD_BALANCE)
public class LeastActiveLoadBalance extends AbstractLoadBalance {
@Override
protected <T> T doSelect(List<T> invokers, String xid) {
int length = invokers.size();
long leastActive = -1;
int leastCount = 0;
int[] leastIndexes = new int[length];
for (int i = 0; i < length; i++) {
long active = RpcStatus.getStatus(invokers.get(i).toString()).getActive();
if (leastActive == -1 || active < leastActive) {
leastActive = active;
leastCount = 1;
leastIndexes[0] = i;
} else if (active == leastActive) {
leastIndexes[leastCount++] = i;
}
}
if (leastCount == 1) {
return invokers.get(leastIndexes[0]);
}
return invokers.get(leastIndexes[ThreadLocalRandom.current().nextInt(leastCount)]);
}
}

View File

@@ -0,0 +1,37 @@
/*
* 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.discovery.loadbalance;
import java.util.List;
/**
* The interface Load balance.
*
* @author slievrly
*/
public interface LoadBalance {
/**
* Select t.
*
* @param <T> the type parameter
* @param invokers the invokers
* @param xid the xid
* @return the t
* @throws Exception the exception
*/
<T> T select(List<T> invokers, String xid) throws Exception;
}

View File

@@ -0,0 +1,56 @@
/*
* 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.discovery.loadbalance;
import io.seata.common.loader.EnhancedServiceLoader;
import io.seata.config.ConfigurationFactory;
import static io.seata.common.DefaultValues.DEFAULT_LOAD_BALANCE;
/**
* The type Load balance factory.
*
* @author slievrly
*/
public class LoadBalanceFactory {
private static final String CLIENT_PREFIX = "client.";
/**
* The constant LOAD_BALANCE_PREFIX.
*/
public static final String LOAD_BALANCE_PREFIX = CLIENT_PREFIX + "loadBalance.";
public static final String LOAD_BALANCE_TYPE = LOAD_BALANCE_PREFIX + "type";
public static final String RANDOM_LOAD_BALANCE = DEFAULT_LOAD_BALANCE;
public static final String ROUND_ROBIN_LOAD_BALANCE = "RoundRobinLoadBalance";
public static final String CONSISTENT_HASH_LOAD_BALANCE = "ConsistentHashLoadBalance";
public static final String LEAST_ACTIVE_LOAD_BALANCE = "LeastActiveLoadBalance";
/**
* Get instance.
*
* @return the instance
*/
public static LoadBalance getInstance() {
String config = ConfigurationFactory.getInstance().getConfig(LOAD_BALANCE_TYPE, DEFAULT_LOAD_BALANCE);
return EnhancedServiceLoader.load(LoadBalance.class, config);
}
}

View File

@@ -0,0 +1,38 @@
/*
* 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.discovery.loadbalance;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import io.seata.common.loader.LoadLevel;
import static io.seata.discovery.loadbalance.LoadBalanceFactory.RANDOM_LOAD_BALANCE;
/**
* The type Random load balance.
*
* @author yuoyao
*/
@LoadLevel(name = RANDOM_LOAD_BALANCE)
public class RandomLoadBalance extends AbstractLoadBalance {
@Override
protected <T> T doSelect(List<T> invokers, String xid) {
int length = invokers.size();
return invokers.get(ThreadLocalRandom.current().nextInt(length));
}
}

View File

@@ -0,0 +1,51 @@
/*
* 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.discovery.loadbalance;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import io.seata.common.loader.LoadLevel;
import static io.seata.discovery.loadbalance.LoadBalanceFactory.ROUND_ROBIN_LOAD_BALANCE;
/**
* The type Round robin load balance.
*
* @author slievrly
*/
@LoadLevel(name = ROUND_ROBIN_LOAD_BALANCE)
public class RoundRobinLoadBalance extends AbstractLoadBalance {
private final AtomicInteger sequence = new AtomicInteger();
@Override
protected <T> T doSelect(List<T> invokers, String xid) {
int length = invokers.size();
return invokers.get(getPositiveSequence() % length);
}
private int getPositiveSequence() {
for (; ; ) {
int current = sequence.get();
int next = current >= Integer.MAX_VALUE ? 0 : current + 1;
if (sequence.compareAndSet(current, next)) {
return current;
}
}
}
}

View File

@@ -0,0 +1,106 @@
/*
* 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.discovery.registry;
import io.seata.common.util.StringUtils;
import io.seata.config.ConfigChangeListener;
import io.seata.config.Configuration;
import io.seata.config.ConfigurationFactory;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
/**
* The type File registry service.
*
* @author slievrly
*/
public class FileRegistryServiceImpl implements RegistryService<ConfigChangeListener> {
private static volatile FileRegistryServiceImpl instance;
private static final Configuration CONFIG = ConfigurationFactory.getInstance();
private static final String POSTFIX_GROUPLIST = ".grouplist";
private static final String ENDPOINT_SPLIT_CHAR = ";";
private static final String IP_PORT_SPLIT_CHAR = ":";
private FileRegistryServiceImpl() {
}
/**
* Gets instance.
*
* @return the instance
*/
static FileRegistryServiceImpl getInstance() {
if (instance == null) {
synchronized (FileRegistryServiceImpl.class) {
if (instance == null) {
instance = new FileRegistryServiceImpl();
}
}
}
return instance;
}
@Override
public void register(InetSocketAddress address) throws Exception {
}
@Override
public void unregister(InetSocketAddress address) throws Exception {
}
@Override
public void subscribe(String cluster, ConfigChangeListener listener) throws Exception {
}
@Override
public void unsubscribe(String cluster, ConfigChangeListener listener) throws Exception {
}
@Override
public List<InetSocketAddress> lookup(String key) throws Exception {
String clusterName = getServiceGroup(key);
if (clusterName == null) {
return null;
}
String endpointStr = CONFIG.getConfig(
PREFIX_SERVICE_ROOT + CONFIG_SPLIT_CHAR + clusterName + POSTFIX_GROUPLIST);
if (StringUtils.isNullOrEmpty(endpointStr)) {
throw new IllegalArgumentException(clusterName + POSTFIX_GROUPLIST + " is required");
}
String[] endpoints = endpointStr.split(ENDPOINT_SPLIT_CHAR);
List<InetSocketAddress> inetSocketAddresses = new ArrayList<>();
for (String endpoint : endpoints) {
String[] ipAndPort = endpoint.split(IP_PORT_SPLIT_CHAR);
if (ipAndPort.length != 2) {
throw new IllegalArgumentException("endpoint format should like ip:port");
}
inetSocketAddresses.add(new InetSocketAddress(ipAndPort[0], Integer.parseInt(ipAndPort[1])));
}
return inetSocketAddresses;
}
@Override
public void close() throws Exception {
}
}

View File

@@ -0,0 +1,66 @@
/*
* 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.discovery.registry;
import java.util.Objects;
import io.seata.common.exception.NotSupportYetException;
import io.seata.common.loader.EnhancedServiceLoader;
import io.seata.config.ConfigurationFactory;
import io.seata.config.ConfigurationKeys;
/**
* The type Registry factory.
*
* @author slievrly
*/
public class RegistryFactory {
private static volatile RegistryService instance = null;
/**
* Gets instance.
*
* @return the instance
*/
public static RegistryService getInstance() {
if (instance == null) {
synchronized (RegistryFactory.class) {
if (instance == null) {
instance = buildRegistryService();
}
}
}
return instance;
}
private static RegistryService buildRegistryService() {
RegistryType registryType;
String registryTypeName = ConfigurationFactory.CURRENT_FILE_INSTANCE.getConfig(
ConfigurationKeys.FILE_ROOT_REGISTRY + ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR
+ ConfigurationKeys.FILE_ROOT_TYPE);
try {
registryType = RegistryType.getType(registryTypeName);
} catch (Exception exx) {
throw new NotSupportYetException("not support registry type: " + registryTypeName);
}
if (RegistryType.File == registryType) {
return FileRegistryServiceImpl.getInstance();
} else {
return EnhancedServiceLoader.load(RegistryProvider.class, Objects.requireNonNull(registryType).name()).provide();
}
}
}

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.discovery.registry;
/**
* the interface registry provider
* @author xingfudeshi@gmail.com
*/
public interface RegistryProvider {
/**
* provide a registry implementation instance
* @return RegistryService
*/
RegistryService provide();
}

View File

@@ -0,0 +1,111 @@
/*
* 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.discovery.registry;
import java.net.InetSocketAddress;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import io.seata.config.ConfigurationCache;
import io.seata.config.ConfigurationFactory;
/**
* The interface Registry service.
*
* @param <T> the type parameter
* @author slievrly
*/
public interface RegistryService<T> {
/**
* The constant PREFIX_SERVICE_MAPPING.
*/
String PREFIX_SERVICE_MAPPING = "vgroupMapping.";
/**
* The constant PREFIX_SERVICE_ROOT.
*/
String PREFIX_SERVICE_ROOT = "service";
/**
* The constant CONFIG_SPLIT_CHAR.
*/
String CONFIG_SPLIT_CHAR = ".";
Set<String> SERVICE_GROUP_NAME = new HashSet<>();
/**
* Register.
*
* @param address the address
* @throws Exception the exception
*/
void register(InetSocketAddress address) throws Exception;
/**
* Unregister.
*
* @param address the address
* @throws Exception the exception
*/
void unregister(InetSocketAddress address) throws Exception;
/**
* Subscribe.
*
* @param cluster the cluster
* @param listener the listener
* @throws Exception the exception
*/
void subscribe(String cluster, T listener) throws Exception;
/**
* Unsubscribe.
*
* @param cluster the cluster
* @param listener the listener
* @throws Exception the exception
*/
void unsubscribe(String cluster, T listener) throws Exception;
/**
* Lookup list.
*
* @param key the key
* @return the list
* @throws Exception the exception
*/
List<InetSocketAddress> lookup(String key) throws Exception;
/**
* Close.
* @throws Exception
*/
void close() throws Exception;
/**
* Get current service group name
*
* @param key service group
* @return the service group name
*/
default String getServiceGroup(String key) {
key = PREFIX_SERVICE_ROOT + CONFIG_SPLIT_CHAR + PREFIX_SERVICE_MAPPING + key;
if (!SERVICE_GROUP_NAME.contains(key)) {
ConfigurationCache.addConfigListener(key);
SERVICE_GROUP_NAME.add(key);
}
return ConfigurationFactory.getInstance().getConfig(key);
}
}

View File

@@ -0,0 +1,75 @@
/*
* 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.discovery.registry;
/**
* The enum Registry type.
*
* @author slievrly
*/
public enum RegistryType {
/**
* File registry type.
*/
File,
/**
* ZK registry type.
*/
ZK,
/**
* Redis registry type.
*/
Redis,
/**
* Nacos registry type.
*/
Nacos,
/**
* Eureka registry type.
*/
Eureka,
/**
* Consul registry type
*/
Consul,
/**
* Etcd3 registry type
*/
Etcd3,
/**
* Sofa registry type
*/
Sofa,
/**
* Custom registry type
*/
Custom;
/**
* Gets type.
*
* @param name the name
* @return the type
*/
public static RegistryType getType(String name) {
for (RegistryType registryType : RegistryType.values()) {
if (registryType.name().equalsIgnoreCase(name)) {
return registryType;
}
}
throw new IllegalArgumentException("not support registry type: " + name);
}
}

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.
#
#
# 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.
#
#
# 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.
#
io.seata.discovery.loadbalance.RoundRobinLoadBalance
io.seata.discovery.loadbalance.RandomLoadBalance
io.seata.discovery.loadbalance.ConsistentHashLoadBalance
io.seata.discovery.loadbalance.LeastActiveLoadBalance

View File

@@ -0,0 +1,45 @@
/*
* 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.discovery.loadbalance.ConsistentHashLoadBalance;
import io.seata.discovery.loadbalance.LoadBalanceFactory;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
/**
* @author Geng Zhang
*/
class ConfigurationFactoryTest {
@Test
void getInstance() {
Configuration configuration = ConfigurationFactory.getInstance();
// check singleton
Assertions.assertEquals(configuration.getClass().getName(), ConfigurationFactory.getInstance().getClass().getName());
}
@Test
void getLoadBalance() {
Configuration configuration = ConfigurationFactory.getInstance();
String loadBalanceType = configuration.getConfig(LoadBalanceFactory.LOAD_BALANCE_TYPE);
int visualNode = configuration.getInt(ConsistentHashLoadBalance.LOAD_BALANCE_CONSISTENT_HASH_VISUAL_NODES);
Assertions.assertEquals("RandomLoadBalance", loadBalanceType);
Assertions.assertEquals(10,visualNode);
}
}

View File

@@ -0,0 +1,130 @@
/*
* 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.discovery.loadbalance;
import io.seata.discovery.registry.RegistryFactory;
import io.seata.discovery.registry.RegistryService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
/**
* The type Load balance factory test.
*
* @author slievrly
*/
public class LoadBalanceFactoryTest {
private static final String XID = "XID";
/**
* Test get registry.
*
* @param loadBalance the load balance
* @throws Exception the exception
*/
@ParameterizedTest
@MethodSource("instanceProvider")
@Disabled
public void testGetRegistry(LoadBalance loadBalance) throws Exception {
Assertions.assertNotNull(loadBalance);
RegistryService registryService = RegistryFactory.getInstance();
InetSocketAddress address1 = new InetSocketAddress("127.0.0.1", 8091);
InetSocketAddress address2 = new InetSocketAddress("127.0.0.1", 8092);
registryService.register(address1);
registryService.register(address2);
List<InetSocketAddress> addressList = registryService.lookup("my_test_tx_group");
InetSocketAddress balanceAddress = loadBalance.select(addressList, XID);
Assertions.assertNotNull(balanceAddress);
}
/**
* Test get address.
*
* @param loadBalance the load balance
* @throws Exception the exception
*/
@ParameterizedTest
@MethodSource("instanceProvider")
@Disabled
public void testUnRegistry(LoadBalance loadBalance) throws Exception {
RegistryService registryService = RegistryFactory.getInstance();
InetSocketAddress address = new InetSocketAddress("127.0.0.1", 8091);
registryService.unregister(address);
}
/**
* Test subscribe.
*
* @param loadBalance the load balance
* @throws Exception the exception
*/
@ParameterizedTest
@MethodSource("instanceProvider")
@Disabled
public void testSubscribe(LoadBalance loadBalance) throws Exception {
Assertions.assertNotNull(loadBalance);
RegistryService registryService = RegistryFactory.getInstance();
InetSocketAddress address1 = new InetSocketAddress("127.0.0.1", 8091);
InetSocketAddress address2 = new InetSocketAddress("127.0.0.1", 8092);
registryService.register(address1);
registryService.register(address2);
List<InetSocketAddress> addressList = registryService.lookup("my_test_tx_group");
InetSocketAddress balanceAddress = loadBalance.select(addressList, XID);
Assertions.assertNotNull(balanceAddress);
//wait trigger testUnRegistry
TimeUnit.SECONDS.sleep(30);
List<InetSocketAddress> addressList1 = registryService.lookup("my_test_tx_group");
Assertions.assertEquals(1, addressList1.size());
}
/**
* Test get address.
*
* @param loadBalance the load balance
* @throws Exception the exception
*/
@ParameterizedTest
@MethodSource("instanceProvider")
public void testGetAddress(LoadBalance loadBalance) throws Exception {
Assertions.assertNotNull(loadBalance);
InetSocketAddress address = new InetSocketAddress("127.0.0.1", 8091);
List<InetSocketAddress> addressList = new ArrayList<>();
addressList.add(address);
InetSocketAddress balanceAddress = loadBalance.select(addressList, XID);
Assertions.assertEquals(address, balanceAddress);
}
/**
* Instance provider object [ ] [ ].
*
* @return the object [ ] [ ]
*/
static Stream<Arguments> instanceProvider() {
LoadBalance loadBalance = LoadBalanceFactory.getInstance();
return Stream.of(
Arguments.of(loadBalance)
);
}
}

View File

@@ -0,0 +1,162 @@
/*
* 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.discovery.loadbalance;
import io.seata.common.rpc.RpcStatus;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Stream;
/**
* Created by guoyao on 2019/2/14.
*/
public class LoadBalanceTest {
private static final String XID = "XID";
/**
* Test random load balance select.
*
* @param addresses the addresses
*/
@ParameterizedTest
@MethodSource("addressProvider")
public void testRandomLoadBalance_select(List<InetSocketAddress> addresses) {
int runs = 10000;
Map<InetSocketAddress, AtomicLong> counter = getSelectedCounter(runs, addresses, new RandomLoadBalance());
for (InetSocketAddress address : counter.keySet()) {
Long count = counter.get(address).get();
Assertions.assertTrue(count > 0, "selecte one time at last");
}
}
/**
* Test round robin load balance select.
*
* @param addresses the addresses
*/
@ParameterizedTest
@MethodSource("addressProvider")
public void testRoundRobinLoadBalance_select(List<InetSocketAddress> addresses) {
int runs = 10000;
Map<InetSocketAddress, AtomicLong> counter = getSelectedCounter(runs, addresses, new RoundRobinLoadBalance());
for (InetSocketAddress address : counter.keySet()) {
Long count = counter.get(address).get();
Assertions.assertTrue(Math.abs(count - runs / (0f + addresses.size())) < 1f, "abs diff shoud < 1");
}
}
/**
* Test consistent hash load load balance select.
*
* @param addresses the addresses
*/
@ParameterizedTest
@MethodSource("addressProvider")
public void testConsistentHashLoadBalance_select(List<InetSocketAddress> addresses) {
int runs = 10000;
int selected = 0;
ConsistentHashLoadBalance loadBalance = new ConsistentHashLoadBalance();
Map<InetSocketAddress, AtomicLong> counter = getSelectedCounter(runs, addresses, loadBalance);
for (InetSocketAddress address : counter.keySet()) {
if (counter.get(address).get() > 0) {
selected++;
}
}
Assertions.assertEquals(1, selected, "selected must be equal to 1");
}
/**
* Test least active load balance select.
*
* @param addresses the addresses
*/
@ParameterizedTest
@MethodSource("addressProvider")
public void testLeastActiveLoadBalance_select(List<InetSocketAddress> addresses) throws Exception {
int runs = 10000;
int size = addresses.size();
for (int i = 0; i < size - 1; i++) {
RpcStatus.beginCount(addresses.get(i).toString());
}
InetSocketAddress socketAddress = addresses.get(size - 1);
LoadBalance loadBalance = new LeastActiveLoadBalance();
for (int i = 0; i < runs; i++) {
InetSocketAddress selectAddress = loadBalance.select(addresses, XID);
Assertions.assertEquals(selectAddress, socketAddress);
}
RpcStatus.beginCount(socketAddress.toString());
RpcStatus.beginCount(socketAddress.toString());
Map<InetSocketAddress, AtomicLong> counter = getSelectedCounter(runs, addresses, loadBalance);
for (InetSocketAddress address : counter.keySet()) {
Long count = counter.get(address).get();
if (address == socketAddress) {
Assertions.assertEquals(count, 0);
} else {
Assertions.assertTrue(count > 0);
}
}
}
/**
* Gets selected counter.
*
* @param runs the runs
* @param addresses the addresses
* @param loadBalance the load balance
* @return the selected counter
*/
public Map<InetSocketAddress, AtomicLong> getSelectedCounter(int runs, List<InetSocketAddress> addresses,
LoadBalance loadBalance) {
Assertions.assertNotNull(loadBalance);
Map<InetSocketAddress, AtomicLong> counter = new ConcurrentHashMap<>();
for (InetSocketAddress address : addresses) {
counter.put(address, new AtomicLong(0));
}
try {
for (int i = 0; i < runs; i++) {
InetSocketAddress selectAddress = loadBalance.select(addresses, XID);
counter.get(selectAddress).incrementAndGet();
}
} catch (Exception e) {
//do nothing
}
return counter;
}
/**
* Address provider object [ ] [ ].
*
* @return Stream<List < InetSocketAddress>>
*/
static Stream<List<InetSocketAddress>> addressProvider() {
return Stream.of(
Arrays.asList(new InetSocketAddress("127.0.0.1", 8091),
new InetSocketAddress("127.0.0.1", 8092),
new InetSocketAddress("127.0.0.1", 8093),
new InetSocketAddress("127.0.0.1", 8094),
new InetSocketAddress("127.0.0.1", 8095))
);
}
}

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.
#
#apollo config
registry.redis.serverAddr = 192.168.1.204:6379
registry.redis.db = 6
registry.redis.max.active = 16
service.vgroupMapping.my_test_tx_group = default

View File

@@ -0,0 +1,23 @@
#
# 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.
#
#loadBalance config
client {
loadBalance {
type = "RandomLoadBalance"
visualNodes = 10
}
}