From da1f25f4c190e4504c786b1992f34effe7233865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E6=9F=922012?= <345849402@qq.com> Date: Mon, 10 Feb 2020 20:40:52 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=E5=9F=BA=E4=BA=8E=20netty=20?= =?UTF-8?q?=E7=9A=84=E6=97=B6=E9=97=B4=E8=BD=AE=E7=AE=97=E6=B3=95=20Hashed?= =?UTF-8?q?WheelTimer=20=E5=AE=9E=E7=8E=B0=E7=9A=84=E5=BB=B6=E8=BF=9F?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 11 ++++++ .../delay/{ => jvm}/RedPacketDelayQueue.java | 11 +++--- .../delay/jvm}/RedPacketMessage.java | 2 +- .../queue/delay/jvm/RedPacketQueue.java | 2 -- .../seckill/queue/delay/jvm/TaskRunner.java | 1 - .../netty/RedPacketHashedWheelTimer.java | 35 +++++++++++++++++++ .../queue/delay/netty/RedPacketTimerTask.java | 35 +++++++++++++++++++ .../seckill/web/RedPacketController.java | 2 +- 8 files changed, 87 insertions(+), 12 deletions(-) rename src/main/java/com/itstyle/seckill/queue/delay/{ => jvm}/RedPacketDelayQueue.java (85%) rename src/main/java/com/itstyle/seckill/{common/entity => queue/delay/jvm}/RedPacketMessage.java (98%) create mode 100644 src/main/java/com/itstyle/seckill/queue/delay/netty/RedPacketHashedWheelTimer.java create mode 100644 src/main/java/com/itstyle/seckill/queue/delay/netty/RedPacketTimerTask.java diff --git a/pom.xml b/pom.xml index 4094580..ab9c109 100644 --- a/pom.xml +++ b/pom.xml @@ -136,6 +136,17 @@ sentinel-core 1.6.3 + + org.projectlombok + lombok + 1.18.8 + provided + + + io.netty + netty-common + 4.1.23.Final + spring-boot-seckill diff --git a/src/main/java/com/itstyle/seckill/queue/delay/RedPacketDelayQueue.java b/src/main/java/com/itstyle/seckill/queue/delay/jvm/RedPacketDelayQueue.java similarity index 85% rename from src/main/java/com/itstyle/seckill/queue/delay/RedPacketDelayQueue.java rename to src/main/java/com/itstyle/seckill/queue/delay/jvm/RedPacketDelayQueue.java index 181745f..b9d83ab 100644 --- a/src/main/java/com/itstyle/seckill/queue/delay/RedPacketDelayQueue.java +++ b/src/main/java/com/itstyle/seckill/queue/delay/jvm/RedPacketDelayQueue.java @@ -1,14 +1,11 @@ -package com.itstyle.seckill.queue.delay; +package com.itstyle.seckill.queue.delay.jvm; -import com.itstyle.seckill.common.entity.RedPacketMessage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; -import java.util.concurrent.*; +import java.util.concurrent.DelayQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; /** * 红包过期失效 延迟队列 diff --git a/src/main/java/com/itstyle/seckill/common/entity/RedPacketMessage.java b/src/main/java/com/itstyle/seckill/queue/delay/jvm/RedPacketMessage.java similarity index 98% rename from src/main/java/com/itstyle/seckill/common/entity/RedPacketMessage.java rename to src/main/java/com/itstyle/seckill/queue/delay/jvm/RedPacketMessage.java index 0c2216c..8257729 100644 --- a/src/main/java/com/itstyle/seckill/common/entity/RedPacketMessage.java +++ b/src/main/java/com/itstyle/seckill/queue/delay/jvm/RedPacketMessage.java @@ -1,4 +1,4 @@ -package com.itstyle.seckill.common.entity; +package com.itstyle.seckill.queue.delay.jvm; import java.time.Instant; import java.time.LocalDateTime; diff --git a/src/main/java/com/itstyle/seckill/queue/delay/jvm/RedPacketQueue.java b/src/main/java/com/itstyle/seckill/queue/delay/jvm/RedPacketQueue.java index bd196a7..4c84f98 100644 --- a/src/main/java/com/itstyle/seckill/queue/delay/jvm/RedPacketQueue.java +++ b/src/main/java/com/itstyle/seckill/queue/delay/jvm/RedPacketQueue.java @@ -1,7 +1,5 @@ package com.itstyle.seckill.queue.delay.jvm; -import com.itstyle.seckill.common.entity.RedPacketMessage; - import java.util.concurrent.DelayQueue; /** diff --git a/src/main/java/com/itstyle/seckill/queue/delay/jvm/TaskRunner.java b/src/main/java/com/itstyle/seckill/queue/delay/jvm/TaskRunner.java index 6f63774..65ff42d 100644 --- a/src/main/java/com/itstyle/seckill/queue/delay/jvm/TaskRunner.java +++ b/src/main/java/com/itstyle/seckill/queue/delay/jvm/TaskRunner.java @@ -1,6 +1,5 @@ package com.itstyle.seckill.queue.delay.jvm; -import com.itstyle.seckill.common.entity.RedPacketMessage; import com.itstyle.seckill.common.redis.RedisUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/com/itstyle/seckill/queue/delay/netty/RedPacketHashedWheelTimer.java b/src/main/java/com/itstyle/seckill/queue/delay/netty/RedPacketHashedWheelTimer.java new file mode 100644 index 0000000..eef9e60 --- /dev/null +++ b/src/main/java/com/itstyle/seckill/queue/delay/netty/RedPacketHashedWheelTimer.java @@ -0,0 +1,35 @@ +package com.itstyle.seckill.queue.delay.netty; + +import io.netty.util.HashedWheelTimer; +import io.netty.util.Timer; +import io.netty.util.TimerTask; + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; + +/** + * 基于 netty 的时间轮算法 HashedWheelTimer 实现的延迟任务 + */ +public class RedPacketHashedWheelTimer { + + public static void main(String[] args) throws Exception { + ThreadFactory factory = r -> { + Thread thread = new Thread(r); + thread.setDaemon(true); + thread.setName("RedPacketHashedWheelTimerWorker"); + return thread; + }; + /** + * @param tickDuration - 每tick一次的时间间隔 + * @param unit - tickDuration 的时间单位 + * @param ticksPerWheel - 时间轮中的个数 + */ + Timer timer = new HashedWheelTimer(factory, 1, + TimeUnit.SECONDS, 100); + for(int i=0;i<100;i++){ + TimerTask timerTask = new RedPacketTimerTask(i); + timer.newTimeout(timerTask, i, TimeUnit.SECONDS); + } + Thread.sleep(Integer.MAX_VALUE); + } +} diff --git a/src/main/java/com/itstyle/seckill/queue/delay/netty/RedPacketTimerTask.java b/src/main/java/com/itstyle/seckill/queue/delay/netty/RedPacketTimerTask.java new file mode 100644 index 0000000..f3c12d3 --- /dev/null +++ b/src/main/java/com/itstyle/seckill/queue/delay/netty/RedPacketTimerTask.java @@ -0,0 +1,35 @@ +package com.itstyle.seckill.queue.delay.netty; + +import io.netty.util.Timeout; +import io.netty.util.TimerTask; + +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; + +public class RedPacketTimerTask implements TimerTask { + + private static final DateTimeFormatter F = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); + + /** + * 红包 ID + */ + private final long redPacketId; + + /** + * 创建时间戳 + */ + private final long timestamp; + + public RedPacketTimerTask(long redPacketId) { + this.redPacketId = redPacketId; + this.timestamp = System.currentTimeMillis(); + } + + @Override + public void run(Timeout timeout) { + System.out.println(String.format("任务执行时间:%s,红包创建时间:%s,红包ID:%s", + LocalDateTime.now().format(F), LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault()).format(F), redPacketId)); + } +} diff --git a/src/main/java/com/itstyle/seckill/web/RedPacketController.java b/src/main/java/com/itstyle/seckill/web/RedPacketController.java index ece9499..e5111cb 100644 --- a/src/main/java/com/itstyle/seckill/web/RedPacketController.java +++ b/src/main/java/com/itstyle/seckill/web/RedPacketController.java @@ -1,10 +1,10 @@ package com.itstyle.seckill.web; -import com.itstyle.seckill.common.entity.RedPacketMessage; import com.itstyle.seckill.common.entity.Result; import com.itstyle.seckill.common.redis.RedisUtil; import com.itstyle.seckill.common.utils.DoubleUtil; +import com.itstyle.seckill.queue.delay.jvm.RedPacketMessage; import com.itstyle.seckill.queue.delay.jvm.RedPacketQueue; import com.itstyle.seckill.service.IRedPacketService; import io.swagger.annotations.Api;