serverIdProvider interface and implements

This commit is contained in:
tanwenhai 2020-12-17 11:12:54 +08:00
parent 35f0991f03
commit 76e5a41881
5 changed files with 111 additions and 38 deletions

View File

@ -0,0 +1,39 @@
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;
/**
* @author user
*/
public class DefaultServerIdProvider implements ServerIdProvider {
private final ServerInfoRepository serverInfoRepository;
private volatile Long id;
public DefaultServerIdProvider(ServerInfoRepository serverInfoRepository) {
this.serverInfoRepository = serverInfoRepository;
}
@Override
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);
server = serverInfoRepository.saveAndFlush(newServerInfo);
}
id = server.getId();
}
}
}
return id;
}
}

View File

@ -3,23 +3,10 @@ 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.google.common.base.Throwables;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.Assert;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
/**
* 唯一ID生成服务使用 Twitter snowflake 算法
@ -38,32 +25,12 @@ public class IdGenerateService {
private static final int DATA_CENTER_ID = 0;
@Autowired
public IdGenerateService(ServerInfoRepository serverInfoRepository,
@Qualifier("coreTransactionManager") PlatformTransactionManager platformTransactionManager) {
TransactionTemplate transactionTemplate = new TransactionTemplate(platformTransactionManager);
// 服务频繁重启数据库id自增值过大使用表锁获取机器id
snowFlakeIdGenerator = transactionTemplate.execute(action -> {
List<ServerInfoDO> serverInfos = serverInfoRepository.findAllAndLockTable();
String ip = NetUtils.getLocalHost();
ServerInfoDO server = serverInfoRepository.findByIp(ip);
Long id = null;
if (server == null) {
ServerInfoDO newServerInfo = new ServerInfoDO(ip);
serverInfoRepository.saveAndFlush(newServerInfo);
id = serverInfos.size() + 1L;
} else {
for (int i = 0, len = serverInfos.size(); i < len; i++) {
if (Objects.equals(serverInfos.get(i).getId(), server.getId())) {
id = i + 1L;
break;
}
}
}
Assert.notNull(id, "[IdGenerateService] init snowflake error, id is null");
log.info("[IdGenerateService] init snowflake for server(address={}) by machineId({}).", ip, id);
public IdGenerateService(@Qualifier("serverIdProvider") ServerIdProvider serverIdProvider) {
long id = serverIdProvider.serverId();
snowFlakeIdGenerator = new SnowFlakeIdGenerator(DATA_CENTER_ID, id);
String ip = NetUtils.getLocalHost();
return new SnowFlakeIdGenerator(DATA_CENTER_ID, id);
});
log.info("[IdGenerateService] init snowflake for server(address={}) by machineId({}).", ip, id);
}
/**

View File

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

View File

@ -0,0 +1,25 @@
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

@ -0,0 +1,30 @@
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);
}
}
}