优化缓存

This commit is contained in:
天爱有情
2022-04-25 11:01:50 +08:00
parent 7d9dea6975
commit 9a6d2687ca
2 changed files with 59 additions and 18 deletions
@@ -25,18 +25,20 @@ public class CacheImageCaptchaGenerator implements ImageCaptchaGenerator {
protected final ScheduledExecutorService scheduledExecutor = new ScheduledThreadPoolExecutor(1, new NamedThreadFactory("slider-captcha-queue")); protected final ScheduledExecutorService scheduledExecutor = new ScheduledThreadPoolExecutor(1, new NamedThreadFactory("slider-captcha-queue"));
protected Map<GenerateParam, ConcurrentLinkedQueue<ImageCaptchaInfo>> queueMap = new ConcurrentHashMap<>(8); protected Map<GenerateParam, ConcurrentLinkedQueue<ImageCaptchaInfo>> queueMap = new ConcurrentHashMap<>(8);
protected Map<GenerateParam, AtomicInteger> posMap = new ConcurrentHashMap<>(8); protected Map<GenerateParam, AtomicInteger> posMap = new ConcurrentHashMap<>(8);
protected Map<GenerateParam, Long> lastUpdateMap = new ConcurrentHashMap<>(8);
protected ImageCaptchaGenerator target; protected ImageCaptchaGenerator target;
protected int size; protected int size;
/** 等待时间,一般报错或者拉取为空时会休眠一段时间再试. */ /** 等待时间,一般报错或者拉取为空时会休眠一段时间再试. */
protected int waitTime = 1000; protected int waitTime = 1000;
/** 调度器检查缓存的间隔时间. */ /** 调度器检查缓存的间隔时间. */
protected int period = 100; protected int period = 5000;
/** 10天内没有任何操作就删除已缓存的数据. */
protected long expireTime = TimeUnit.DAYS.toMillis(10);
@Getter @Getter
@Setter @Setter
protected boolean requiredGetCaptcha = true; protected boolean requiredGetCaptcha = true;
public CacheImageCaptchaGenerator(ImageCaptchaGenerator target, int size) { public CacheImageCaptchaGenerator(ImageCaptchaGenerator target, int size) {
this.target = target; this.target = target;
this.size = size; this.size = size;
} }
@@ -48,6 +50,14 @@ public class CacheImageCaptchaGenerator implements ImageCaptchaGenerator {
this.period = period; this.period = period;
} }
public CacheImageCaptchaGenerator(ImageCaptchaGenerator target, int size, int waitTime, int period, Long expireTime) {
this.target = target;
this.size = size;
this.waitTime = waitTime;
this.period = period;
this.expireTime = expireTime;
}
/** /**
* 记的初始化调度器 * 记的初始化调度器
*/ */
@@ -62,6 +72,7 @@ public class CacheImageCaptchaGenerator implements ImageCaptchaGenerator {
queueMap.forEach((k, queue) -> { queueMap.forEach((k, queue) -> {
try { try {
AtomicInteger pos = posMap.computeIfAbsent(k, k1 -> new AtomicInteger(0)); AtomicInteger pos = posMap.computeIfAbsent(k, k1 -> new AtomicInteger(0));
int addCount = 0;
while (pos.get() < this.size) { while (pos.get() < this.size) {
if (pos.get() >= size) { if (pos.get() >= size) {
return; return;
@@ -69,6 +80,7 @@ public class CacheImageCaptchaGenerator implements ImageCaptchaGenerator {
ImageCaptchaInfo slideImageInfo = target.generateCaptchaImage(k); ImageCaptchaInfo slideImageInfo = target.generateCaptchaImage(k);
if (slideImageInfo != null) { if (slideImageInfo != null) {
boolean addStatus = queue.offer(slideImageInfo); boolean addStatus = queue.offer(slideImageInfo);
addCount++;
if (addStatus) { if (addStatus) {
// 添加记录 // 添加记录
pos.incrementAndGet(); pos.incrementAndGet();
@@ -77,11 +89,22 @@ public class CacheImageCaptchaGenerator implements ImageCaptchaGenerator {
sleep(); sleep();
} }
} }
if (addCount == 0) {
// 没有添加,检测最新更新时间 如果时间过长,直接清除数据
Long lastUpdate = lastUpdateMap.get(k);
if (lastUpdate != null && System.currentTimeMillis() - lastUpdate > expireTime) {
queueMap.remove(k);
posMap.remove(k);
lastUpdateMap.remove(k);
}
}
} catch (Exception e) { } catch (Exception e) {
// cache所有 // cache所有
log.error("缓存队列扫描时出错, ex", e); log.error("缓存队列扫描时出错, ex", e);
// 删掉它 // 删掉它
queueMap.remove(k); queueMap.remove(k);
posMap.remove(k);
lastUpdateMap.remove(k);
// 休眠 // 休眠
sleep(); sleep();
} }
@@ -107,21 +130,31 @@ public class CacheImageCaptchaGenerator implements ImageCaptchaGenerator {
@SneakyThrows @SneakyThrows
public ImageCaptchaInfo generateCaptchaImage(GenerateParam generateParam, boolean requiredGetCaptcha) { public ImageCaptchaInfo generateCaptchaImage(GenerateParam generateParam, boolean requiredGetCaptcha) {
ConcurrentLinkedQueue<ImageCaptchaInfo> queue = queueMap.computeIfAbsent(generateParam, g -> new ConcurrentLinkedQueue<>()); ConcurrentLinkedQueue<ImageCaptchaInfo> queue = queueMap.get(generateParam);
ImageCaptchaInfo poll = queue.poll(); ImageCaptchaInfo captchaInfo = null;
if (poll == null && requiredGetCaptcha) { if (queue != null) {
log.warn("滑块验证码缓存不足, genParam:{}", generateParam); captchaInfo = queue.poll();
// 如果池内没数据, 则直接生成 if (captchaInfo == null) {
return target.generateCaptchaImage(generateParam); log.warn("滑块验证码缓存不足, genParam:{}", generateParam);
} }else {
// 减1 AtomicInteger pos = posMap.get(generateParam);
if (poll != null) { if (pos != null) {
AtomicInteger pos = posMap.get(generateParam); pos.decrementAndGet();
if (pos != null) { }
pos.decrementAndGet();
} }
}else {
queueMap.putIfAbsent(generateParam, new ConcurrentLinkedQueue<>());
posMap.putIfAbsent(generateParam, new AtomicInteger(0));
} }
return poll; if (captchaInfo == null && requiredGetCaptcha) {
// 直接生成 不走缓存
captchaInfo = target.generateCaptchaImage(generateParam);
}
if (captchaInfo != null){
// 记录最新时间
lastUpdateMap.put(generateParam, System.currentTimeMillis());
}
return captchaInfo;
} }
@Override @Override
@@ -1,17 +1,21 @@
package example; package example;
import cloud.tianai.captcha.template.slider.generator.ImageCaptchaGenerator;
import cloud.tianai.captcha.template.slider.generator.common.constant.CaptchaTypeConstant; import cloud.tianai.captcha.template.slider.generator.common.constant.CaptchaTypeConstant;
import cloud.tianai.captcha.template.slider.generator.common.model.dto.ImageCaptchaInfo; import cloud.tianai.captcha.template.slider.generator.common.model.dto.ImageCaptchaInfo;
import cloud.tianai.captcha.template.slider.generator.common.model.dto.RotateImageCaptchaInfo; import cloud.tianai.captcha.template.slider.generator.common.model.dto.RotateImageCaptchaInfo;
import cloud.tianai.captcha.template.slider.generator.impl.CacheImageCaptchaGenerator;
import cloud.tianai.captcha.template.slider.generator.impl.StandardRotateImageCaptchaGenerator; import cloud.tianai.captcha.template.slider.generator.impl.StandardRotateImageCaptchaGenerator;
import cloud.tianai.captcha.template.slider.resource.ImageCaptchaResourceManager; import cloud.tianai.captcha.template.slider.resource.ImageCaptchaResourceManager;
import cloud.tianai.captcha.template.slider.resource.ResourceStore; import cloud.tianai.captcha.template.slider.resource.ResourceStore;
import cloud.tianai.captcha.template.slider.resource.impl.DefaultImageCaptchaResourceManager; import cloud.tianai.captcha.template.slider.resource.impl.DefaultImageCaptchaResourceManager;
import cloud.tianai.captcha.template.slider.resource.impl.DefaultResourceStore; import cloud.tianai.captcha.template.slider.resource.impl.DefaultResourceStore;
import java.util.concurrent.TimeUnit;
public class StandardRotateCaptchaGeneratorTest { public class StandardRotateCaptchaGeneratorTest {
public static void main(String[] args) { public static void main(String[] args) throws InterruptedException {
ResourceStore resourceStore = new DefaultResourceStore(); ResourceStore resourceStore = new DefaultResourceStore();
// Map<String, Resource> template = new HashMap<>(); // Map<String, Resource> template = new HashMap<>();
// template.put(SliderCaptchaConstant.TEMPLATE_FIXED_IMAGE_NAME, new Resource("file", "C:\\Users\\Thinkpad\\Desktop\\a.png")); // template.put(SliderCaptchaConstant.TEMPLATE_FIXED_IMAGE_NAME, new Resource("file", "C:\\Users\\Thinkpad\\Desktop\\a.png"));
@@ -22,11 +26,15 @@ public class StandardRotateCaptchaGeneratorTest {
ImageCaptchaResourceManager imageCaptchaResourceManager = new DefaultImageCaptchaResourceManager(resourceStore); ImageCaptchaResourceManager imageCaptchaResourceManager = new DefaultImageCaptchaResourceManager(resourceStore);
StandardRotateImageCaptchaGenerator standardRotateImageCaptchaGenerator = new StandardRotateImageCaptchaGenerator(imageCaptchaResourceManager, true); CacheImageCaptchaGenerator standardRotateImageCaptchaGenerator = new CacheImageCaptchaGenerator(new StandardRotateImageCaptchaGenerator(imageCaptchaResourceManager, true),
20, 1000, 100, TimeUnit.MINUTES.toMillis(3));
standardRotateImageCaptchaGenerator.initSchedule();
ImageCaptchaInfo imageCaptchaInfo = standardRotateImageCaptchaGenerator.generateCaptchaImage(CaptchaTypeConstant.ROTATE); ImageCaptchaInfo imageCaptchaInfo = standardRotateImageCaptchaGenerator.generateCaptchaImage(CaptchaTypeConstant.ROTATE);
System.out.println("backgroundImage:" + imageCaptchaInfo.getBackgroundImage()); System.out.println("backgroundImage:" + imageCaptchaInfo.getBackgroundImage());
System.out.println("sliderImage:" + imageCaptchaInfo.getSliderImage()); System.out.println("sliderImage:" + imageCaptchaInfo.getSliderImage());
System.out.println(((RotateImageCaptchaInfo)imageCaptchaInfo).getDegree()); System.out.println(((RotateImageCaptchaInfo)imageCaptchaInfo).getDegree());
TimeUnit.DAYS.sleep(1);
} }
} }