refactor: add extension module

This commit is contained in:
tjq 2020-12-20 00:04:07 +08:00
parent 9f2d3134d8
commit c40774d578
13 changed files with 75 additions and 113 deletions

View File

@ -1,6 +1,8 @@
package com.github.kfcfans.powerjob.server.service.alarm; package com.github.kfcfans.powerjob.server.extension;
import com.github.kfcfans.powerjob.server.persistence.core.model.UserInfoDO; import com.github.kfcfans.powerjob.server.persistence.core.model.UserInfoDO;
import com.github.kfcfans.powerjob.server.service.alarm.Alarm;
import com.github.kfcfans.powerjob.server.service.alarm.AlarmCenter;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import java.util.List; import java.util.List;

View File

@ -0,0 +1,14 @@
package com.github.kfcfans.powerjob.server.extension;
/**
* provide unique server ip in the cluster for IdGenerateService
* @author user
*/
public interface ServerIdProvider {
/**
* get number for IdGenerateService
* @return serverId, must in range [0, 16384)
*/
long getServerId();
}

View File

@ -2,11 +2,6 @@ package com.github.kfcfans.powerjob.server.persistence.core.repository;
import com.github.kfcfans.powerjob.server.persistence.core.model.ServerInfoDO; import com.github.kfcfans.powerjob.server.persistence.core.model.ServerInfoDO;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Lock;
import org.springframework.data.jpa.repository.Query;
import javax.persistence.LockModeType;
import java.util.List;
/** /**
* 服务器信息 数据操作层 * 服务器信息 数据操作层
@ -16,8 +11,4 @@ import java.util.List;
*/ */
public interface ServerInfoRepository extends JpaRepository<ServerInfoDO, Long> { public interface ServerInfoRepository extends JpaRepository<ServerInfoDO, Long> {
ServerInfoDO findByIp(String ip); ServerInfoDO findByIp(String ip);
@Query("select t from ServerInfoDO as t order by t.id asc")
@Lock(LockModeType.PESSIMISTIC_WRITE)
List<ServerInfoDO> findAllAndLockTable();
} }

View File

@ -1,5 +1,6 @@
package com.github.kfcfans.powerjob.server.service.alarm; package com.github.kfcfans.powerjob.server.service.alarm;
import com.github.kfcfans.powerjob.server.extension.Alarmable;
import com.github.kfcfans.powerjob.server.persistence.core.model.UserInfoDO; import com.github.kfcfans.powerjob.server.persistence.core.model.UserInfoDO;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Queues; import com.google.common.collect.Queues;

View File

@ -8,7 +8,7 @@ import com.github.kfcfans.powerjob.server.common.SJ;
import com.github.kfcfans.powerjob.server.common.utils.DingTalkUtils; import com.github.kfcfans.powerjob.server.common.utils.DingTalkUtils;
import com.github.kfcfans.powerjob.server.persistence.core.model.UserInfoDO; import com.github.kfcfans.powerjob.server.persistence.core.model.UserInfoDO;
import com.github.kfcfans.powerjob.server.service.alarm.Alarm; import com.github.kfcfans.powerjob.server.service.alarm.Alarm;
import com.github.kfcfans.powerjob.server.service.alarm.Alarmable; import com.github.kfcfans.powerjob.server.extension.Alarmable;
import com.google.common.cache.Cache; import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;

View File

@ -2,7 +2,7 @@ package com.github.kfcfans.powerjob.server.service.alarm.impl;
import com.github.kfcfans.powerjob.server.persistence.core.model.UserInfoDO; import com.github.kfcfans.powerjob.server.persistence.core.model.UserInfoDO;
import com.github.kfcfans.powerjob.server.service.alarm.Alarm; import com.github.kfcfans.powerjob.server.service.alarm.Alarm;
import com.github.kfcfans.powerjob.server.service.alarm.Alarmable; import com.github.kfcfans.powerjob.server.extension.Alarmable;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;

View File

@ -5,7 +5,7 @@ import com.github.kfcfans.powerjob.common.OmsConstant;
import com.github.kfcfans.powerjob.common.utils.HttpUtils; import com.github.kfcfans.powerjob.common.utils.HttpUtils;
import com.github.kfcfans.powerjob.server.persistence.core.model.UserInfoDO; import com.github.kfcfans.powerjob.server.persistence.core.model.UserInfoDO;
import com.github.kfcfans.powerjob.server.service.alarm.Alarm; import com.github.kfcfans.powerjob.server.service.alarm.Alarm;
import com.github.kfcfans.powerjob.server.service.alarm.Alarmable; import com.github.kfcfans.powerjob.server.extension.Alarmable;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import okhttp3.MediaType; import okhttp3.MediaType;
import okhttp3.RequestBody; import okhttp3.RequestBody;

View File

@ -1,39 +1,37 @@
package com.github.kfcfans.powerjob.server.service.id; package com.github.kfcfans.powerjob.server.service.id;
import com.github.kfcfans.powerjob.common.utils.NetUtils; import com.github.kfcfans.powerjob.common.utils.NetUtils;
import com.github.kfcfans.powerjob.server.extension.ServerIdProvider;
import com.github.kfcfans.powerjob.server.persistence.core.model.ServerInfoDO; import com.github.kfcfans.powerjob.server.persistence.core.model.ServerInfoDO;
import com.github.kfcfans.powerjob.server.persistence.core.repository.ServerInfoRepository; import com.github.kfcfans.powerjob.server.persistence.core.repository.ServerInfoRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/** /**
* 默认服务器 ID 生成策略不适用于 Server 频繁重启且变化 IP 的场景
* @author user * @author user
*/ */
@Slf4j
@Service
public class DefaultServerIdProvider implements ServerIdProvider { public class DefaultServerIdProvider implements ServerIdProvider {
private final ServerInfoRepository serverInfoRepository;
private volatile Long id; private final Long id;
public DefaultServerIdProvider(ServerInfoRepository serverInfoRepository) { public DefaultServerIdProvider(ServerInfoRepository serverInfoRepository) {
this.serverInfoRepository = serverInfoRepository; String ip = NetUtils.getLocalHost();
} ServerInfoDO server = serverInfoRepository.findByIp(ip);
@Override if (server == null) {
public long serverId() {
if (id == null) {
synchronized (this) {
if (id == null) {
String ip = NetUtils.getLocalHost();
ServerInfoDO server = serverInfoRepository.findByIp(ip);
if (server == null) {
ServerInfoDO newServerInfo = new ServerInfoDO(ip); ServerInfoDO newServerInfo = new ServerInfoDO(ip);
server = serverInfoRepository.saveAndFlush(newServerInfo); server = serverInfoRepository.saveAndFlush(newServerInfo);
}
id = server.getId();
} }
} this.id = server.getId();
log.info("[DefaultServerIdProvider] address:{},id:{}", ip, id);
} }
return id; @Override
} public long getServerId() {
return id;
}
} }

View File

@ -1,17 +1,19 @@
package com.github.kfcfans.powerjob.server.service.id; package com.github.kfcfans.powerjob.server.service.id;
import com.github.kfcfans.powerjob.common.utils.NetUtils; import com.github.kfcfans.powerjob.common.PowerJobException;
import com.github.kfcfans.powerjob.server.persistence.core.model.ServerInfoDO; import com.github.kfcfans.powerjob.server.extension.ServerIdProvider;
import com.github.kfcfans.powerjob.server.persistence.core.repository.ServerInfoRepository; import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
/** /**
* 唯一ID生成服务使用 Twitter snowflake 算法 * 唯一ID生成服务使用 Twitter snowflake 算法
* 机房ID固定为0占用2位 * 机房ID固定为0占用2位
* 机器ID数据库自增占用14位如果频繁部署需要删除数据库重置id * 机器ID ServerIdProvider 提供
* *
* @author tjq * @author tjq
* @since 2020/4/6 * @since 2020/4/6
@ -21,16 +23,37 @@ import org.springframework.stereotype.Service;
public class IdGenerateService { public class IdGenerateService {
private final SnowFlakeIdGenerator snowFlakeIdGenerator; private final SnowFlakeIdGenerator snowFlakeIdGenerator;
private static final int DATA_CENTER_ID = 0; private static final int DATA_CENTER_ID = 0;
@Autowired @Autowired
public IdGenerateService(@Qualifier("serverIdProvider") ServerIdProvider serverIdProvider) { public IdGenerateService(List<ServerIdProvider> serverIdProviders) {
long id = serverIdProvider.serverId();
snowFlakeIdGenerator = new SnowFlakeIdGenerator(DATA_CENTER_ID, id);
String ip = NetUtils.getLocalHost();
log.info("[IdGenerateService] init snowflake for server(address={}) by machineId({}).", ip, id); if (CollectionUtils.isEmpty(serverIdProviders)) {
throw new PowerJobException("can't find any ServerIdProvider!");
}
ServerIdProvider serverIdProvider;
int severIpProviderNums = serverIdProviders.size();
if (severIpProviderNums == 1) {
serverIdProvider = serverIdProviders.get(0);
} else {
List<ServerIdProvider> extendServerIpProviders = Lists.newArrayList();
for (ServerIdProvider sp : serverIdProviders) {
if (sp instanceof DefaultServerIdProvider) {
continue;
}
extendServerIpProviders.add(sp);
}
int extNum = extendServerIpProviders.size();
if (extNum != 1) {
throw new PowerJobException(String.format("find %d ServerIdProvider but just need one, please delete the useless ServerIdProvider!", extNum));
}
serverIdProvider = extendServerIpProviders.get(0);
}
long id = serverIdProvider.getServerId();
snowFlakeIdGenerator = new SnowFlakeIdGenerator(DATA_CENTER_ID, id);
log.info("[IdGenerateService] initialize IdGenerateService successfully, ServerIdProvider:{},ID:{}", serverIdProvider.getClass().getSimpleName(), id);
} }
/** /**

View File

@ -1,12 +0,0 @@
package com.github.kfcfans.powerjob.server.service.id;
/**
* @author user
*/
public interface ServerIdProvider {
/**
* get number for IdGenerateService
* @return serverId
*/
long serverId();
}

View File

@ -1,25 +0,0 @@
package com.github.kfcfans.powerjob.server.service.id;
import com.github.kfcfans.powerjob.server.persistence.core.repository.ServerInfoRepository;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author user
*/
@Configuration
public class ServerIdProviderConfiguration {
@ConditionalOnProperty(prefix = "oms.server-id", name = "provider", havingValue = "hostname")
@Bean(name = "serverIdProvider")
public ServerIdProvider statefulSetServerIdProvider() {
return new StatefulSetServerIdProvider();
}
@ConditionalOnMissingBean(ServerIdProvider.class)
@Bean(name = "serverIdProvider")
public ServerIdProvider defaultServerIdProvider(ServerInfoRepository serverInfoRepository) {
return new DefaultServerIdProvider(serverInfoRepository);
}
}

View File

@ -34,8 +34,8 @@ class SnowFlakeIdGenerator {
private final static long DATA_CENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT; private final static long DATA_CENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
private final static long TIMESTAMP_LEFT = DATA_CENTER_LEFT + DATA_CENTER_BIT; private final static long TIMESTAMP_LEFT = DATA_CENTER_LEFT + DATA_CENTER_BIT;
private long dataCenterId; //数据中心 private final long dataCenterId; //数据中心
private long machineId; //机器标识 private final long machineId; //机器标识
private long sequence = 0L; //序列号 private long sequence = 0L; //序列号
private long lastTimestamp = -1L;//上一次时间戳 private long lastTimestamp = -1L;//上一次时间戳

View File

@ -1,30 +0,0 @@
package com.github.kfcfans.powerjob.server.service.id;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author user
*/
public class StatefulSetServerIdProvider implements ServerIdProvider {
/**
* xxx-1,aa-bb-2
*/
private static final Pattern HOSTNAME_PATTERN = Pattern.compile("^.*-([0-9]+)$");
@Override
public long serverId() {
try {
String hostname = InetAddress.getLocalHost().getHostName();
Matcher matcher = HOSTNAME_PATTERN.matcher(hostname);
if (matcher.matches()) {
return Long.parseLong(matcher.group(1));
}
throw new RuntimeException(String.format("hostname=%s not match %s", hostname, HOSTNAME_PATTERN.toString()));
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
}