refactor(系统设置): UID生成器优化
This commit is contained in:
parent
5e1b480510
commit
1b3712492c
|
@ -9,6 +9,7 @@ import io.metersphere.sdk.util.CommonBeanFactory;
|
||||||
import io.metersphere.sdk.util.LogUtils;
|
import io.metersphere.sdk.util.LogUtils;
|
||||||
import io.metersphere.system.service.BaseScheduleService;
|
import io.metersphere.system.service.BaseScheduleService;
|
||||||
import io.metersphere.system.service.PluginLoadService;
|
import io.metersphere.system.service.PluginLoadService;
|
||||||
|
import io.metersphere.system.uid.impl.DefaultUidGenerator;
|
||||||
import io.minio.MinioClient;
|
import io.minio.MinioClient;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.springframework.boot.ApplicationArguments;
|
import org.springframework.boot.ApplicationArguments;
|
||||||
|
@ -26,9 +27,13 @@ public class AppStartListener implements ApplicationRunner {
|
||||||
@Resource
|
@Resource
|
||||||
private BaseScheduleService baseScheduleService;
|
private BaseScheduleService baseScheduleService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DefaultUidGenerator defaultUidGenerator;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(ApplicationArguments args) throws Exception {
|
public void run(ApplicationArguments args) throws Exception {
|
||||||
LogUtils.info("================= 应用启动 =================");
|
LogUtils.info("================= 应用启动 =================");
|
||||||
|
defaultUidGenerator.afterPropertiesSet();
|
||||||
// 初始化MinIO配置
|
// 初始化MinIO配置
|
||||||
((MinioRepository) FileCenter.getRepository(StorageType.MINIO)).init(minioClient);
|
((MinioRepository) FileCenter.getRepository(StorageType.MINIO)).init(minioClient);
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package io.metersphere.system.uid;
|
package io.metersphere.system.uid;
|
||||||
|
|
||||||
import io.metersphere.system.uid.impl.CachedUidGenerator;
|
|
||||||
import io.metersphere.sdk.util.CommonBeanFactory;
|
import io.metersphere.sdk.util.CommonBeanFactory;
|
||||||
|
import io.metersphere.system.uid.impl.DefaultUidGenerator;
|
||||||
|
|
||||||
public class IDGenerator {
|
public class IDGenerator {
|
||||||
private static final CachedUidGenerator DEFAULT_UID_GENERATOR;
|
private static final DefaultUidGenerator DEFAULT_UID_GENERATOR;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
DEFAULT_UID_GENERATOR = CommonBeanFactory.getBean(CachedUidGenerator.class);
|
DEFAULT_UID_GENERATOR = CommonBeanFactory.getBean(DefaultUidGenerator.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,147 +0,0 @@
|
||||||
|
|
||||||
package io.metersphere.system.uid.impl;
|
|
||||||
|
|
||||||
import io.metersphere.sdk.exception.MSException;
|
|
||||||
import io.metersphere.system.uid.BitsAllocator;
|
|
||||||
import io.metersphere.system.uid.buffer.BufferPaddingExecutor;
|
|
||||||
import io.metersphere.system.uid.buffer.RejectedPutBufferHandler;
|
|
||||||
import io.metersphere.system.uid.buffer.RejectedTakeBufferHandler;
|
|
||||||
import io.metersphere.system.uid.buffer.RingBuffer;
|
|
||||||
import io.metersphere.sdk.util.LogUtils;
|
|
||||||
import org.springframework.beans.factory.DisposableBean;
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* from {@link DefaultUidGenerator}, based on a lock free {@link RingBuffer}<p>
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
public class CachedUidGenerator extends DefaultUidGenerator implements DisposableBean, InitializingBean {
|
|
||||||
private static final int DEFAULT_BOOST_POWER = 3;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Spring properties
|
|
||||||
*/
|
|
||||||
private int boostPower = DEFAULT_BOOST_POWER;
|
|
||||||
private Long scheduleInterval;
|
|
||||||
|
|
||||||
private RejectedPutBufferHandler rejectedPutBufferHandler;
|
|
||||||
private RejectedTakeBufferHandler rejectedTakeBufferHandler;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RingBuffer
|
|
||||||
*/
|
|
||||||
private RingBuffer ringBuffer;
|
|
||||||
private BufferPaddingExecutor bufferPaddingExecutor;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterPropertiesSet() {
|
|
||||||
// initialize workerId & bitsAllocator
|
|
||||||
super.afterPropertiesSet();
|
|
||||||
|
|
||||||
// initialize RingBuffer & RingBufferPaddingExecutor
|
|
||||||
this.initRingBuffer();
|
|
||||||
LogUtils.info("Initialized RingBuffer successfully.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getUID() {
|
|
||||||
try {
|
|
||||||
return ringBuffer.take();
|
|
||||||
} catch (Exception e) {
|
|
||||||
LogUtils.error("Generate unique id exception. ", e);
|
|
||||||
throw new MSException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String parseUID(long uid) {
|
|
||||||
return super.parseUID(uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void destroy() throws Exception {
|
|
||||||
bufferPaddingExecutor.shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the UIDs in the same specified second under the max sequence
|
|
||||||
* * @return UID list, size of {@link BitsAllocator#getMaxSequence()} + 1
|
|
||||||
*/
|
|
||||||
protected List<Long> nextIdsForOneSecond(long currentSecond) {
|
|
||||||
// Initialize result list size of (max sequence + 1)
|
|
||||||
int listSize = (int) bitsAllocator.getMaxSequence() + 1;
|
|
||||||
List<Long> uidList = new ArrayList<>(listSize);
|
|
||||||
|
|
||||||
// Allocate the first sequence of the second, the others can be calculated with the offset
|
|
||||||
long firstSeqUid = bitsAllocator.allocate(currentSecond - epochSeconds, workerId, 0L);
|
|
||||||
for (int offset = 0; offset < listSize; offset++) {
|
|
||||||
uidList.add(firstSeqUid + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
return uidList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize RingBuffer & RingBufferPaddingExecutor
|
|
||||||
*/
|
|
||||||
private void initRingBuffer() {
|
|
||||||
// initialize RingBuffer
|
|
||||||
int bufferSize = ((int) bitsAllocator.getMaxSequence() + 1) << boostPower;
|
|
||||||
int paddingFactor = RingBuffer.DEFAULT_PADDING_PERCENT;
|
|
||||||
this.ringBuffer = new RingBuffer(bufferSize, paddingFactor);
|
|
||||||
LogUtils.info("Initialized ring buffer size:{}, paddingFactor:{}", bufferSize, paddingFactor);
|
|
||||||
|
|
||||||
// initialize RingBufferPaddingExecutor
|
|
||||||
boolean usingSchedule = (scheduleInterval != null);
|
|
||||||
this.bufferPaddingExecutor = new BufferPaddingExecutor(ringBuffer, this::nextIdsForOneSecond, usingSchedule);
|
|
||||||
if (usingSchedule) {
|
|
||||||
bufferPaddingExecutor.setScheduleInterval(scheduleInterval);
|
|
||||||
}
|
|
||||||
|
|
||||||
LogUtils.info("Initialized BufferPaddingExecutor. Using schdule:{}, interval:{}", usingSchedule, scheduleInterval);
|
|
||||||
|
|
||||||
// set rejected put/take handle policy
|
|
||||||
this.ringBuffer.setBufferPaddingExecutor(bufferPaddingExecutor);
|
|
||||||
if (rejectedPutBufferHandler != null) {
|
|
||||||
this.ringBuffer.setRejectedPutHandler(rejectedPutBufferHandler);
|
|
||||||
}
|
|
||||||
if (rejectedTakeBufferHandler != null) {
|
|
||||||
this.ringBuffer.setRejectedTakeHandler(rejectedTakeBufferHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
// fill in all slots of the RingBuffer
|
|
||||||
bufferPaddingExecutor.paddingBuffer();
|
|
||||||
|
|
||||||
// start buffer padding threads
|
|
||||||
bufferPaddingExecutor.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setters for spring property
|
|
||||||
*/
|
|
||||||
public void setBoostPower(int boostPower) {
|
|
||||||
Assert.isTrue(boostPower > 0, "Boost power must be positive!");
|
|
||||||
this.boostPower = boostPower;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRejectedPutBufferHandler(RejectedPutBufferHandler rejectedPutBufferHandler) {
|
|
||||||
Assert.notNull(rejectedPutBufferHandler, "RejectedPutBufferHandler can't be null!");
|
|
||||||
this.rejectedPutBufferHandler = rejectedPutBufferHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRejectedTakeBufferHandler(RejectedTakeBufferHandler rejectedTakeBufferHandler) {
|
|
||||||
Assert.notNull(rejectedTakeBufferHandler, "RejectedTakeBufferHandler can't be null!");
|
|
||||||
this.rejectedTakeBufferHandler = rejectedTakeBufferHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setScheduleInterval(long scheduleInterval) {
|
|
||||||
Assert.isTrue(scheduleInterval > 0, "Schedule interval must positive!");
|
|
||||||
this.scheduleInterval = scheduleInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -8,13 +8,15 @@ import io.metersphere.system.uid.worker.WorkerIdAssigner;
|
||||||
import io.metersphere.sdk.util.LogUtils;
|
import io.metersphere.sdk.util.LogUtils;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class DefaultUidGenerator {
|
public class DefaultUidGenerator implements DisposableBean, InitializingBean {
|
||||||
/**
|
/**
|
||||||
* Bits allocate
|
* Bits allocate
|
||||||
*/
|
*/
|
||||||
|
@ -176,4 +178,9 @@ public class DefaultUidGenerator {
|
||||||
this.epochSeconds = TimeUnit.MILLISECONDS.toSeconds(TimeUtils.parseByDayPattern(epochStr).getTime());
|
this.epochSeconds = TimeUnit.MILLISECONDS.toSeconds(TimeUtils.parseByDayPattern(epochStr).getTime());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() throws Exception {
|
||||||
|
LogUtils.info("Shutdown UidGenerator...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue