mirror of
https://github.com/dromara/RuoYi-Vue-Plus.git
synced 2025-09-24 07:19:46 +08:00
[重磅更新] 增加 轻量级 分布式队列 支持
This commit is contained in:
@ -0,0 +1,83 @@
|
||||
package com.ruoyi.demo.controller.queue;
|
||||
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.utils.redis.QueueUtils;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 有界队列 演示案例
|
||||
* <p>
|
||||
* 轻量级队列 重量级数据量 请使用 MQ
|
||||
* <p>
|
||||
* 集群测试通过 同一个数据只会被消费一次 做好事务补偿
|
||||
* 集群测试流程 在其中一台发送数据 两端分别调用获取接口 一次获取一条
|
||||
*
|
||||
* @author Lion Li
|
||||
* @version 3.6.0
|
||||
*/
|
||||
@Slf4j
|
||||
@Api(value = "有界队列 演示案例", tags = {"有界队列"})
|
||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||
@RestController
|
||||
@RequestMapping("/demo/queue/bounded")
|
||||
public class BoundedQueueController {
|
||||
|
||||
|
||||
@ApiOperation("添加队列数据")
|
||||
@GetMapping("/add")
|
||||
public AjaxResult<Void> add(@ApiParam("队列名") String queueName,
|
||||
@ApiParam("容量") int capacity) {
|
||||
// 用完了一定要销毁 否则会一直存在
|
||||
boolean b = QueueUtils.destroyBoundedQueueObject(queueName);
|
||||
log.info("通道: {} , 删除: {}", queueName, b);
|
||||
// 初始化设置一次即可
|
||||
if (QueueUtils.trySetBoundedQueueCapacity(queueName, capacity)) {
|
||||
log.info("通道: {} , 设置容量: {}", queueName, capacity);
|
||||
} else {
|
||||
log.info("通道: {} , 设置容量失败", queueName);
|
||||
return AjaxResult.error("操作失败");
|
||||
}
|
||||
for (int i = 0; i < 11; i++) {
|
||||
String data = "data-" + i;
|
||||
boolean flag = QueueUtils.addBoundedQueueObject(queueName, data);
|
||||
if (flag == false) {
|
||||
log.info("通道: {} , 发送数据: {} 失败, 通道已满", queueName, data);
|
||||
} else {
|
||||
log.info("通道: {} , 发送数据: {}", queueName, data);
|
||||
}
|
||||
}
|
||||
return AjaxResult.success("操作成功");
|
||||
}
|
||||
|
||||
@ApiOperation("删除队列数据")
|
||||
@GetMapping("/remove")
|
||||
public AjaxResult<Void> remove(@ApiParam("队列名") String queueName) {
|
||||
String data = "data-" + 5;
|
||||
if (QueueUtils.removeBoundedQueueObject(queueName, data)) {
|
||||
log.info("通道: {} , 删除数据: {}", queueName, data);
|
||||
} else {
|
||||
return AjaxResult.error("操作失败");
|
||||
}
|
||||
return AjaxResult.success("操作成功");
|
||||
}
|
||||
|
||||
@ApiOperation("获取队列数据")
|
||||
@GetMapping("/get")
|
||||
public AjaxResult<Void> get(@ApiParam("队列名") String queueName) {
|
||||
String data;
|
||||
do {
|
||||
data = QueueUtils.getBoundedQueueObject(queueName);
|
||||
log.info("通道: {} , 获取数据: {}", queueName, data);
|
||||
} while (data != null);
|
||||
return AjaxResult.success("操作成功");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package com.ruoyi.demo.controller.queue;
|
||||
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.utils.redis.QueueUtils;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 延迟队列 演示案例
|
||||
* <p>
|
||||
* 轻量级队列 重量级数据量 请使用 MQ
|
||||
* 例如: 创建订单30分钟后过期处理
|
||||
* <p>
|
||||
* 集群测试通过 同一个数据只会被消费一次 做好事务补偿
|
||||
* 集群测试流程 两台集群分别开启订阅 在其中一台发送数据 观察接收消息的规律
|
||||
*
|
||||
* @author Lion Li
|
||||
* @version 3.6.0
|
||||
*/
|
||||
@Slf4j
|
||||
@Api(value = "延迟队列 演示案例", tags = {"延迟队列"})
|
||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||
@RestController
|
||||
@RequestMapping("/demo/queue/delayed")
|
||||
public class DelayedQueueController {
|
||||
|
||||
@ApiOperation("订阅队列")
|
||||
@GetMapping("/subscribe")
|
||||
public AjaxResult<Void> subscribe(@ApiParam("队列名") String queueName) {
|
||||
log.info("通道: {} 监听中......", queueName);
|
||||
// 项目初始化设置一次即可
|
||||
QueueUtils.subscribeBlockingQueue(queueName, (String orderNum) -> {
|
||||
// 观察接收时间
|
||||
log.info("通道: {}, 收到数据: {}", queueName, orderNum);
|
||||
});
|
||||
return AjaxResult.success("操作成功");
|
||||
}
|
||||
|
||||
@ApiOperation("添加队列数据")
|
||||
@GetMapping("/add")
|
||||
public AjaxResult<Void> add(@ApiParam("队列名") String queueName,
|
||||
@ApiParam("订单号") String orderNum,
|
||||
@ApiParam("延迟时间(秒)") Long time) {
|
||||
QueueUtils.addDelayedQueueObject(queueName, orderNum, time, TimeUnit.SECONDS);
|
||||
// 观察发送时间
|
||||
log.info("通道: {} , 发送数据: {}", queueName, orderNum);
|
||||
return AjaxResult.success("操作成功");
|
||||
}
|
||||
|
||||
@ApiOperation("删除队列数据")
|
||||
@GetMapping("/remove")
|
||||
public AjaxResult<Void> remove(@ApiParam("队列名") String queueName,
|
||||
@ApiParam("订单号") String orderNum) {
|
||||
if (QueueUtils.removeDelayedQueueObject(queueName, orderNum)) {
|
||||
log.info("通道: {} , 删除数据: {}", queueName, orderNum);
|
||||
} else {
|
||||
return AjaxResult.error("操作失败");
|
||||
}
|
||||
return AjaxResult.success("操作成功");
|
||||
}
|
||||
|
||||
@ApiOperation("销毁队列")
|
||||
@GetMapping("/destroy")
|
||||
public AjaxResult<Void> destroy(@ApiParam("队列名") String queueName) {
|
||||
// 用完了一定要销毁 否则会一直存在
|
||||
QueueUtils.destroyDelayedQueue(queueName);
|
||||
return AjaxResult.success("操作成功");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.ruoyi.demo.controller.queue;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 实体类 注意不允许使用内部类 否则会找不到类
|
||||
*
|
||||
* @author Lion Li
|
||||
* @version 3.6.0
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
public class PriorityDemo {
|
||||
private String name;
|
||||
private Integer orderNum;
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.ruoyi.demo.controller.queue;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* 比较器 注意不允许使用 内部类或匿名类或lambda表达式 会找不到类
|
||||
*
|
||||
* @author Lion Li
|
||||
* @version 3.6.0
|
||||
*/
|
||||
public class PriorityDemoComparator implements Comparator<PriorityDemo> {
|
||||
@Override
|
||||
public int compare(PriorityDemo pd1, PriorityDemo pd2) {
|
||||
return Integer.compare(pd1.getOrderNum(), pd2.getOrderNum());
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package com.ruoyi.demo.controller.queue;
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.utils.redis.QueueUtils;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 优先队列 演示案例
|
||||
* <p>
|
||||
* 轻量级队列 重量级数据量 请使用 MQ
|
||||
* <p>
|
||||
* 集群测试通过 同一个消息只会被消费一次 做好事务补偿
|
||||
* 集群测试流程 在其中一台发送数据 两端分别调用获取接口 一次获取一条
|
||||
*
|
||||
* @author Lion Li
|
||||
* @version 3.6.0
|
||||
*/
|
||||
@Slf4j
|
||||
@Api(value = "优先队列 演示案例", tags = {"优先队列"})
|
||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||
@RestController
|
||||
@RequestMapping("/demo/queue/priority")
|
||||
public class PriorityQueueController {
|
||||
|
||||
@ApiOperation("添加队列数据")
|
||||
@GetMapping("/add")
|
||||
public AjaxResult<Void> add(@ApiParam("队列名") String queueName) {
|
||||
// 用完了一定要销毁 否则会一直存在
|
||||
boolean b = QueueUtils.destroyPriorityQueueObject(queueName);
|
||||
log.info("通道: {} , 删除: {}", queueName, b);
|
||||
// 初始化设置一次即可 此处注意 不允许用内部类或匿名类
|
||||
boolean flag = QueueUtils.trySetPriorityQueueComparator(queueName, new PriorityDemoComparator());
|
||||
if (flag) {
|
||||
log.info("通道: {} , 设置比较器成功", queueName);
|
||||
} else {
|
||||
log.info("通道: {} , 设置比较器失败", queueName);
|
||||
return AjaxResult.error("操作失败");
|
||||
}
|
||||
for (int i = 0; i < 10; i++) {
|
||||
int randomNum = RandomUtil.randomInt(10);
|
||||
PriorityDemo data = new PriorityDemo().setName("data-" + i).setOrderNum(randomNum);
|
||||
if (QueueUtils.addPriorityQueueObject(queueName, data)) {
|
||||
log.info("通道: {} , 发送数据: {}", queueName, data);
|
||||
} else {
|
||||
log.info("通道: {} , 发送数据: {}, 发送失败", queueName, data);
|
||||
}
|
||||
}
|
||||
return AjaxResult.success("操作成功");
|
||||
}
|
||||
|
||||
@ApiOperation("删除队列数据")
|
||||
@GetMapping("/remove")
|
||||
public AjaxResult<Void> remove(@ApiParam("队列名") String queueName,
|
||||
@ApiParam("对象名") String name,
|
||||
@ApiParam("排序号") Integer orderNum) {
|
||||
PriorityDemo data = new PriorityDemo().setName(name).setOrderNum(orderNum);
|
||||
if (QueueUtils.removePriorityQueueObject(queueName, data)) {
|
||||
log.info("通道: {} , 删除数据: {}", queueName, data);
|
||||
} else {
|
||||
return AjaxResult.error("操作失败");
|
||||
}
|
||||
return AjaxResult.success("操作成功");
|
||||
}
|
||||
|
||||
@ApiOperation("获取队列数据")
|
||||
@GetMapping("/get")
|
||||
public AjaxResult<Void> get(@ApiParam("队列名") String queueName) {
|
||||
PriorityDemo data;
|
||||
do {
|
||||
data = QueueUtils.getPriorityQueueObject(queueName);
|
||||
log.info("通道: {} , 获取数据: {}", queueName, data);
|
||||
} while (data != null);
|
||||
return AjaxResult.success("操作成功");
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user