chore(project): 添加项目配置文件和忽略规则
- 添加 Babel 配置文件支持 ES6+ 语法转换 - 添加 ESLint 忽略规则和配置文件 - 添加 Git 忽略规则文件 - 添加 Travis CI 配置文件 - 添加 1.4.2 版本变更日志文件 - 添加 Helm 图表辅助模板文件 - 添加 Helm 忽略规则文件
This commit is contained in:
44
discovery/seata-discovery-zk/pom.xml
Normal file
44
discovery/seata-discovery-zk/pom.xml
Normal file
@@ -0,0 +1,44 @@
|
||||
<?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-zk</artifactId>
|
||||
<name>seata-discovery-zk ${project.version}</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.seata</groupId>
|
||||
<artifactId>seata-discovery-core</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.101tec</groupId>
|
||||
<artifactId>zkclient</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.curator</groupId>
|
||||
<artifactId>curator-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* 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.zk;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import io.seata.common.util.CollectionUtils;
|
||||
import io.seata.common.util.NetUtil;
|
||||
import io.seata.common.util.StringUtils;
|
||||
import io.seata.config.Configuration;
|
||||
import io.seata.config.ConfigurationFactory;
|
||||
import io.seata.discovery.registry.RegistryService;
|
||||
import org.I0Itec.zkclient.IZkChildListener;
|
||||
import org.I0Itec.zkclient.IZkStateListener;
|
||||
import org.I0Itec.zkclient.ZkClient;
|
||||
import org.apache.zookeeper.Watcher;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static io.seata.common.Constants.IP_PORT_SPLIT_CHAR;
|
||||
|
||||
/**
|
||||
* zookeeper path as /registry/zk/
|
||||
*
|
||||
* @author crazier.huang
|
||||
*/
|
||||
public class ZookeeperRegisterServiceImpl implements RegistryService<IZkChildListener> {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ZookeeperRegisterServiceImpl.class);
|
||||
|
||||
private static volatile ZookeeperRegisterServiceImpl instance;
|
||||
private static volatile ZkClient zkClient;
|
||||
private static final Configuration FILE_CONFIG = ConfigurationFactory.CURRENT_FILE_INSTANCE;
|
||||
private static final String ZK_PATH_SPLIT_CHAR = "/";
|
||||
private static final String FILE_ROOT_REGISTRY = "registry";
|
||||
private static final String FILE_CONFIG_SPLIT_CHAR = ".";
|
||||
private static final String REGISTRY_CLUSTER = "cluster";
|
||||
private static final String REGISTRY_TYPE = "zk";
|
||||
private static final String SERVER_ADDR_KEY = "serverAddr";
|
||||
private static final String AUTH_USERNAME = "username";
|
||||
private static final String AUTH_PASSWORD = "password";
|
||||
private static final String SESSION_TIME_OUT_KEY = "sessionTimeout";
|
||||
private static final String CONNECT_TIME_OUT_KEY = "connectTimeout";
|
||||
private static final int DEFAULT_SESSION_TIMEOUT = 6000;
|
||||
private static final int DEFAULT_CONNECT_TIMEOUT = 2000;
|
||||
private static final String FILE_CONFIG_KEY_PREFIX = FILE_ROOT_REGISTRY + FILE_CONFIG_SPLIT_CHAR + REGISTRY_TYPE
|
||||
+ FILE_CONFIG_SPLIT_CHAR;
|
||||
private static final String ROOT_PATH = ZK_PATH_SPLIT_CHAR + FILE_ROOT_REGISTRY + ZK_PATH_SPLIT_CHAR + REGISTRY_TYPE
|
||||
+ ZK_PATH_SPLIT_CHAR;
|
||||
private static final String ROOT_PATH_WITHOUT_SUFFIX = ZK_PATH_SPLIT_CHAR + FILE_ROOT_REGISTRY + ZK_PATH_SPLIT_CHAR
|
||||
+ REGISTRY_TYPE;
|
||||
private static final ConcurrentMap<String, List<InetSocketAddress>> CLUSTER_ADDRESS_MAP = new ConcurrentHashMap<>();
|
||||
private static final ConcurrentMap<String, List<IZkChildListener>> LISTENER_SERVICE_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
private static final int REGISTERED_PATH_SET_SIZE = 1;
|
||||
private static final Set<String> REGISTERED_PATH_SET = Collections.synchronizedSet(new HashSet<>(REGISTERED_PATH_SET_SIZE));
|
||||
|
||||
private ZookeeperRegisterServiceImpl() {
|
||||
}
|
||||
|
||||
static ZookeeperRegisterServiceImpl getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (ZookeeperRegisterServiceImpl.class) {
|
||||
if (instance == null) {
|
||||
instance = new ZookeeperRegisterServiceImpl();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(InetSocketAddress address) throws Exception {
|
||||
NetUtil.validAddress(address);
|
||||
|
||||
String path = getRegisterPathByPath(address);
|
||||
doRegister(path);
|
||||
}
|
||||
|
||||
private boolean doRegister(String path) {
|
||||
if (checkExists(path)) {
|
||||
return false;
|
||||
}
|
||||
createParentIfNotPresent(path);
|
||||
getClientInstance().createEphemeral(path, true);
|
||||
REGISTERED_PATH_SET.add(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void createParentIfNotPresent(String path) {
|
||||
int i = path.lastIndexOf('/');
|
||||
if (i > 0) {
|
||||
String parent = path.substring(0, i);
|
||||
if (!checkExists(parent)) {
|
||||
getClientInstance().createPersistent(parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkExists(String path) {
|
||||
return getClientInstance().exists(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister(InetSocketAddress address) throws Exception {
|
||||
NetUtil.validAddress(address);
|
||||
|
||||
String path = getRegisterPathByPath(address);
|
||||
getClientInstance().delete(path);
|
||||
REGISTERED_PATH_SET.remove(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe(String cluster, IZkChildListener listener) throws Exception {
|
||||
if (cluster == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String path = ROOT_PATH + cluster;
|
||||
if (!getClientInstance().exists(path)) {
|
||||
getClientInstance().createPersistent(path);
|
||||
}
|
||||
getClientInstance().subscribeChildChanges(path, listener);
|
||||
LISTENER_SERVICE_MAP.computeIfAbsent(cluster, key -> new CopyOnWriteArrayList<>())
|
||||
.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsubscribe(String cluster, IZkChildListener listener) throws Exception {
|
||||
if (cluster == null) {
|
||||
return;
|
||||
}
|
||||
String path = ROOT_PATH + cluster;
|
||||
if (getClientInstance().exists(path)) {
|
||||
getClientInstance().unsubscribeChildChanges(path, listener);
|
||||
|
||||
List<IZkChildListener> subscribeList = LISTENER_SERVICE_MAP.get(cluster);
|
||||
if (subscribeList != null) {
|
||||
List<IZkChildListener> newSubscribeList = subscribeList.stream()
|
||||
.filter(eventListener -> !eventListener.equals(listener))
|
||||
.collect(Collectors.toList());
|
||||
LISTENER_SERVICE_MAP.put(cluster, newSubscribeList);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key the key
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public List<InetSocketAddress> lookup(String key) throws Exception {
|
||||
String clusterName = getServiceGroup(key);
|
||||
|
||||
if (clusterName == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return doLookup(clusterName);
|
||||
}
|
||||
|
||||
// visible for test.
|
||||
List<InetSocketAddress> doLookup(String clusterName) throws Exception {
|
||||
boolean exist = getClientInstance().exists(ROOT_PATH + clusterName);
|
||||
if (!exist) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!LISTENER_SERVICE_MAP.containsKey(clusterName)) {
|
||||
List<String> childClusterPath = getClientInstance().getChildren(ROOT_PATH + clusterName);
|
||||
refreshClusterAddressMap(clusterName, childClusterPath);
|
||||
subscribeCluster(clusterName);
|
||||
}
|
||||
|
||||
return CLUSTER_ADDRESS_MAP.get(clusterName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
getClientInstance().close();
|
||||
}
|
||||
|
||||
private ZkClient getClientInstance() {
|
||||
if (zkClient == null) {
|
||||
synchronized (ZookeeperRegisterServiceImpl.class) {
|
||||
if (zkClient == null) {
|
||||
zkClient = buildZkClient(FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + SERVER_ADDR_KEY),
|
||||
FILE_CONFIG.getInt(FILE_CONFIG_KEY_PREFIX + SESSION_TIME_OUT_KEY, DEFAULT_SESSION_TIMEOUT),
|
||||
FILE_CONFIG.getInt(FILE_CONFIG_KEY_PREFIX + CONNECT_TIME_OUT_KEY, DEFAULT_CONNECT_TIMEOUT),
|
||||
FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + AUTH_USERNAME),
|
||||
FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + AUTH_PASSWORD));
|
||||
}
|
||||
}
|
||||
}
|
||||
return zkClient;
|
||||
}
|
||||
|
||||
// visible for test.
|
||||
ZkClient buildZkClient(String address, int sessionTimeout, int connectTimeout,String... authInfo) {
|
||||
ZkClient zkClient = new ZkClient(address, sessionTimeout, connectTimeout);
|
||||
if (authInfo != null && authInfo.length == 2) {
|
||||
if (!StringUtils.isBlank(authInfo[0]) && !StringUtils.isBlank(authInfo[1])) {
|
||||
StringBuilder auth = new StringBuilder(authInfo[0]).append(":").append(authInfo[1]);
|
||||
zkClient.addAuthInfo("digest", auth.toString().getBytes());
|
||||
}
|
||||
}
|
||||
if (!zkClient.exists(ROOT_PATH_WITHOUT_SUFFIX)) {
|
||||
zkClient.createPersistent(ROOT_PATH_WITHOUT_SUFFIX, true);
|
||||
}
|
||||
zkClient.subscribeStateChanges(new IZkStateListener() {
|
||||
|
||||
@Override
|
||||
public void handleStateChanged(Watcher.Event.KeeperState keeperState) throws Exception {
|
||||
//ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleNewSession() throws Exception {
|
||||
recover();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSessionEstablishmentError(Throwable throwable) throws Exception {
|
||||
//ignore
|
||||
}
|
||||
});
|
||||
return zkClient;
|
||||
}
|
||||
|
||||
private void recover() throws Exception {
|
||||
// recover Server
|
||||
if (!REGISTERED_PATH_SET.isEmpty()) {
|
||||
REGISTERED_PATH_SET.forEach(this::doRegister);
|
||||
}
|
||||
// recover client
|
||||
if (!LISTENER_SERVICE_MAP.isEmpty()) {
|
||||
Map<String, List<IZkChildListener>> listenerMap = new HashMap<>(LISTENER_SERVICE_MAP);
|
||||
LISTENER_SERVICE_MAP.clear();
|
||||
for (Map.Entry<String, List<IZkChildListener>> listenerEntry : listenerMap.entrySet()) {
|
||||
List<IZkChildListener> iZkChildListeners = listenerEntry.getValue();
|
||||
if (CollectionUtils.isEmpty(iZkChildListeners)) {
|
||||
continue;
|
||||
}
|
||||
for (IZkChildListener listener : iZkChildListeners) {
|
||||
subscribe(listenerEntry.getKey(), listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void subscribeCluster(String cluster) throws Exception {
|
||||
subscribe(cluster, (parentPath, currentChilds) -> {
|
||||
String clusterName = parentPath.replace(ROOT_PATH, "");
|
||||
if (CollectionUtils.isEmpty(currentChilds) && CLUSTER_ADDRESS_MAP.get(clusterName) != null) {
|
||||
CLUSTER_ADDRESS_MAP.remove(clusterName);
|
||||
} else if (!CollectionUtils.isEmpty(currentChilds)) {
|
||||
refreshClusterAddressMap(clusterName, currentChilds);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void refreshClusterAddressMap(String clusterName, List<String> instances) {
|
||||
List<InetSocketAddress> newAddressList = new ArrayList<>();
|
||||
if (instances == null) {
|
||||
CLUSTER_ADDRESS_MAP.put(clusterName, newAddressList);
|
||||
return;
|
||||
}
|
||||
for (String path : instances) {
|
||||
try {
|
||||
String[] ipAndPort = path.split(IP_PORT_SPLIT_CHAR);
|
||||
newAddressList.add(new InetSocketAddress(ipAndPort[0], Integer.parseInt(ipAndPort[1])));
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("The cluster instance info is error, instance info:{}", path);
|
||||
}
|
||||
}
|
||||
CLUSTER_ADDRESS_MAP.put(clusterName, newAddressList);
|
||||
}
|
||||
|
||||
private String getClusterName() {
|
||||
String clusterConfigName = String.join(FILE_CONFIG_SPLIT_CHAR, FILE_ROOT_REGISTRY, REGISTRY_TYPE, REGISTRY_CLUSTER);
|
||||
return FILE_CONFIG.getConfig(clusterConfigName);
|
||||
}
|
||||
|
||||
private String getRegisterPathByPath(InetSocketAddress address) {
|
||||
return ROOT_PATH + getClusterName() + ZK_PATH_SPLIT_CHAR + NetUtil.toStringAddress(address);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.zk;
|
||||
|
||||
import io.seata.common.loader.LoadLevel;
|
||||
import io.seata.discovery.registry.RegistryProvider;
|
||||
import io.seata.discovery.registry.RegistryService;
|
||||
|
||||
/**
|
||||
* @author xingfudeshi@gmail.com
|
||||
*/
|
||||
@LoadLevel(name = "ZK", order = 1)
|
||||
public class ZookeeperRegistryProvider implements RegistryProvider {
|
||||
@Override
|
||||
public RegistryService provide() {
|
||||
return ZookeeperRegisterServiceImpl.getInstance();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
io.seata.discovery.registry.zk.ZookeeperRegistryProvider
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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.zk;
|
||||
|
||||
import io.seata.common.util.NetUtil;
|
||||
import org.I0Itec.zkclient.IZkChildListener;
|
||||
import org.I0Itec.zkclient.ZkClient;
|
||||
import org.apache.curator.test.TestingServer;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author Geng Zhang
|
||||
*/
|
||||
public class ZookeeperRegisterServiceImplTest {
|
||||
protected static TestingServer server = null;
|
||||
|
||||
@BeforeAll
|
||||
public static void adBeforeClass() throws Exception {
|
||||
server = new TestingServer(2181, true);
|
||||
server.start();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void adAfterClass() throws Exception {
|
||||
if (server != null) {
|
||||
server.stop();
|
||||
}
|
||||
}
|
||||
|
||||
ZookeeperRegisterServiceImpl service = (ZookeeperRegisterServiceImpl) new ZookeeperRegistryProvider().provide();
|
||||
|
||||
@Test
|
||||
public void getInstance() {
|
||||
ZookeeperRegisterServiceImpl service1 = ZookeeperRegisterServiceImpl.getInstance();
|
||||
Assertions.assertEquals(service1, service);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildZkTest() {
|
||||
ZkClient client = service.buildZkClient("127.0.0.1:2181", 5000, 5000);
|
||||
Assertions.assertTrue(client.exists("/zookeeper"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAll() throws Exception {
|
||||
service.register(new InetSocketAddress(NetUtil.getLocalAddress(), 33333));
|
||||
|
||||
Assertions.assertNull(service.lookup("xxx"));
|
||||
List<InetSocketAddress> lookup2 = service.doLookup("default");
|
||||
Assertions.assertEquals(1, lookup2.size());
|
||||
|
||||
final List<String> data = new ArrayList<>();
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
IZkChildListener listener = (s, list) -> {
|
||||
data.clear();
|
||||
data.addAll(list);
|
||||
latch.countDown();
|
||||
};
|
||||
service.subscribe("default", listener);
|
||||
final CountDownLatch latch2 = new CountDownLatch(1);
|
||||
final List<String> data2 = new ArrayList<>();
|
||||
IZkChildListener listener2 = (s, list) -> {
|
||||
data2.clear();
|
||||
data2.addAll(list);
|
||||
latch2.countDown();
|
||||
};
|
||||
service.subscribe("default", listener2);
|
||||
|
||||
service.unregister(new InetSocketAddress(NetUtil.getLocalAddress(), 33333));
|
||||
latch2.await(1000, TimeUnit.MILLISECONDS);
|
||||
Assertions.assertEquals(0, data2.size());
|
||||
|
||||
service.unsubscribe("default", listener);
|
||||
service.unsubscribe("default", listener2);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.zk;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* @author Geng Zhang
|
||||
*/
|
||||
public class ZookeeperRegistryProviderTest {
|
||||
|
||||
@Test
|
||||
public void provide() {
|
||||
ZookeeperRegistryProvider provider = new ZookeeperRegistryProvider();
|
||||
Assertions.assertTrue(provider.provide() instanceof ZookeeperRegisterServiceImpl);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user