使用sponge+dtm快速搭建一个高性能的电商系统,秒杀抢购和订单架构的设计与实现

本文将展示如何使用 Sponge 框架快速创建一个简易版高性能电商系统,主要实现秒杀抢购和订单功能,并通过分布式事务管理器 DTM 来确保数据一致性。电商系统的架构图如下:

flash-sale-order-cache


这是源码示例eshop,目录下包括了两个一样的代码示例,只是代码结构稍有不同,主要是为了展示说明sponge支持创建不同仓库模式的微服务项目,example-1-multi-repo是适合微服务多仓库(multi-repo),example-2-mono-repo是适合微服务单仓库(mono-repo)。


准备环境

为了构建这个电商系统,准备生成代码工具:

  • Sponge: 快速创建不同类型服务和模块代码。点击 Sponge 安装说明 以获取更多信息。

准备以下依赖服务:

  • DTM:分布式事务管理器,用于保证系统在多服务调用中的数据一致性。
  • Redis:结合 DTM,用作秒杀抢购的缓存。
  • Kafka:作为订单系统的消息队列,用于处理订单异步消息。
  • MySQL:为各个服务提供数据存储。

所有这些服务将运行在虚拟机中,虚拟机的 IP 地址为 192.168.3.37


启动 DTM 服务

DTM 是本系统的核心组件之一,负责管理订单和秒杀抢购的分布式事务。需要启动两个 DTM 服务实例,分别用于 MySQL 和 Redis 存储。

DTM下载地址:https://github.com/dtm-labs/dtm/releases/tag/v1.18.0

服务名端口配置
DTM-MySQLHTTP: 36789, gRPC: 36790
DTM-RedisHTTP: 35789, gRPC: 35790

1. 启动使dtm-mysql服务
  • 在 MySQL 中导入 DTM 需要的表结构:

    • dtmcli.barrier.mysql.sql
    • dtmsvr.storage.mysql.sql
  • 修改 DTM 配置文件 (示例配置文件):

    Store: # specify which engine to store trans status
      Driver: 'mysql'
      Host: '192.168.3.37'
      User: 'root'
      Password: '123456'
      Port: 3306
      Db: 'dtm'
    
    # 使用注册与发现(sponge的dtm驱动已支持etcd、consul、nacos)
    #MicroService:
       #Driver: 'dtm-driver-sponge'
       #Target: 'etcd://127.0.0.1:2379/dtmservice'
       #EndPoint: 'grpc://127.0.0.1:36790'
    
  • 启动 DTM 服务:

    #dtm 服务端口 http: 36789, grpc: 36790 
    ./dtm -c conf.yml
    

2. 启动dtm-redis服务
  • 修改 DTM 配置文件 (示例配置文件):

    Store: # specify which engine to store trans status
        Driver: 'redis'
        Host: '192.168.3.37'
        User: 'default'
        Password: '123456'
        Port: 6379
    
    
    # 修改默认dtm服务端口
    HttpPort: 35789
    GrpcPort: 35790
    
    
    # 如果使用注册与发现(sponge的dtm驱动已支持etcd\consul\nacos),则需要配置如下(使用http协议)
    #MicroService:
       #Driver: 'dtm-driver-sponge'
       #Target: 'etcd://127.0.0.1:2379/dtmservice'
       #EndPoint: 'http://127.0.0.1:35789'
    
  • 启动 DTM 服务:

    #dtm 服务端口 http: 35789, grpc: 35790 
    ./dtm -c conf.yml
    

使用sponge快速构建电商系统

简易版电商系统由以下 8 个微服务组成:

  • eshop_gw:API 网关服务
  • user:用户服务
  • product:商品服务
  • order:订单服务
  • stock:库存服务
  • coupon:优惠券服务
  • pay:支付服务
  • flashSale:秒杀抢购服务

1. 准备各个服务mysql数据库和表

将以下服务对应的数据库表导入 MySQL:

  • user 服务的库和表
  • product 服务的库和表
  • order 服务的库和表
  • stock 服务的库和表
  • coupon 服务的库和表
  • pay 服务的库和表

2. 准备各个服务的protobuf文件

这些protobuf文件给sponge快速创建服务:

  • user 服务的protobuf文件
  • product 服务的protobuf文件
  • order 服务的protobuf文件
  • stock 服务的protobuf文件
  • coupon 服务的protobuf文件
  • pay 服务的protobuf文件
  • flashSale 秒杀抢购服的protobuf文件
  • eshop_gw api 网关服务的protobuf文件

3. 基于protobuf生成gRPC+HTTP混合服务代码

打开sponge的UI页面,切换到菜单Protobuf --> 创建grpc+http服务,填写参数,分别生成7个支持grpc+http混合服务代码user、product、order、stock、coupon、pay、flashSale,如下图所示:

eshop-grpc-http-pb

下载代码后,分别解压各个服务代码到eshop目录下。

注:在生成代码页面如果参数开启了大仓库类型,表示创建的服务适合微服务单仓库(mono-repo)模式。


4. 基于mysql表生成CRUD代码

打开sponge的UI页面,切换到菜单Public --> 生成service+handler CRUD代码,填写参数,分别生成user、product、order、stock、coupon、pay服务的CRUD代码,如下图所示:

eshop-service-handler

下载代码后,分别解压CRUD代码,把CRUD代码(api和internal两个目录)移动到对应服务代码中(如果提示proto文件重复,忽略即可)。

注:在生成代码页面如果参数开启了大仓库类型,表示创建的服务适合微服务单仓库(mono-repo)模式。


5. 基于protobuf生成api网关服务代码

打开sponge的UI页面,切换到菜单Protobuf --> 创建grpc网关服务,填写参数,生成eshop_gw的api网关服务代码,如下图所示:

eshop-grpc-gw-pb

下载代码后,解压服务代码到eshop目录下。

为了让eshop_gw服务可以连接各个服务,需要生成连接代码。打开sponge的UI页面,切换到菜单Public --> 生成grpc连接代码,填写参数,生成eshop_gw的连接各个grpc代码,如下图所示:

eshop-grpc-conn

下载代码后,解压代码,把连接代码(internal目录)移动到eshop_gw服务代码中。

注:在生成代码页面如果参数开启了大仓库类型,表示创建的服务适合微服务单仓库(mono-repo)模式。


6. 填写业务逻辑代码

到此为止,服务框架已经基本搭建完毕。接下来分别在各服务的 internal/service 目录下编写实际的业务逻辑代码。


7. 启动服务

启动服务前先修改各个服务的配置文件,修改端口、数据库连接等信息。各个服务默认的http端口(8080),grpc端口(8282),因为在同一台主机本地(本地测试ip为192.168.3.90)运行,为了防止端口冲突,所以在配置已经修改了各个服务的端口(在configs/xxx.yml目录下和api/xxx/v1/xxx.proto中修改端口),下面是已修改的端口:

服务协议HTTP 端口gRPC 端口
eshop_gwHTTP8080-
userHTTP, gRPC3008030082
productHTTP, gRPC3018030182
orderHTTP, gRPC3028030282
stockHTTP, gRPC3038030382
couponHTTP, gRPC3048030482
payHTTP, gRPC3058030582
flashSaleHTTP, gRPC3068030682

注:如果在容器或不同机器上运行,不需要修改默认的端口,只需修改映射端口。


测试与验证

单个服务测试

各个服务启动成功之后,先验证单个服务是否正常运行,分别测试user、product、order、stock、coupon、pay、flashSale这7个服务的api。

在浏览器访问 http://localhost:<服务端口>/apis/swagger/index.html,验证各个服务的api是否正常,除了在swaggers页面测试api,也可以在各个服务下的internal/service/xxx_client_test.go 文件中填写参数后运行测试grpc api。


集成测试

各个服务测试正常后,通过eshop_gw的api网关服务测试整个系统是否正常运行。在浏览器访问api网关服务的swagger页面,http://localhost:8080/apis/swagger/index.html,如下图所示:

eshop-gw-swagger


测试提交订单 API

  • 提交订单使用了dtm的分布式事务模式saga,主要验证创建订单、扣减库存、创建支付订单、优惠券数据是否一致。

  • 为了避免库存不足导致订单失败,测试前先设置库存,在swagger页面找到设置产品库存api,填写参数,例如产品id为1、库存为10

    {
      "productID": 1,
      "stock": 10
    }
    
  • 测试提交订单分别请求无缓冲队列和缓冲队列的api,在swagger页面找到对应的api,填写参数,例如用户id为1、产品id为1、产品数量为1、订单金额为100

    {
      "userID": 1,
      "productID": 1,
      "productCount": 1,
      "amount": 100,
      "couponID": 0
    }
    

注:如果设置couponID不为0,表示使用优惠券,如果优惠券失效或过期,会导致订单失败。如果想使得订单成功的话,在swagger页面找到创建优惠券api创建新的优惠券,然后获取得到优惠券id,填写到提交订单api的couponID字段。


测试秒杀抢购API

  • 秒杀抢购使用了kafka的消息队列、dtm+redis的二阶段消息、dtm+mysql的saga两个分布式事务模式,主要验证秒杀抢购、扣减库存、创建订单、扣减库存、创建支付订单数据是否一致。

  • 为了避免库存不足导致订单失败,测试前先设置库存,在swagger页面找到设置产品库存api,填写参数,例如产品id为1、库存为10

    {
     "productID": 1,
     "stock": 10
    }
    
  • 测试秒杀抢购api,验证数据是否一致,在swagger页面找到秒杀抢购api,填写参数,例如用户id为1、产品id为1

    {
      "userID": 1,
      "productID": 1,
      "amount": 100
    }
    

压力测试

这里使用压力测试工具k6对eshop_gw的api网关服务进行压力测试,验证系统在高并发场景下的性能。压测前先设置足够的库存数量,否则会导致订单失败。

  1. 压测提交订单 API的场景,使用k6的脚本 submitOrder.js ,运行命令如下:

    # 1000个虚拟用户,持续10秒
    k6 run --vus 1000 --duration 10s test/k6/submitOrder.js
    
    # 或者,指定虚拟用户数和请求迭代次数,例如1000个虚拟用户共同完成迭代请求100000次
    k6 run -u 1000 -i 100000 submit_order.js
    
  2. 压测秒杀抢购 API的场景,使用k6的脚本 flashSale.js ,运行命令如下:

    # 10000个虚拟用户,持续1秒
    k6 run --vus 10000 --duration 1s test/k6/flashSale.js
    

注:压测结果与机器配置、网络环境、数据库配置等因素有关,请根据实际情况进行调整。


总结

这个例子展示了如何快速构建一个高性能的电子商务系统。系统架构分为用户、产品、订单、库存、支付、秒杀抢购等服务,每个服务代码(不含业务逻辑代码)都可以由Sponge生成,使用DTM保证高并发秒杀、订单场景下的数据一致性。通过集成Redis和Kafka,系统还具有高效的缓存和消息队列支持,提高了整体性能和可扩展性。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

kafka-windows集群部署

kafka-windows集群部署目录 文章目录 kafka-windows集群部署目录前言一、复制出来四个kafka文件夹二、修改集群每个kafka的配置文件四、启动zookeeper&#xff0c;kafka集群 前言 部署本文步骤可以先阅读这一篇博客&#xff0c;这篇是关于单机kafka部署测试的。本文用到的文件…

Android 电源管理各个版本的变动和限制

由于Android设备的电池容量有限&#xff0c;而用户在使用过程中会进行各种高耗电操作&#xff0c;如网络连接、屏幕亮度调节、后台程序运行等&#xff0c;因此需要通过各种省电措施来优化电池使用‌&#xff0c;延长电池续航时间&#xff0c;提高用户体验&#xff0c;并减少因电…

基于LORA的一主多从监测系统_AHT20温湿度传感器

1&#xff09;AHT20温湿度传感器 这个传感器&#xff0c;网上能找到的资料还是比较多的&#xff0c;我们使用的是HAL硬件i2c&#xff0c;相比于模拟i2c&#xff0c;我们不需要过于关注时序问题&#xff0c;我们只需要关心如何获取数据以及数据如何处理&#xff0c;下面以数据手…

Prometheus之Pushgateway使用

Pushgateway属于整个架构图的这一部分 The Pushgateway is an intermediary service which allows you to push metrics from jobs which cannot be scraped. The Prometheus Pushgateway exists to allow ephemeral and batch jobs to expose their metrics to Prometheus. S…

MATLAB APPdesigner中的日期选择器怎样实时显示时间

文章目录 1.问题描述2.代码设置代码示例解释 1.问题描述 我们在做MATLAB的时候&#xff0c;一般需要在APP界面中加上时间显示&#xff0c;像下图中的右上角&#xff0c;在组件中有日期选择器&#xff0c;但是这个并不是实时显示的&#xff0c;我们还需要自己进行设置。 2.代码…

(11)MATLAB莱斯(Rician)衰落信道仿真2

文章目录 前言一、莱斯衰落信道仿真模型二、仿真代码与结果1.仿真代码2.仿真结果画图 三、后续&#xff1a;四、参考文献&#xff1a; 前言 首先给出莱斯衰落信道仿真模型&#xff0c;该模型由直射路径分量和反射路径分量组成&#xff0c;其中反射路径分量由瑞利衰落信道模型构…

力扣之603.连续空余座位

文章目录 1. 603.连续空余座位1.1 题干1.2 准备数据1.3 思路分析1.4 解法1.5 结果截图 1. 603.连续空余座位 1.1 题干 表: Cinema ----------------- | Column Name | Type | ----------------- | seat_id | int | | free | bool | ----------------- Seat_id 是该表的自动递…

宏队列和微队列

1、javascript是一个单线程语言。 javascript 语言的目的&#xff08;待补充&#xff09; 2、主线程执行完成之后&#xff0c;再执行微队列&#xff0c;微队列执行完成后再执行宏队列 3、promise的构造函数传入的回调函数是同步执行 4、promise的then函数会直接加入微队列&…

zookeeper选举kafka集群的controller

zookeeper选举kafka集群的controller目录 文章目录 zookeeper选举kafka集群的controller目录前言一、实操体验controller的选举二、模拟controller选举四、删除controller节点 前言 kafka集群的controller是kafka集群中一个有特殊作用的broker&#xff0c;负责整个kafka集群的…

用java编写飞机大战

游戏界面使用JFrame和JPanel构建。背景图通过BG类绘制。英雄机和敌机在界面上显示并移动。子弹从英雄机发射并在屏幕上移动。游戏有四种状态&#xff1a;READY、RUNNING、PAUSE、GAMEOVER。状态通过鼠标点击进行切换&#xff1a;点击开始游戏&#xff08;从READY变为RUNNING&am…

Nginx06-静态资源部署

零、文章目录 Nginx06-静态资源部署 1、静态资源概述 静态资源&#xff1a;是在Web开发中不经常改变的文件&#xff0c;比如图片、CSS样式表、JavaScript脚本文件等。这些资源通常是预先编译好的&#xff0c;不需要服务器端的动态处理。动态资源&#xff1a;是在Web开发中需…

前端编程艺术(3)---JavaScript

目录 1.JavaScript 1.输出 2.变量和数据类型 3.运算符 4.数组 5.函数 6.面向对象 7.ES6面向对象 2.BOM 1.document对象 3.DOM 4.JSON 1.JavaScript JavaScript是一种脚本编程语言&#xff0c;通常用于为网页增加交互性和动态效果。它是一种高级语言&#xff…

面试(十)

目录 一. 单元测试 二. FreeRTOS和裸机哪个实时性好&#xff1f; 三. 怎么判断某个程序的运行时间 四. 函数指针 五. 全局变量被线程使用冲突 5.1 使用互斥锁 5.2 使用读写锁 5.3 使用原子操作 六. 局部变量没有初始化是什么值 七. uint_8 n 255 , n等于多少 八. …

【springboot】简易模块化开发项目整合Swagger2

接上一项目【springboot】简易模块化开发项目整合MyBatis-plus&#xff0c;进行拓展项目 1.新建模块 右键项目→New→Module&#xff0c;新建一个模块 父项目选择fast-demo&#xff0c;命名为fast-demo-config&#xff0c;用于存放所有配置项 添加后&#xff0c;项目结构如图…

计算机网络:物理层 —— 信道复用技术

文章目录 信道信道复用技术信道复用技术的作用基本原理常用的信道复用技术频分复用 FDM时分复用 TDM波分复用 WDM码分复用 CDM码片向量基本原理 信道 信道是指信息传输的通道或介质。在通信中&#xff0c;信道扮演着传输信息的媒介的角色&#xff0c;将发送方发送的信号传递给…

Flink 03 | 数据流基本操作

Flink数据流结构 DataStream 转换 通常我们需要分析的业务数据可能存在如下问题&#xff1a; 数据中包含一些我们不需要的数据 数据格式不方面分析 因此我们需要对原始数据流进行加工&#xff0c;比如过滤、转换等操作才可以进行数据分析。 “ Flink DataStream 转换主要作…

PHP变量(第④篇)

本栏目教学是php零基础到精通&#xff0c;如果你还没有安装php开发工具请查看下方链接&#xff1a; Vscode、小皮面板安装-CSDN博客 今天来讲一讲php中的变量&#xff0c;变量是用于存储信息的"容器"&#xff0c;这些数据可以在程序执行期间被修改&#xff08;即其…

nginx配置https加密

安装nginx 官网&#xff1a; https://nginx.org/ yum安装&#xff1a; https://nginx.org/en/linux_packages.html /etc/yum.repos.d/nginx.repo [nginx-stable] namenginx stable repo baseurlhttp://nginx.org/packages/centos/$releasever/$basearch/ gpgcheck1 enabled1 …

(C语言贪吃蛇)15.贪吃蛇吃食物

目录 前言 注意事项⚠️ 效果预览 实现方法 运行效果 新的问题&#x1f64b; 最终效果 总结 前言 我们上一节实现了解决了贪吃蛇不合理走位的情况&#xff0c;不理解的再回去看看(传送门&#xff1a;解决贪吃蛇不合理走位)&#xff0c;那么贪吃蛇自然是要吃食物的啊&…

【GEE学习第三期】GEE常用函数总结

【GEE学习第三期】GEE常用函数总结 数据统计类ee.List.sequence函数 图像处理类ee.Geometry类‌defaultVisualizationVis函数 数据输入输出数值与绘图导出影像 参考 数据统计类 ee.List.sequence函数 用法如下&#xff1a; ee.List.sequence &#xff08;开始&#xff0c;结…