会员登录|免费注册|忘记密码|管理入口 返回主站||保存桌面|手机浏览|联系方式|购物车
2.2 SpringBoot整合RocketMQ
2024-12-24IP属地 湖北0

模拟电商网站购物场景中的【下单】和【支付】业务

###1)下单

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-49XNkX9g-1627787820381)(img/下单组件图.png)]

  1. 用户请求订单系统下单
  2. 订单系统通过RPC调用订单服务下单
  3. 订单服务调用优惠券服务,扣减优惠券
  4. 订单服务调用调用库存服务,校验并扣减库存
  5. 订单服务调用用户服务,扣减用户余额
  6. 订单服务完成确认订单

###2)支付

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-79j0Klbi-1627787820384)(img/支付组件图.png)]

  1. 用户请求支付系统
  2. 支付系统调用第三方支付平台API进行发起支付流程
  3. 用户通过第三方支付平台支付成功后,第三方支付平台回调通知支付系统
  4. 支付系统调用订单服务修改订单状态
  5. 支付系统调用积分服务添加积分
  6. 支付系统调用日志服务记录日志

问题1

用户提交订单后,扣减库存成功、扣减优惠券成功、使用余额成功,但是在确认订单操作失败,需要对库存、库存、余额进行回退。

如何保证数据的完整性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y47HiSGx-1627787820386)(img/下单失败流程图.png)]

使用MQ保证在下单失败后系统数据的完整性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JH8SqNa7-1627787820389)(img/下单时序图(2)].png)

###问题2

用户通过第三方支付平台(支付宝、微信)支付成功后,第三方支付平台要通过回调API异步通知商家支付系统用户支付结果,支付系统根据支付结果修改订单状态、记录支付日志和给用户增加积分。

商家支付系统如何保证在收到第三方支付平台的异步通知时,如何快速给第三方支付凭条做出回应

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9xA5I4cM-1627787820391)(img/支付流程.png)]

通过MQ进行数据分发,提高系统处理性能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-odBTFhaZ-1627787820392)(img/支付成功数据分发流程图.png)]

  • SpringBoot
  • Dubbo
  • Zookeeper
  • RocketMQ
  • Mysql

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QrqQUCgb-1627787820393)(img/项目结构图.png)]

下载rocketmq-spring项目

将rocketmq-spring安装到本地仓库

 

2.2.1 消息生产者

1)添加依赖
 
2)配置文件
 
3)启动类
 
4)测试类
 

2.2.2 消息消费者

1)添加依赖

同消息生产者

2)配置文件

同消息生产者

3)启动类
 
4)消息监听器
 
 

下载dubbo-spring-boot-starter依赖包

将安装到本地仓库

 

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z0245bPe-1627787820394)(…/%E6%96%87%E6%A1%A3/img/dubbo.png)]

2.3.1 搭建Zookeeper集群

1)准备工作
  1. 安装JDK
  2. 将Zookeeper上传到服务器
  3. 解压Zookeeper,并创建data目录,将conf下的zoo_sample.cfg文件改名为zoo.cfg
  4. 建立,将解压后的Zookeeper复制到以下三个目录
 
  1. 配置每一个 Zookeeper 的 dataDir(zoo.cfg) clientPort 分别为 2181 2182 2183

    修改

 

​ 修改/usr/local/zookeeper-cluster/zookeeper-2/conf/zoo.cfg

 

​ 修改/usr/local/zookeeper-cluster/zookeeper-3/conf/zoo.cfg

 
2)配置集群
  1. 在每个 zookeeper 的 data 目录下创建一个 myid 文件,内容分别是 1、2、3 。这个文件就是记录每个服务器的 ID

  2. 在每一个 zookeeper 的 zoo.cfg 配置客户端访问端口(clientPort)和集群服务器 IP 列表。

    集群服务器 IP 列表如下

 

解释:server.服务器 ID=服务器 IP 地址:服务器之间通信端口:服务器之间投票选举端口

3)启动集群

启动集群就是分别启动每个实例。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-POeMIEKU-1627787820396)(…/%E6%96%87%E6%A1%A3/img/zk.png)]

2.3.2 RPC服务接口

 

2.3.3 服务提供者

1)添加依赖
 
2)配置文件
 
3)启动类
 
4)服务实现
 

2.3.4 服务消费者

1)添加依赖
 
2)配置文件
 
3)启动类
 
4)Controller
 
 
 

1)优惠券表

FieldTypeCommentcoupon_idbigint(50) NOT NULL优惠券IDcoupon_pricedecimal(10,2) NULL优惠券金额user_idbigint(50) NULL用户IDorder_idbigint(32) NULL订单IDis_usedint(1) NULL是否使用 0未使用 1已使用used_timetimestamp NULL使用时间

2)商品表

FieldTypeCommentgoods_idbigint(50) NOT NULL主键goods_namevarchar(255) NULL商品名称goods_numberint(11) NULL商品库存goods_pricedecimal(10,2) NULL商品价格goods_descvarchar(255) NULL商品描述add_timetimestamp NULL添加时间

3)订单表

FieldTypeCommentorder_idbigint(50) NOT NULL订单IDuser_idbigint(50) NULL用户IDorder_statusint(1) NULL订单状态 0未确认 1已确认 2已取消 3无效 4退款pay_statusint(1) NULL支付状态 0未支付 1支付中 2已支付shipping_statusint(1) NULL发货状态 0未发货 1已发货 2已退货addressvarchar(255) NULL收货地址consigneevarchar(255) NULL收货人goods_idbigint(50) NULL商品IDgoods_numberint(11) NULL商品数量goods_pricedecimal(10,2) NULL商品价格goods_amountdecimal(10,0) NULL商品总价shipping_feedecimal(10,2) NULL运费order_amountdecimal(10,2) NULL订单价格coupon_idbigint(50) NULL优惠券IDcoupon_paiddecimal(10,2) NULL优惠券money_paiddecimal(10,2) NULL已付金额pay_amountdecimal(10,2) NULL支付金额add_timetimestamp NULL创建时间confirm_timetimestamp NULL订单确认时间pay_timetimestamp NULL支付时间

4)订单商品日志表

FieldTypeCommentgoods_idint(11) NOT NULL商品IDorder_idvarchar(32) NOT NULL订单IDgoods_numberint(11) NULL库存数量log_timedatetime NULL记录时间

5)用户表

FieldTypeCommentuser_idbigint(50) NOT NULL用户IDuser_namevarchar(255) NULL用户姓名user_passwordvarchar(255) NULL用户密码user_mobilevarchar(255) NULL手机号user_scoreint(11) NULL积分user_reg_timetimestamp NULL注册时间user_moneydecimal(10,0) NULL用户余额

6)用户余额日志表

FieldTypeCommentuser_idbigint(50) NOT NULL用户IDorder_idbigint(50) NOT NULL订单IDmoney_log_typeint(1) NOT NULL日志类型 1订单付款 2 订单退款use_moneydecimal(10,2) NULL操作金额create_timetimestamp NULL日志时间

7)订单支付表

FieldTypeCommentpay_idbigint(50) NOT NULL支付编号order_idbigint(50) NULL订单编号pay_amountdecimal(10,2) NULL支付金额is_paidint(1) NULL是否已支付 1否 2是

8)MQ消息生产表

FieldTypeCommentidvarchar(100) NOT NULL主键group_namevarchar(100) NULL生产者组名msg_topicvarchar(100) NULL消息主题msg_tagvarchar(100) NULLTagmsg_keyvarchar(100) NULLKeymsg_bodyvarchar(500) NULL消息内容msg_statusint(1) NULL0:未处理;1:已经处理create_timetimestamp NOT NULL记录时间

###9)MQ消息消费表

FieldTypeCommentmsg_idvarchar(50) NULL消息IDgroup_namevarchar(100) NOT NULL消费者组名msg_tagvarchar(100) NOT NULLTagmsg_keyvarchar(100) NOT NULLKeymsg_bodyvarchar(500) NULL消息体consumer_statusint(1) NULL0:正在处理;1:处理成功;2:处理失败consumer_timesint(1) NULL消费次数consumer_timestamptimestamp NULL消费时间remarkvarchar(500) NULL备注

shop系统基于Maven进行项目管理

3.1.1 工程浏览

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YLUq5D0g-1627787820397)(img/项目初始化.png)]

  • 父工程:shop-parent
  • 订单系统:shop-order-web
  • 支付系统:shop-pay-web
  • 优惠券服务:shop-coupon-service
  • 订单服务:shop-order-service
  • 支付服务:shop-pay-service
  • 商品服务:shop-goods-service
  • 用户服务:shop-user-service
  • 实体类:shop-pojo
  • 持久层:shop-dao
  • 接口层:shop-api
  • 工具工程:shop-common

共12个系统

3.1.2 工程关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ndxrPyAS-1627787820399)(img/项目结构图.png)]

1)代码生成

使用Mybatis逆向工程针对数据表生成CURD持久层代码

###2)代码导入

  • 将实体类导入到shop-pojo工程
  • 在服务层工程中导入对应的Mapper类和对应配置文件
  • ID生成器

    IDWorker:Twitter雪花算法

  • 异常处理类

    CustomerException:自定义异常类

    CastException:异常抛出类

  • 常量类

    ShopCode:系统状态类

  • 响应实体类

    Result:封装响应状态和响应信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4DIEQSYk-1627787820400)(img/下单时序图(2)].png)

1)接口定义

  • IOrderService
 

###2)业务类实现

 

###3)校验订单

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cl25CfaY-1627787820401)(img/校验订单(2)].png)

 

###4)生成预订单

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DAxM7fO4-1627787820402)(img/生成预订单.png)]

 

###5)扣减库存

  • 通过dubbo调用商品服务完成扣减库存
 
  • 商品服务GoodsService扣减库存
 

###6)扣减优惠券

  • 通过dubbo完成扣减优惠券
 
  • 优惠券服务CouponService更改优惠券状态
 

###7)扣减用户余额

  • 通过用户服务完成扣减余额
 
  • 用户服务UserService,更新余额

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T9yxRYsO-1627787820403)(img/更改用户余额.png)]

 

###8)确认订单

 

9)小结

 
 

4.2.1 消息发送方

  • 配置RocketMQ属性值
 
  • 注入模板类和属性值信息
 
  • 发送下单失败消息
 
 

4.2.2 消费接收方

  • 配置RocketMQ属性值
 
  • 创建监听类,消费消息
 
1)回退库存
  • 流程分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rGr73DNN-1627787820404)(img/回退库存.png)]

  • 消息消费者
 
2)回退优惠券
 
3)回退余额
 
4)取消订单
 
 

1)准备测试环境

 

###1)准备测试数据

  • 用户数据
  • 商品数据
  • 优惠券数据

###2)测试下单成功流程

 

执行完毕后,查看数据库中用户的余额、优惠券数据,及订单的状态数据

###3)测试下单失败流程

代码同上。

执行完毕后,查看用户的余额、优惠券数据是否发生更改,订单的状态是否为取消。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ggKDb8YK-1627787820405)(img/创建支付订单.png)]

 
 

5.2.1 流程分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ExVwJhWh-1627787820407)(img/12.支付后回调.png)]

5.2.2 代码实现

 
线程池优化消息发送逻辑
  • 创建线程池对象
 
  • 使用线程池
 

5.2.3

处理消息

支付成功后,支付服务payService发送MQ消息,订单服务、用户服务、日志服务需要订阅消息进行处理

  1. 订单服务修改订单状态为已支付
  2. 日志服务记录支付日志
  3. 用户服务负责给用户增加积分

以下用订单服务为例说明消息的处理情况

1)配置RocketMQ属性值
 
2)消费消息
  • 在订单服务中,配置公共的消息处理类
 
  • 接受订单支付成功消息
 
 

通过Rest客户端请求shop-order-web和shop-pay-web完成下单和支付操作

1)配置RestTemplate类

 

2)配置请求地址

  • 订单系统
 
  • 支付系统
 
 
 
 
 

odsNumber(1);
order.setAddress(“北京”);
order.setGoodsPrice(new BigDecimal(“5000”));
order.setOrderAmount(new BigDecimal(“5000”));
order.setMoneyPaid(new BigDecimal(“100”));
order.setCouponId(couponId);
order.setShippingFee(new BigDecimal(0));

 

}