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.service.alarm.Alarm;
import com.github.kfcfans.powerjob.server.service.alarm.AlarmCenter;
import org.springframework.beans.factory.InitializingBean;
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 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> {
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;
import com.github.kfcfans.powerjob.server.extension.Alarmable;
import com.github.kfcfans.powerjob.server.persistence.core.model.UserInfoDO;
import com.google.common.collect.Lists;
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.persistence.core.model.UserInfoDO;
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.CacheBuilder;
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.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 org.springframework.beans.factory.annotation.Autowired;
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.server.persistence.core.model.UserInfoDO;
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 okhttp3.MediaType;
import okhttp3.RequestBody;

View File

@ -1,39 +1,37 @@
package com.github.kfcfans.powerjob.server.service.id;
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.repository.ServerInfoRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* 默认服务器 ID 生成策略不适用于 Server 频繁重启且变化 IP 的场景
* @author user
*/
@Slf4j
@Service
public class DefaultServerIdProvider implements ServerIdProvider {
private final ServerInfoRepository serverInfoRepository;
private volatile Long id;
private final Long id;
public DefaultServerIdProvider(ServerInfoRepository serverInfoRepository) {
this.serverInfoRepository = serverInfoRepository;
}
public DefaultServerIdProvider(ServerInfoRepository serverInfoRepository) {
String ip = NetUtils.getLocalHost();
ServerInfoDO server = serverInfoRepository.findByIp(ip);
@Override
public long serverId() {
if (id == null) {
synchronized (this) {
if (id == null) {
String ip = NetUtils.getLocalHost();
ServerInfoDO server = serverInfoRepository.findByIp(ip);
if (server == null) {
if (server == null) {
ServerInfoDO newServerInfo = new ServerInfoDO(ip);
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;
import com.github.kfcfans.powerjob.common.utils.NetUtils;
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.common.PowerJobException;
import com.github.kfcfans.powerjob.server.extension.ServerIdProvider;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
/**
* 唯一ID生成服务使用 Twitter snowflake 算法
* 机房ID固定为0占用2位
* 机器ID数据库自增占用14位如果频繁部署需要删除数据库重置id
* 机器ID ServerIdProvider 提供
*
* @author tjq
* @since 2020/4/6
@ -21,16 +23,37 @@ import org.springframework.stereotype.Service;
public class IdGenerateService {
private final SnowFlakeIdGenerator snowFlakeIdGenerator;
private static final int DATA_CENTER_ID = 0;
@Autowired
public IdGenerateService(@Qualifier("serverIdProvider") ServerIdProvider serverIdProvider) {
long id = serverIdProvider.serverId();
snowFlakeIdGenerator = new SnowFlakeIdGenerator(DATA_CENTER_ID, id);
String ip = NetUtils.getLocalHost();
public IdGenerateService(List<ServerIdProvider> serverIdProviders) {
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 TIMESTAMP_LEFT = DATA_CENTER_LEFT + DATA_CENTER_BIT;
private long dataCenterId; //数据中心
private long machineId; //机器标识
private final long dataCenterId; //数据中心
private final long machineId; //机器标识
private long sequence = 0L; //序列号
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);
}
}
}