提交 c690f89d authored 作者: 陈世营's avatar 陈世营

leaf zookeeper分布式ID

上级 b74f828d
......@@ -35,14 +35,18 @@
<tomcat-embed-core.version>8.5.34</tomcat-embed-core.version>
<jacoco.version>0.8.3</jacoco.version>
<curator.version>2.10.0</curator.version>
<junit.version>4.12</junit.version>
<maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
<shardingsphere.version>5.0.0-RC1-SNAPSHOT</shardingsphere.version>
<shardingsphere.spi.impl.version>5.0.0-RC1-SNAPSHOT</shardingsphere.spi.impl.version>
<maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
<lombok.version>1.18.8</lombok.version>
<leaf-core.version>1.0.1</leaf-core.version>
</properties>
<dependencyManagement>
......@@ -223,8 +227,45 @@
<artifactId>sharding-orchestration-reg-etcd</artifactId>
<version>${shardingsphere.spi.impl.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!--shardingsphere end-->
<!--zookeeper begin-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>${curator.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
<version>${curator.version}</version>
<exclusions>
<exclusion>
<artifactId>netty</artifactId>
<groupId>io.netty</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>${curator.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-test</artifactId>
<version>${curator.version}</version>
<scope>test</scope>
</dependency>
<!--zookeeper end-->
</dependencies>
</dependencyManagement>
......@@ -271,8 +312,8 @@
</plugin>
</plugins>
</build>
<distributionManagement>
<distributionManagement>
<repository>
<id>nexus-releases</id>
<name>Nexus Release Repository</name>
......
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>loit-build-component</artifactId>
<groupId>com.timeloit.project</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>loit-keygen-leaf-zk</artifactId>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-test</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.loit.component.keygen.leaf;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.loit.component.keygen.leaf.core.reg.RegistryCenter;
import com.loit.component.keygen.leaf.core.reg.RegistryCenterConfiguration;
import com.loit.component.keygen.leaf.core.reg.RegistryCenterServiceLoader;
import com.loit.component.keygen.leaf.keygen.LeafKeyGenerator;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.SynchronousQueue;
/**
* Key generator implemented by leaf segment algorithms.
*
* @author wangguangyuan
*/
public final class LeafSegmentLeafKeyGenerator implements LeafKeyGenerator {
private static final String DEFAULT_NAMESPACE = "leaf_segment";
private static final String DEFAULT_STEP = "10000";
private static final String DEFAULT_INITIAL_VALUE = "1";
private static final String DEFAULT_REGISTRY_CENTER = "zookeeper";
private static final String SLANTING_BAR = "/";
private static final String REGULAR_PATTERN = "^((?!/).)*$";
private final ExecutorService incrementCacheIdExecutor;
private final SynchronousQueue<Long> cacheIdQueue;
private RegistryCenter leafRegistryCenter;
private long id;
private long step;
@Getter
@Setter
private Properties properties = new Properties();
public LeafSegmentLeafKeyGenerator() {
incrementCacheIdExecutor = Executors.newSingleThreadExecutor();
cacheIdQueue = new SynchronousQueue<>();
}
@Override
public String getType() {
return "LEAF_SEGMENT";
}
@Override
public synchronized Comparable<?> generateKey() {
String leafKey = getLeafKey();
if (null == leafRegistryCenter) {
initLeafSegmentKeyGenerator(leafKey);
} else {
increaseIdWhenLeafKeyStoredInCenter(leafKey);
}
return id;
}
private void initLeafSegmentKeyGenerator(final String leafKey) {
RegistryCenterConfiguration leafConfiguration = getRegistryCenterConfiguration();
leafRegistryCenter = new RegistryCenterServiceLoader().load(leafConfiguration);
step = getStep();
id = initializeId(leafKey);
initializeLeafKeyInCenter(leafKey, id, step);
initializeCacheIdAsynchronous(id, step);
}
private void increaseIdWhenLeafKeyStoredInCenter(final String leafKey) {
if ((id % step) == 0) {
id = tryTakeCacheId();
incrementCacheIdAsynchronous(leafKey, step - (id % step));
}
++id;
}
private long initializeId(final String leafKey) {
if (leafRegistryCenter.isExisted(leafKey)) {
return Long.parseLong(leafRegistryCenter.getDirectly(leafKey)) + 1;
} else {
return getInitialValue();
}
}
private void initializeLeafKeyInCenter(final String leafKey, final long id, final long step) {
leafRegistryCenter.initLock(leafKey);
while (!leafRegistryCenter.tryLock()) {
continue;
}
leafRegistryCenter.persist(leafKey, String.valueOf(id + step - id % step));
leafRegistryCenter.tryRelease();
}
private void initializeCacheIdAsynchronous(final long id, final long step) {
incrementCacheIdExecutor.execute(new Runnable() {
@Override
public void run() {
tryPutCacheId(id + step - id % step);
}
});
}
private void incrementCacheIdAsynchronous(final String leafKey, final long step) {
incrementCacheIdExecutor.execute(new Runnable() {
@Override
public void run() {
long newId = incrementCacheId(leafKey, step);
tryPutCacheId(newId);
}
});
}
private RegistryCenterConfiguration getRegistryCenterConfiguration() {
RegistryCenterConfiguration result = new RegistryCenterConfiguration(getRegistryCenterType(), properties);
result.setNamespace(DEFAULT_NAMESPACE);
result.setServerLists(getServerList());
result.setDigest(getDigest());
return result;
}
@SneakyThrows
private long incrementCacheId(final String leafKey, final long step) {
while (!leafRegistryCenter.tryLock()) {
continue;
}
long result = updateCacheIdInCenter(leafKey, step);
leafRegistryCenter.tryRelease();
return result;
}
private long updateCacheIdInCenter(final String leafKey, final long step) {
String cacheIdInString = leafRegistryCenter.getDirectly(leafKey);
if (Strings.isNullOrEmpty(cacheIdInString)) {
return Long.MIN_VALUE;
}
long cacheId = Long.parseLong(cacheIdInString);
long result = cacheId + step;
leafRegistryCenter.update(leafKey, String.valueOf(result));
return result;
}
@SneakyThrows
private void tryPutCacheId(final long id) {
cacheIdQueue.put(id);
}
@SneakyThrows
private long tryTakeCacheId() {
return cacheIdQueue.take();
}
private long getStep() {
long result = Long.parseLong(properties.getProperty("step", DEFAULT_STEP));
Preconditions.checkArgument(result > 0L && result < Long.MAX_VALUE);
return result;
}
private long getInitialValue() {
long result = Long.parseLong(properties.getProperty("initialValue", DEFAULT_INITIAL_VALUE));
Preconditions.checkArgument(result >= 0L && result < Long.MAX_VALUE);
return result;
}
private String getLeafKey() {
String leafKey = properties.getProperty("leafKey");
Preconditions.checkArgument(!Strings.isNullOrEmpty(leafKey));
Preconditions.checkArgument(leafKey.matches(REGULAR_PATTERN));
return SLANTING_BAR + leafKey;
}
private String getServerList() {
String result = properties.getProperty("serverList");
Preconditions.checkArgument(!Strings.isNullOrEmpty(result));
return result;
}
private String getDigest() {
return properties.getProperty("digest");
}
private String getRegistryCenterType() {
return properties.getProperty("registryCenterType", DEFAULT_REGISTRY_CENTER);
}
}
package com.loit.component.keygen.leaf.core;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import java.util.*;
/**
* SPI service loader for new instance for every call.
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class NewInstanceServiceLoader {
private static final Map<Class, Collection<Class<?>>> SERVICE_MAP = new HashMap<>();
/**
* Register SPI service into map for new instance.
*
* @param service service type
* @param <T> type of service
*/
public static <T> void register(final Class<T> service) {
for (T each : ServiceLoader.load(service)) {
registerServiceClass(service, each);
}
}
@SuppressWarnings("unchecked")
private static <T> void registerServiceClass(final Class<T> service, final T instance) {
Collection<Class<?>> serviceClasses = SERVICE_MAP.get(service);
if (null == serviceClasses) {
serviceClasses = new LinkedHashSet<>();
}
serviceClasses.add(instance.getClass());
SERVICE_MAP.put(service, serviceClasses);
}
/**
* New service instances.
*
* @param service service class
* @param <T> type of service
* @return service instances
*/
@SneakyThrows
@SuppressWarnings("unchecked")
public static <T> Collection<T> newServiceInstances(final Class<T> service) {
Collection<T> result = new LinkedList<>();
if (null == SERVICE_MAP.get(service)) {
return result;
}
for (Class<?> each : SERVICE_MAP.get(service)) {
result.add((T) each.newInstance());
}
return result;
}
}
package com.loit.component.keygen.leaf.core.exception;
/**
* Sharding rule exception.
*
*/
public final class LeafConfigurationException extends RuntimeException {
private static final long serialVersionUID = -1360264079938958332L;
/**
* Constructs an exception with formatted error message and arguments.
*
* @param errorMessage formatted error message
* @param args arguments of error message
*/
public LeafConfigurationException(final String errorMessage, final Object... args) {
super(String.format(errorMessage, args));
}
/**
* Constructs an exception with cause exception.
*
* @param cause cause exception
*/
public LeafConfigurationException(final Exception cause) {
super(cause);
}
}
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.loit.component.keygen.leaf.core.exception;
/**
* Registry center exception.
*
* @author zhangliang
*/
public final class RegistryCenterException extends RuntimeException {
private static final long serialVersionUID = -6417179023552012152L;
public RegistryCenterException(final String errorMessage, final Object... args) {
super(String.format(errorMessage, args));
}
public RegistryCenterException(final Exception cause) {
super(cause);
}
}
package com.loit.component.keygen.leaf.core.listener;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* Data changed event.
*
*/
@RequiredArgsConstructor
@Getter
public final class DataChangedEvent {
private final String key;
private final String value;
private final ChangedType changedType;
/**
* Data changed type.
*/
public enum ChangedType {
UPDATED, DELETED, IGNORED
}
}
package com.loit.component.keygen.leaf.core.listener;
/**
* Listener for data changed event.
*
* @author junxiong
*/
public interface DataChangedEventListener {
/**
* Fire when data changed.
*
* @param dataChangedEvent data changed event
*/
void onChange(DataChangedEvent dataChangedEvent);
}
package com.loit.component.keygen.leaf.core.reg;
import com.loit.component.keygen.leaf.core.listener.DataChangedEventListener;
import com.loit.component.keygen.leaf.core.spi.TypeBasedSPI;
import java.util.List;
/**
* Registry center.
*/
public interface RegistryCenter extends TypeBasedSPI {
/**
* Initialize registry center.
*
* @param config registry center configuration
*/
void init(RegistryCenterConfiguration config);
/**
* Get data from registry center.
*
* <p>Maybe use cache if existed.</p>
*
* @param key key of data
* @return value of data
*/
String get(String key);
/**
* Get data from registry center directly.
*
* <p>Cannot use cache.</p>
*
* @param key key of data
* @return value of data
*/
String getDirectly(String key);
/**
* Judge data is existed or not.
*
* @param key key of data
* @return data is existed or not
*/
boolean isExisted(String key);
/**
* Get node's sub-nodes list.
*
* @param key key of data
* @return sub-nodes name list
*/
List<String> getChildrenKeys(String key);
/**
* Persist data.
*
* @param key key of data
* @param value value of data
*/
void persist(String key, String value);
/**
* Update data.
*
* @param key key of data
* @param value value of data
*/
void update(String key, String value);
/**
* Persist ephemeral data.
*
* @param key key of data
* @param value value of data
*/
void persistEphemeral(String key, String value);
/**
* Watch key or path of the registry.
*
* @param key key of data
* @param dataChangedEventListener data changed event listener
*/
void watch(String key, DataChangedEventListener dataChangedEventListener);
/**
* Close.
*/
void close();
/**
* Initialize the lock of the key.
*
* @param key key of data
*/
void initLock(String key);
/**
* Try to get the lock of the key.
*
* @return get the lock or not
*/
boolean tryLock();
/**
* Try to release the lock of the key.
*
*/
void tryRelease();
}
package com.loit.component.keygen.leaf.core.reg;
import com.loit.component.keygen.leaf.core.spi.TypeBasedSPIConfiguration;
import lombok.Getter;
import lombok.Setter;
import java.util.Properties;
/**
* Registry center configuration.
*/
@Getter
@Setter
public final class RegistryCenterConfiguration extends TypeBasedSPIConfiguration {
/**
* Server list of registry center.
*/
private String serverLists;
/**
* Namespace of registry center.
*/
private String namespace;
/**
* Digest of registry center.
*/
private String digest;
/**
* Operation timeout time in milliseconds.
*/
private int operationTimeoutMilliseconds = 500;
/**
* Max number of times to retry.
*/
private int maxRetries = 3;
/**
* Time interval in milliseconds on each retry.
*/
private int retryIntervalMilliseconds = 500;
/**
* Time to live in seconds of ephemeral keys.
*/
private int timeToLiveSeconds = 60;
public RegistryCenterConfiguration(final String type) {
super(type);
}
public RegistryCenterConfiguration(final String type, final Properties properties) {
super(type, properties);
}
}
package com.loit.component.keygen.leaf.core.reg;
import com.google.common.base.Preconditions;
import com.loit.component.keygen.leaf.core.NewInstanceServiceLoader;
import com.loit.component.keygen.leaf.core.spi.TypeBasedSPIServiceLoader;
/**
* Registry center loader from SPI.
*/
public final class RegistryCenterServiceLoader extends TypeBasedSPIServiceLoader<RegistryCenter> {
static {
NewInstanceServiceLoader.register(RegistryCenter.class);
}
public RegistryCenterServiceLoader() {
super(RegistryCenter.class);
}
/**
* Load registry center from SPI.
*
* @param regCenterConfig registry center configuration
* @return registry center
*/
public RegistryCenter load(final RegistryCenterConfiguration regCenterConfig) {
Preconditions.checkNotNull(regCenterConfig, "Registry center configuration cannot be null.");
RegistryCenter result = newService(regCenterConfig.getType(), regCenterConfig.getProperties());
result.init(regCenterConfig);
return result;
}
}
package com.loit.component.keygen.leaf.core.spi;
import java.util.Properties;
/**
* Base algorithm SPI.
*/
public interface TypeBasedSPI {
/**
* Get algorithm type.
*
* @return type
*/
String getType();
/**
* Get properties.
*
* @return properties of algorithm
*/
Properties getProperties();
/**
* Set properties.
*
* @param properties properties of algorithm
*/
void setProperties(Properties properties);
}
package com.loit.component.keygen.leaf.core.spi;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import lombok.Getter;
import java.util.Properties;
/**
* Type based SPI configuration.
*
* @author zhangliang
*/
@Getter
public abstract class TypeBasedSPIConfiguration {
private final String type;
private final Properties properties;
public TypeBasedSPIConfiguration(final String type) {
this(type, null);
}
public TypeBasedSPIConfiguration(final String type, final Properties properties) {
Preconditions.checkArgument(!Strings.isNullOrEmpty(type), "Type is required.");
this.type = type;
this.properties = null == properties ? new Properties() : properties;
}
}
package com.loit.component.keygen.leaf.core.spi;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.loit.component.keygen.leaf.core.NewInstanceServiceLoader;
import com.loit.component.keygen.leaf.core.exception.LeafConfigurationException;
import lombok.RequiredArgsConstructor;
import java.util.Collection;
import java.util.Properties;
/**
* Type based SPI service loader.
*
* @param <T> type of algorithm class
*/
@RequiredArgsConstructor
public abstract class TypeBasedSPIServiceLoader<T extends TypeBasedSPI> {
private final Class<T> classType;
/**
* Create new instance for type based SPI.
*
* @param type SPI type
* @param props SPI properties
* @return SPI instance
*/
public final T newService(final String type, final Properties props) {
Collection<T> typeBasedServices = loadTypeBasedServices(type);
if (typeBasedServices.isEmpty()) {
throw new LeafConfigurationException("Invalid `%s` SPI type `%s`.", classType.getName(), type);
}
T result = typeBasedServices.iterator().next();
result.setProperties(props);
return result;
}
/**
* Create new service by default SPI type.
*
* @return type based SPI instance
*/
public final T newService() {
T result = loadFirstTypeBasedService();
result.setProperties(new Properties());
return result;
}
private Collection<T> loadTypeBasedServices(final String type) {
return Collections2.filter(NewInstanceServiceLoader.newServiceInstances(classType), new Predicate<T>() {
@Override
public boolean apply(final T input) {
return type.equalsIgnoreCase(input.getType());
}
});
}
private T loadFirstTypeBasedService() {
Collection<T> instances = NewInstanceServiceLoader.newServiceInstances(classType);
if (instances.isEmpty()) {
throw new LeafConfigurationException("Invalid `%s` SPI, no implementation class load from SPI.", classType.getName());
}
return instances.iterator().next();
}
}
package com.loit.component.keygen.leaf.keygen;
import com.loit.component.keygen.leaf.core.spi.TypeBasedSPI;
/**
* Key generator.
*
*/
public interface LeafKeyGenerator extends TypeBasedSPI {
/**
* Generate key.
*
* @return generated key
*/
Comparable<?> generateKey();
}
package com.loit.component.keygen.leaf.zk;
import com.loit.component.keygen.leaf.core.exception.RegistryCenterException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.KeeperException.ConnectionLossException;
import org.apache.zookeeper.KeeperException.NoNodeException;
import org.apache.zookeeper.KeeperException.NodeExistsException;
/**
* Curator zookeeper exception handler.
*
* @author zhangliang
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Slf4j
public final class CuratorZookeeperExceptionHandler {
/**
* Handle exception.
*
* <p>Ignore interrupt and connection invalid exception.</p>
*
* @param cause to be handled exception
*/
public static void handleException(final Exception cause) {
if (null == cause) {
return;
}
if (isIgnoredException(cause) || null != cause.getCause() && isIgnoredException(cause.getCause())) {
log.debug("Ignored exception for: {}", cause.getMessage());
} else if (cause instanceof InterruptedException) {
Thread.currentThread().interrupt();
} else {
throw new RegistryCenterException(cause);
}
}
private static boolean isIgnoredException(final Throwable cause) {
return cause instanceof ConnectionLossException || cause instanceof NoNodeException || cause instanceof NodeExistsException;
}
}
package com.loit.component.keygen.leaf.zk;
import com.loit.component.keygen.leaf.core.reg.RegistryCenter;
import com.loit.component.keygen.leaf.core.reg.RegistryCenterConfiguration;
import com.loit.component.keygen.leaf.zk.util.EmbedTestingServer;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.List;
import java.util.Properties;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
public class CuratorZookeeperRegistryCenterTest {
private static RegistryCenter curatorZookeeperRegistryCenter = new CuratorZookeeperRegistryCenter();
@BeforeClass
public static void init() {
EmbedTestingServer.start();
RegistryCenterConfiguration configuration = new RegistryCenterConfiguration(curatorZookeeperRegistryCenter.getType(), new Properties());
configuration.setServerLists("127.0.0.1:2181");
curatorZookeeperRegistryCenter.init(configuration);
}
@Test
public void assertPersist() {
curatorZookeeperRegistryCenter.persist("/test", "value1");
assertThat(curatorZookeeperRegistryCenter.get("/test"), is("value1"));
}
@Test
public void assertUpdate() {
curatorZookeeperRegistryCenter.persist("/test", "value2");
assertThat(curatorZookeeperRegistryCenter.get("/test"), is("value2"));
}
@Test
public void assertPersistEphemeral() {
curatorZookeeperRegistryCenter.persist("/test/ephemeral", "value3");
assertThat(curatorZookeeperRegistryCenter.get("/test/ephemeral"), is("value3"));
}
@Test
public void assertGetDirectly() {
curatorZookeeperRegistryCenter.persist("/test", "value4");
assertThat(curatorZookeeperRegistryCenter.getDirectly("/test"), is("value4"));
}
@Test
public void assertIsExisted() {
curatorZookeeperRegistryCenter.persist("/test/existed", "value5");
assertThat(curatorZookeeperRegistryCenter.isExisted("/test/existed"), is(true));
}
@Test
public void assertGetChildrenKeys() {
curatorZookeeperRegistryCenter.persist("/test/children/1", "value11");
curatorZookeeperRegistryCenter.persist("/test/children/2", "value12");
curatorZookeeperRegistryCenter.persist("/test/children/3", "value13");
List<String> childrenKeys = curatorZookeeperRegistryCenter.getChildrenKeys("/test/children");
assertThat(childrenKeys.size(), is(3));
}
@Test
public void assertLock() {
curatorZookeeperRegistryCenter.initLock("/test/lock1");
assertThat(curatorZookeeperRegistryCenter.tryLock(), is(true));
}
@Test
public void assertRelease() {
curatorZookeeperRegistryCenter.initLock("/test/lock2");
curatorZookeeperRegistryCenter.tryLock();
curatorZookeeperRegistryCenter.tryRelease();
}
@Test(expected = IllegalMonitorStateException.class)
public void assertReleaseWithoutLock() {
curatorZookeeperRegistryCenter.initLock("/test/lock3");
curatorZookeeperRegistryCenter.tryRelease();
}
}
package com.loit.component.keygen.leaf.zk;
import com.loit.component.keygen.leaf.core.listener.DataChangedEventListener;
import com.loit.component.keygen.leaf.core.reg.RegistryCenter;
import com.loit.component.keygen.leaf.core.reg.RegistryCenterConfiguration;
import lombok.Getter;
import lombok.Setter;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
public final class ThirdTestRegistryCenter implements RegistryCenter {
private final Map<String, String> keys = new HashMap<>();
@Getter
@Setter
private Properties properties = new Properties();
private ReentrantLock lock = new ReentrantLock();
@Override
public void init(final RegistryCenterConfiguration config) {
}
@Override
public String get(final String key) {
return "";
}
@Override
public String getDirectly(final String key) {
return keys.get(key);
}
@Override
public boolean isExisted(final String key) {
return keys.containsKey(key);
}
@Override
public List<String> getChildrenKeys(final String key) {
return Collections.emptyList();
}
@Override
public void persist(final String key, final String value) {
keys.put(key, value);
}
@Override
public void update(final String key, final String value) {
keys.put(key, value);
}
@Override
public void persistEphemeral(final String key, final String value) {
}
@Override
public void watch(final String key, final DataChangedEventListener dataChangedEventListener) {
}
@Override
public void close() {
}
@Override
public String getType() {
return "ThirdTestRegistryCenter";
}
@Override
public void initLock(final String key) {
lock = new ReentrantLock();
}
@Override
public boolean tryLock() {
return lock.tryLock();
}
@Override
public void tryRelease() {
lock.unlock();
}
}
package com.loit.component.keygen.leaf.zk.util;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.curator.test.TestingServer;
import org.apache.zookeeper.KeeperException;
import java.io.File;
import java.io.IOException;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class EmbedTestingServer {
private static final int PORT = 3181;
private static volatile TestingServer testingServer;
/**
* Start embed zookeeper server.
*/
public static void start() {
if (null != testingServer) {
return;
}
try {
testingServer = new TestingServer(PORT, new File(String.format("target/test_zk_data/%s/", System.nanoTime())));
// CHECKSTYLE:OFF
} catch (final Exception ex) {
// CHECKSTYLE:ON
if (!isIgnoredException(ex)) {
throw new RuntimeException(ex);
}
} finally {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
try {
testingServer.close();
} catch (final IOException ignored) {
}
}
});
}
}
private static boolean isIgnoredException(final Throwable cause) {
return cause instanceof KeeperException.ConnectionLossException || cause instanceof KeeperException.NoNodeException || cause instanceof KeeperException.NodeExistsException;
}
}
......@@ -18,6 +18,7 @@
<module>loit-seata-mybatis-mysql-suport</module>
<module>loit-component-jetcache-client</module>
<module>sharding-keygen-leaf</module>
<module>loit-keygen-leaf-zk</module>
</modules>
</project>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论