RocketMQ实现一个简单的秒杀接口

news2024/11/25 2:04:30

预设场景:

“秒杀”这一词多半出现在购物方面,但是又不单单只是购物,比如12306购票和学校抢课(大学生的痛苦)也可以看成一个秒杀。秒杀应该是一个“三高”,这个三高不是指高血脂,高血压和高血糖。而是指“高并发”,“高性能”和“高可用”。

假设有一百个库存商品需要抢购,可以试用mq进行削峰,防止宕机。
在这里插入图片描述
在这里插入图片描述

1.创建rocketmq server模块。

1.1. 配置相关文件

  1. springboot2.6.13版本
    在这里插入图片描述
  2. xml依赖
 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- rocketmq -->
        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-spring-boot-starter</artifactId>
            <version>2.2.3</version>
        </dependency>

    </dependencies>
  1. application.properties相关配置
#应用名
spring.application.name=seckill-server
server.port=8081
rocketmq.producer.groupName=${spring.application.name}
# mq的nameserver地址
rocketmq.producer.namesrvAddr=127.0.0.1:9876

1.2. controller代码

  1. 这里我使用1000冗余数量,控制接口访问数,正常来讲,应该使用中间件去同步真实库存,我这里省略了。
  2. 我这里的业务逻辑比较简单,可以根据自身需要更改逻辑。
@RestController
public class OpenOrderController{
    int redundancy = 1000;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @GetMapping("/secKill")
   public String secKill(String id){
        redundancy--;
        if(redundancy > 0){
            rocketMQTemplate.convertAndSend("seckill-topic", id);
            return id+"正在抢购中请等待";
        }else{
            return "商品已售完";
        }
        
   }
}

2.创建rocketmq-consumer模块

1.1. 配置相关文件

  1. xml依赖配置
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.rocketmq</groupId>
            <artifactId>rocketmq-spring-boot-starter</artifactId>
            <version>2.2.3</version>
        </dependency>
  1. application.properties相关配置
spring.application.name=seckill-consumer
server.port=8082
rocketmq.consumer.group=${spring.application.name}
rocketmq.name-server=127.0.0.1:9876

1.2. controller代码

这里是真实的消息处理,springboot的监听处理极其简化了监听器的配置过程。
这里吧库存设置成一个简单的成员变量,实际上在分布式项目中可能使用redis同步真实库存。

在真实的场景中我们可以在这一步进行鉴权,是不是目标用户(黑户),生成订单等,发送短信(回调执行结果)等操作。由于已经由MQ进行了流量削峰,这一步可以进行更多的操作,有条不紊的进行业务逻辑的执行,

下面是示例代码:

@Component
@RocketMQMessageListener(topic = "seckill-topic", consumerGroup = "seckill-consumer-group")
public class SeckillConsumer implements RocketMQListener<String> {
    int realInventory = 100;
    @Override
    public void onMessage(String id) {
        // 处理秒杀请求
        // 执行库存扣减和订单生成等操作
        // 返回秒杀结果给用户
        realInventory--;
        if(realInventory >= 0){
            System.out.println("当前商品剩余"+realInventory);
            System.out.println(id + "抢到商品");
        }else{
            System.out.println("商品已售完");
        }

    }
}

3.创建测试示例

  1. 使用1w线程发送1w请求进行接口测试。
public class HttpTest {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(1000);
        for (int i = 0; i < 10000; i++) {
            executorService.execute(() -> {
                try {
                    URL url = new URL("http://localhost:8081/secKill?id=" + UUID.randomUUID().toString());
                    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    connection.connect();
                    int responseCode = connection.getResponseCode();
                    if (responseCode == HttpURLConnection.HTTP_OK) {
                        System.out.println("Request success!");
                    } else {
                        System.out.println("Request failed!");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }
        executorService.shutdown();
    }
}

  1. 测试结果
    测试代码控制台
    在这里插入图片描述
    生产者控制台
    在这里插入图片描述
    消费者控制台
    在这里插入图片描述

这里抛出一个问题?
为什么会出现消息的乱序消费呢?如何实现顺序消费呢?

答:springboot默认是异步多线程消费的,无法保证顺序。
consumeMode = ConsumeMode.ORDERLY ConsumeMode.ORDERLY的作用是让消费者单线程顺序接收消息,从而保证消息的全局顺序

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/584982.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据中间件 - MyCat2 配置文件说明

数据中间件 - MyCat2 配置文件说明 本章内容基于 MyCat2 版本. 会对 Mycat 中的配置文件作用,以及结合 Mycat 的一些概念进行介绍,比起一上来就盲目的开始操作,然后遇到各种问题,先从全局进行了解对提高效率是有帮助的. MyCat 的配置文件都存放在 conf 路径下. server.jso…

学习Node.js的9大理由以及日常开发中的14个高级特性和代码示例分享

目录 为什么要学Nodejs 1. 高级事件处理&#xff1a;事件驱动机制 2. 非阻塞I/O 3. 异步编程 4. 模块系统 5. 流式数据处理 6. 跨平台支持 7. 高性能网络编程 8. 调试工具 9. 第三方模块 10. 升级 V8 引擎至 10.7 11. 函数式编程 12. 高级路由 13. 试验 Node wat…

国内免费可用的ChatGPT网页版

ChatGPT 一、ChatGPT是个啥&#xff1f;二、16个国内免费的ChatGPT网站。三、ChatGPT使用方式 一、ChatGPT是个啥&#xff1f; chat&#xff1a;表示“聊天”。 GPT&#xff1a;则是Generative、Pre-trained、Transformer的缩写&#xff0c;表示“预训练语言模型”&#xff0…

【Unity100个实用小技巧】同一个Canvas下的UI顺序通过代码如何修改

☀️博客主页&#xff1a;CSDN博客主页&#x1f4a8;本文由 萌萌的小木屋 原创&#xff0c;首发于 CSDN&#x1f4a2;&#x1f525;学习专栏推荐&#xff1a;面试汇总❗️游戏框架专栏推荐&#xff1a;游戏实用框架专栏⛅️点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd;&#…

三维场景重建经典论文详解

来源&#xff1a;投稿 作者&#xff1a;小灰灰 编辑&#xff1a;学姐 论文标题&#xff1a; 《REAL-TIME INDOOR SCENE RECONSTRUCTION WITH RGBD AND INERTIA INPUT》 论文链接: https://arxiv.org/pdf/2008.00490.pdf https://github.com/CWanli/RecoNet 数据集&#xff1a;P…

停车系统多位多车算法

1、算法代码 下面代码是伪Java代码&#xff0c;看得懂就行。 //查询当前车牌号对应的车主的其他的车牌号的入场纪录&#xff0c;根据时间倒叙排列。 List<Record> comeRecords mapper.selectFromDB; //车主所有的在场车辆数量-车主拥有车位数量 等于需要计费的车辆数量…

虚拟机NAT模式下修改linux静态ip

首先修改VMware的虚拟网络编辑器&#xff0c;NAT设置-> 设置网关&#xff0c;一般ip的第四部分网关为2&#xff0c;第三部分自己设置。 然后设置自己windows电脑 右键属性里面的ipv4&#xff0c;设置为静态的&#xff0c;dns除了对应网关还加一个通用dns 8.8.8.8。 这些外…

基于Q-Table的强化学习笔记

基于Q-Table的强化学习笔记 1 几个概念1.1 状态空间 S S S和动作空间 A A A1.2 奖励 R R R1.3 价值函数与Q-Table1.4 马尔可夫性 2 基于Q-Table的强化学习算法2.1 SARSA算法2.2 Q-learning算法 1 几个概念 最近也从小白入手看了些强化学习(Reinforcement Learning&#xff0c;…

中国人民大学与加拿大女王大学金融硕士——每天都要优于过去的自己,加油!

职场中拉开人与人之间差距的&#xff0c;往往是日复一日微小的积累。满足已取得的成就会让人停滞不前&#xff0c;一旦停止学习&#xff0c;人就会止步不前。懂得持续学习、终生成长的人&#xff0c;能保持积极进取的状态。金融行业的你有计划来人民大学与加拿大女王大学金融硕…

累积运行时间功能块(SCL语言)

设备累积运行时间功能块梯形图源代码请参看下面的文章博客: SMART PLC设备累计运行时间功能块_RXXW_Dor的博客-CSDN博客功能块非常简单,没有什么特别需要说明的,方法不唯一仅供参考。https://blog.csdn.net/m0_46143730/article/details/129170452方法始终不唯一,受限于当…

【c】vscode c/c++环境配置

文章目录 1 mingw下载及配置1.1 mingw下载1.2 环境变量配置1.3 gdb安装 2 vscode c插件安装3 vscode文件配置 1 mingw下载及配置 1.1 mingw下载 https://sourceforge.net/projects/mingw-w64/files/ 1.2 环境变量配置 1.3 gdb安装 我下载的mingw未安装gdb调试 cmd执行: …

vue3 项目实践总结

一、挂载全局变量 1.1 main.js 中挂载 // 引入全局变量 import api from /api;const app createApp(App);// 挂载全局变量 app.config.globalProperties.$API api;app.use(store).use(router).use(ElementPlus).use(Vant).mount(#app);1.2 组件中获取 方法一 推荐使用proxy…

研发工程师玩转Kubernetes——非定时任务

在《研发工程师玩转Kubernetes——自动扩缩容》一文中&#xff0c;我们使用在本地使用wrk进行了压力测试。如果我们希望在容器中运行&#xff0c;该怎么做呢&#xff1f; 构建/推送wrk镜像 Dockerfile如下。主要就是在Ubuntu22中安装wrk。 From ubuntu:22.04 RUN apt-get up…

【Nodejs】Node-js笔记

Node.js 文章目录 Node.js一、Node.js概述1.1、介绍1.2、官网1.3、Node.js应用场景1.4、安装Node.js1.5、npm包管理器1.5.1、介绍1.5.2、切换npm源1.5.3、生成JSON配置文件1.5.4、查看当前安装的树形模块1.5.5、安装模块1.5.6、自定义脚本命令1.5.7 、自动重启应用 1.6、模块化…

VehicleHal.java - fwk层对应VehicleService

VehicleHal.java - fwk层对应VehicleService 1、VehicleHal.java初始化1.1 hal服务区分1.2 简要时序图 2、PowerHalService为例2.1 PowerHalService初始化和订阅2.2 简要时序图 android12-release 【IVI】VehicleService启动 【IVI】车载设备硬件抽象层VHAL 【IVI】CarService启…

【人脸识别】insightface 使用记录和搭建服务注意点和坑 从0到1

文章目录 前言1.开始1.1 前置1.2 再次运行&#xff0c;人脸检测跑通1.3 人脸特征抽取1.3.1 模型下载1.3.2 重新跑一下检测和识别1.3.3 人脸监测返回值分析1.3.4 计算相似度 1.4 全流程的相似度 2. 业务化人脸识别 前言 人脸识别项目&#xff0c;再走一遍。之前是公司老人留下的…

HTML+CSS实训——Day05——JavaScript基础知识点

前言 上一周我们只做了静态页面&#xff0c;这周开始要学js了&#xff0c;那我们先来认识一下他的语法和变量吧。 知识点 变量定义 学习了var还有console.log()输出变量 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8&…

点云配准算法综述-完整解读

点云配准的挑战 同源点云配准 同源点云的配准是指从同一类型的传感器,但在不同的时间或视角下获取的点云在进行配准问题中存在的挑战,其主要包含了 噪声和离群值。在不同的采集时间,环境和传感器噪声是不同的,采集到的点云在同一三维位置附近会包含噪声和异常值。部分重叠…

全网最火爆,从接口测试到接口自动化测试总结,卷王进阶高级...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 Python接口自动化测…

设计模式之美-为什么基于接口而非实现编程?有必要为每个类都定义接口吗?

我愿意称之为最强设计书籍之一。看完这篇文章使我对代码编写有了新的思考。值得注意的是文章全篇写的是伪代码&#xff0c;并没有真正实现方法的逻辑&#xff0c;不过这样反而有利于逻辑的理解。 在上一节课中&#xff0c;我们讲了接口和抽象类&#xff0c;以及各种编程语言是如…