chore(project): 添加项目配置文件和忽略规则
- 添加 Babel 配置文件支持 ES6+ 语法转换 - 添加 ESLint 忽略规则和配置文件 - 添加 Git 忽略规则文件 - 添加 Travis CI 配置文件 - 添加 1.4.2 版本变更日志文件 - 添加 Helm 图表辅助模板文件 - 添加 Helm 忽略规则文件
This commit is contained in:
39
discovery/seata-discovery-redis/pom.xml
Normal file
39
discovery/seata-discovery-redis/pom.xml
Normal file
@@ -0,0 +1,39 @@
|
||||
<?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-redis</artifactId>
|
||||
<name>seata-discovery-redis ${project.version}</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.seata</groupId>
|
||||
<artifactId>seata-discovery-core</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.redis;
|
||||
|
||||
/**
|
||||
* The RedisListener
|
||||
*
|
||||
* @author kl @kailing.pub
|
||||
*/
|
||||
public interface RedisListener {
|
||||
/**
|
||||
* The constant REGISTER.
|
||||
*/
|
||||
String REGISTER = "register";
|
||||
/**
|
||||
* The constant UN_REGISTER.
|
||||
*/
|
||||
String UN_REGISTER = "unregister";
|
||||
|
||||
/**
|
||||
* use for redis event
|
||||
*
|
||||
* @param event the event
|
||||
*/
|
||||
void onEvent(String event);
|
||||
}
|
||||
@@ -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.redis;
|
||||
|
||||
import io.seata.common.loader.LoadLevel;
|
||||
import io.seata.discovery.registry.RegistryProvider;
|
||||
import io.seata.discovery.registry.RegistryService;
|
||||
|
||||
/**
|
||||
* @author xingfudeshi@gmail.com
|
||||
*/
|
||||
@LoadLevel(name = "Redis", order = 1)
|
||||
public class RedisRegistryProvider implements RegistryProvider {
|
||||
@Override
|
||||
public RegistryService provide() {
|
||||
return RedisRegistryServiceImpl.getInstance();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* 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.redis;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
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.ExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import io.seata.common.exception.ShouldNeverHappenException;
|
||||
import io.seata.common.thread.NamedThreadFactory;
|
||||
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.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import redis.clients.jedis.JedisPool;
|
||||
import redis.clients.jedis.JedisPubSub;
|
||||
import redis.clients.jedis.Protocol;
|
||||
|
||||
/**
|
||||
* The type Redis registry service.
|
||||
*
|
||||
* @author kl @kailing.pub
|
||||
*/
|
||||
public class RedisRegistryServiceImpl implements RegistryService<RedisListener> {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RedisRegistryServiceImpl.class);
|
||||
private static final String PRO_SERVER_ADDR_KEY = "serverAddr";
|
||||
private static final String REDIS_FILEKEY_PREFIX = "registry.redis.";
|
||||
private static final String DEFAULT_CLUSTER = "default";
|
||||
private static final String REGISTRY_CLUSTER_KEY = "cluster";
|
||||
private String clusterName;
|
||||
private static final String REDIS_DB = "db";
|
||||
private static final String REDIS_PASSWORD = "password";
|
||||
private static final ConcurrentMap<String, List<RedisListener>> LISTENER_SERVICE_MAP = new ConcurrentHashMap<>();
|
||||
private static final ConcurrentMap<String, Set<InetSocketAddress>> CLUSTER_ADDRESS_MAP = new ConcurrentHashMap<>();
|
||||
private static volatile RedisRegistryServiceImpl instance;
|
||||
private static volatile JedisPool jedisPool;
|
||||
|
||||
private ExecutorService threadPoolExecutor = new ScheduledThreadPoolExecutor(1,
|
||||
new NamedThreadFactory("RedisRegistryService", 1));
|
||||
|
||||
private RedisRegistryServiceImpl() {
|
||||
Configuration seataConfig = ConfigurationFactory.CURRENT_FILE_INSTANCE;
|
||||
this.clusterName = seataConfig.getConfig(REDIS_FILEKEY_PREFIX + REGISTRY_CLUSTER_KEY, DEFAULT_CLUSTER);
|
||||
String password = seataConfig.getConfig(getRedisPasswordFileKey());
|
||||
String serverAddr = seataConfig.getConfig(getRedisAddrFileKey());
|
||||
String[] serverArr = serverAddr.split(":");
|
||||
String host = serverArr[0];
|
||||
int port = Integer.parseInt(serverArr[1]);
|
||||
int db = seataConfig.getInt(getRedisDbFileKey());
|
||||
GenericObjectPoolConfig redisConfig = new GenericObjectPoolConfig();
|
||||
redisConfig.setTestOnBorrow(seataConfig.getBoolean(REDIS_FILEKEY_PREFIX + "test.on.borrow", true));
|
||||
redisConfig.setTestOnReturn(seataConfig.getBoolean(REDIS_FILEKEY_PREFIX + "test.on.return", false));
|
||||
redisConfig.setTestWhileIdle(seataConfig.getBoolean(REDIS_FILEKEY_PREFIX + "test.while.idle", false));
|
||||
int maxIdle = seataConfig.getInt(REDIS_FILEKEY_PREFIX + "max.idle", 0);
|
||||
if (maxIdle > 0) {
|
||||
redisConfig.setMaxIdle(maxIdle);
|
||||
}
|
||||
int minIdle = seataConfig.getInt(REDIS_FILEKEY_PREFIX + "min.idle", 0);
|
||||
if (minIdle > 0) {
|
||||
redisConfig.setMinIdle(minIdle);
|
||||
}
|
||||
int maxActive = seataConfig.getInt(REDIS_FILEKEY_PREFIX + "max.active", 0);
|
||||
if (maxActive > 0) {
|
||||
redisConfig.setMaxTotal(maxActive);
|
||||
}
|
||||
int maxTotal = seataConfig.getInt(REDIS_FILEKEY_PREFIX + "max.total", 0);
|
||||
if (maxTotal > 0) {
|
||||
redisConfig.setMaxTotal(maxTotal);
|
||||
}
|
||||
int maxWait = seataConfig.getInt(REDIS_FILEKEY_PREFIX + "max.wait",
|
||||
seataConfig.getInt(REDIS_FILEKEY_PREFIX + "timeout", 0));
|
||||
if (maxWait > 0) {
|
||||
redisConfig.setMaxWaitMillis(maxWait);
|
||||
}
|
||||
int numTestsPerEvictionRun = seataConfig.getInt(REDIS_FILEKEY_PREFIX + "num.tests.per.eviction.run", 0);
|
||||
if (numTestsPerEvictionRun > 0) {
|
||||
redisConfig.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
|
||||
}
|
||||
int timeBetweenEvictionRunsMillis = seataConfig.getInt(
|
||||
REDIS_FILEKEY_PREFIX + "time.between.eviction.runs.millis", 0);
|
||||
if (timeBetweenEvictionRunsMillis > 0) {
|
||||
redisConfig.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
|
||||
}
|
||||
int minEvictableIdleTimeMillis = seataConfig.getInt(REDIS_FILEKEY_PREFIX + "min.evictable.idle.time.millis",
|
||||
0);
|
||||
if (minEvictableIdleTimeMillis > 0) {
|
||||
redisConfig.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
|
||||
}
|
||||
if (StringUtils.isNullOrEmpty(password)) {
|
||||
jedisPool = new JedisPool(redisConfig, host, port, Protocol.DEFAULT_TIMEOUT, null, db);
|
||||
} else {
|
||||
jedisPool = new JedisPool(redisConfig, host, port, Protocol.DEFAULT_TIMEOUT, password, db);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets instance.
|
||||
*
|
||||
* @return the instance
|
||||
*/
|
||||
static RedisRegistryServiceImpl getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (RedisRegistryServiceImpl.class) {
|
||||
if (instance == null) {
|
||||
instance = new RedisRegistryServiceImpl();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(InetSocketAddress address) {
|
||||
NetUtil.validAddress(address);
|
||||
String serverAddr = NetUtil.toStringAddress(address);
|
||||
try (Jedis jedis = jedisPool.getResource()) {
|
||||
jedis.hset(getRedisRegistryKey(), serverAddr, ManagementFactory.getRuntimeMXBean().getName());
|
||||
jedis.publish(getRedisRegistryKey(), serverAddr + "-" + RedisListener.REGISTER);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister(InetSocketAddress address) {
|
||||
NetUtil.validAddress(address);
|
||||
String serverAddr = NetUtil.toStringAddress(address);
|
||||
try (Jedis jedis = jedisPool.getResource()) {
|
||||
jedis.hdel(getRedisRegistryKey(), serverAddr);
|
||||
jedis.publish(getRedisRegistryKey(), serverAddr + "-" + RedisListener.UN_REGISTER);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe(String cluster, RedisListener listener) {
|
||||
String redisRegistryKey = REDIS_FILEKEY_PREFIX + cluster;
|
||||
LISTENER_SERVICE_MAP.computeIfAbsent(cluster, key -> new ArrayList<>())
|
||||
.add(listener);
|
||||
threadPoolExecutor.submit(() -> {
|
||||
try {
|
||||
try (Jedis jedis = jedisPool.getResource()) {
|
||||
jedis.subscribe(new NotifySub(LISTENER_SERVICE_MAP.get(cluster)), redisRegistryKey);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsubscribe(String cluster, RedisListener listener) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<InetSocketAddress> lookup(String key) {
|
||||
String clusterName = getServiceGroup(key);
|
||||
if (clusterName == null) {
|
||||
return null;
|
||||
}
|
||||
if (!LISTENER_SERVICE_MAP.containsKey(clusterName)) {
|
||||
String redisRegistryKey = REDIS_FILEKEY_PREFIX + clusterName;
|
||||
Map<String, String> instances;
|
||||
try (Jedis jedis = jedisPool.getResource()) {
|
||||
instances = jedis.hgetAll(redisRegistryKey);
|
||||
}
|
||||
if (instances != null && !instances.isEmpty()) {
|
||||
Set<InetSocketAddress> newAddressSet = instances.keySet().stream()
|
||||
.map(NetUtil::toInetSocketAddress)
|
||||
.collect(Collectors.toSet());
|
||||
CLUSTER_ADDRESS_MAP.put(clusterName, newAddressSet);
|
||||
}
|
||||
subscribe(clusterName, msg -> {
|
||||
String[] msgr = msg.split("-");
|
||||
String serverAddr = msgr[0];
|
||||
String eventType = msgr[1];
|
||||
switch (eventType) {
|
||||
case RedisListener.REGISTER:
|
||||
CLUSTER_ADDRESS_MAP.get(clusterName).add(NetUtil.toInetSocketAddress(serverAddr));
|
||||
break;
|
||||
case RedisListener.UN_REGISTER:
|
||||
CLUSTER_ADDRESS_MAP.get(clusterName).remove(NetUtil.toInetSocketAddress(serverAddr));
|
||||
break;
|
||||
default:
|
||||
throw new ShouldNeverHappenException("unknown redis msg:" + msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
return new ArrayList<>(CLUSTER_ADDRESS_MAP.getOrDefault(clusterName, Collections.emptySet()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
jedisPool.destroy();
|
||||
}
|
||||
|
||||
private static class NotifySub extends JedisPubSub {
|
||||
|
||||
private final List<RedisListener> redisListeners;
|
||||
|
||||
/**
|
||||
* Instantiates a new Notify sub.
|
||||
*
|
||||
* @param redisListeners the redis listeners
|
||||
*/
|
||||
NotifySub(List<RedisListener> redisListeners) {
|
||||
this.redisListeners = redisListeners;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(String key, String msg) {
|
||||
for (RedisListener listener : redisListeners) {
|
||||
listener.onEvent(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getRedisRegistryKey() {
|
||||
return REDIS_FILEKEY_PREFIX + clusterName;
|
||||
}
|
||||
|
||||
private String getRedisAddrFileKey() {
|
||||
return REDIS_FILEKEY_PREFIX + PRO_SERVER_ADDR_KEY;
|
||||
}
|
||||
|
||||
private String getRedisPasswordFileKey() {
|
||||
return REDIS_FILEKEY_PREFIX + REDIS_PASSWORD;
|
||||
}
|
||||
|
||||
private String getRedisDbFileKey() {
|
||||
return REDIS_FILEKEY_PREFIX + REDIS_DB;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
io.seata.discovery.registry.redis.RedisRegistryProvider
|
||||
Reference in New Issue
Block a user