消息队列-订单服务准备

本文详细介绍了电商订单服务的环境搭建,包括静态资源分配、域名配置、Nginx与网关修改。同时讲解了SpringSession的整合,涉及session、线程池和Redis的配置。此外,还阐述了订单的构成、状态、流程,以及幂等性处理、秒杀业务的关键点。

订单服务笔记:
file:///E:/%E6%A1%8C%E9%9D%A2/%E8%B0%B7%E7%B2%92%E5%95%86%E5%9F%8E/%E8%B0%B7%E7%B2%92%E5%95%86%E5%9F%8E/%E9%AB%98%E7%BA%A7%E7%AF%87/%E8%AF%BE%E4%BB%B6/09%E3%80%81%E5%95%86%E5%9F%8E%E4%B8%9A%E5%8A%A1.pdf
百度云地址:https://pan.baidu.com/s/1DV6kf6FZWQls5oyvUZBuZA ,密码1111

一、页面环境搭建

流程:购物车–.>去结算–>结算页–>支付页–>二维码

1.静态资源放入nginx、动态资源html放入项目

1).把订单的等待付款的静态资源放入nginx的static/order/detail下
2).把订单的订单页的静态资源放入nginx的static/order/list下
3).把订单的确认页的静态资源放入nginx的static/order/confirm下
4).把订单的支付页的静态资源放入nginx的static/order/pay下
在这里插入图片描述

2.配置域名服务—hosts

1).管理员模式打开SwitchHosts.exe

在这里插入图片描述

2)…配置订单域名服务

在这里插入图片描述

3.修改nginx的配置文件gulimall.conf,已经配置好

在这里插入图片描述

4.修改网关

    - id: gulimall_order_route
      uri: lb://gulimall-order
      predicates:
        - Host=order.gulimall.com

5.修改html页面的资源路径

	static/order/confirm
	static/order/detail/
	static/order/list
	static/order/pay

1). 加入thymeleaf配置

    <!--thymeleaf-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    
    spring.thymeleaf.cache=false
    
	<html lang="en" xmlns:th="http://www.thymeleaf.org">

二、整合SpringSession–分布式session

谷粒商城的社交登录-使用了SpringSession

1.导入session、线程池、redis

1).SpringSesion 的配置

    <!--整合spring-session完成Session共享问题-->
    <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session-data-redis</artifactId>
    </dependency>
    
   #session保存到redis
	spring.session.store-type=redis
	#设置session过期时间
	server.servlet.session.timeout=30s
	
	启动类:@EnableRedisHttpSession //开启SpringSession
@Configuration
public class SessionConfig {
    @Bean
    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer serializer = new DefaultCookieSerializer();
        serializer.setCookieName("GULISESSION");
//        serializer.setCookiePath("/");
        serializer.setDomainName("gulimall.com");
        return serializer;
    }
    @Bean
    public RedisSerializer<Object> springSessionDefaultRedisSerializer(){
        return new GenericJackson2JsonRedisSerializer();
    }
}

2).线程池 的配置

#线程池的配置
gulimall.thread.core-size=20
gulimall.thread.max-size=200
gulimall.thread.keep-alive-time=10
	//线程池配置类
	@Configuration
	public class MyThreadConfig {
	    @Bean("executor")
	    public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool) {
	        return new ThreadPoolExecutor(
	                pool.getCoreSize(),
	                pool.getMaxSize(),
	                pool.getKeepAliveTime(),
	                TimeUnit.SECONDS,
	                new LinkedBlockingDeque<>(100000),
	                Executors.defaultThreadFactory(),
	                new ThreadPoolExecutor.AbortPolicy()
	        );
	    }
	}
	//线程池 参数的配置类
	@ConfigurationProperties(prefix = "gulimall.thread")
	@Component
	@Data
	public class ThreadPoolConfigProperties {
	    private Integer coreSize;
	    private Integer maxSize;
	    private Integer keepAliveTime;
	}

3).redis的配置

 <!--spring整合redis依赖,lettuce容易内存溢出,使用jedis不会-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
        <exclusions>
            <exclusion>
                <groupId>io.lettuce</groupId>
                <artifactId>lettuce-core</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <!--导入jedis依赖-->
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
    </dependency>

	#配置redis
	spring.redis.host=192.168.56.10
	spring.redis.port=6379

三、订单介绍

1.订单中心

电商系统涉及到 3 流,分别时信息流,资金流,物流,而订单系统作为中枢将三者有机的集
合起来。
订单模块是电商系统的枢纽,在订单这个环节上需求获取多个模块的数据和信息,同时对这
些信息进行加工处理后流向下个环节,这一系列就构成了订单的信息流通。

1.1.订单构成

在这里插入图片描述

1).用户信息

用户信息包括用户账号、用户等级、用户的收货地址、收货人、收货人电话等组成,用户账
户需要绑定手机号码,但是用户绑定的手机号码不一定是收货信息上的电话。用户可以添加
多个收货信息,用户等级信息可以用来和促销系统进行匹配,获取商品折扣,同时用户等级
还可以获取积分的奖励等

2).订单基础信息

订单基础信息是订单流转的核心,其包括订单类型、父/子订单、订单编号、订单状态、订
单流转的时间等。
(1)订单类型包括实体商品订单和虚拟订单商品等,这个根据商城商品和服务类型进行区
分。
(2)同时订单都需要做父子订单处理,之前在初创公司一直只有一个订单,没有做父子订
单处理后期需要进行拆单的时候就比较麻烦,尤其是多商户商场,和不同仓库商品的时候,
父子订单就是为后期做拆单准备的。
(3)订单编号不多说了,需要强调的一点是父子订单都需要有订单编号,需要完善的时候
可以对订单编号的每个字段进行统一定义和诠释。
(4)订单状态记录订单每次流转过程,后面会对订单状态进行单独的说明。
(5)订单流转时间需要记录下单时间,支付时间,发货时间,结束时间/关闭时间等等

3).商品信息

商品信息从商品库中获取商品的 SKU 信息、图片、名称、属性规格、商品单价、商户信息
等,从用户下单行为记录的用户下单数量,商品合计价格等。

4).优惠信息

优惠信息记录用户参与的优惠活动,包括优惠促销活动,比如满减、满赠、秒杀等,用户使
用的优惠券信息,优惠券满足条件的优惠券需要默认展示出来,具体方式已在之前的优惠券
篇章做过详细介绍,另外还虚拟币抵扣信息等进行记录。
为什么把优惠信息单独拿出来而不放在支付信息里面呢?
因为优惠信息只是记录用户使用的条目,而支付信息需要加入数据进行计算,所以做为区分。

5).支付信息

(1)支付流水单号,这个流水单号是在唤起网关支付后支付通道返回给电商业务平台的支
付流水号,财务通过订单号和流水单号与支付通道进行对账使用。
(2)支付方式用户使用的支付方式,比如微信支付、支付宝支付、钱包支付、快捷支付等。
支付方式有时候可能有两个——余额支付+第三方支付。
(3)商品总金额,每个商品加总后的金额;运费,物流产生的费用;优惠总金额,包括促
销活动的优惠金额,优惠券优惠金额,虚拟积分或者虚拟币抵扣的金额,会员折扣的金额等
之和;实付金额,用户实际需要付款的金额。
用户实付金额=商品总金额+运费-优惠总金额

6). 物流信息

物流信息包括配送方式,物流公司,物流单号,物流状态,物流状态可以通过第三方接口来
获取和向用户展示物流每个状态节点。

1.2、订单状态

1). 待付款

用户提交订单后,订单进行预下单,目前主流电商网站都会唤起支付,便于用户快速完成支
付,需要注意的是待付款状态下可以对库存进行锁定,锁定库存需要配置支付超时时间,超
时后将自动取消订单,订单变更关闭状态。

2). 已付款/待发货

用户完成订单支付,订单系统需要记录支付时间,支付流水单号便于对账,订单下放到 WMS
系统,仓库进行调拨,配货,分拣,出库等操作。

3). 待收货/已发货

仓储将商品出库后,订单进入物流环节,订单系统需要同步物流信息,便于用户实时知悉物
品物流状态

4). 已完成

用户确认收货后,订单交易完成。后续支付侧进行结算,如果订单存在问题进入售后状态

5). 已取消

付款之前取消订单。包括超时未付款或用户商户取消订单都会产生这种订单状态。

6). 售后中

用户在付款后申请退款,或商家发货后用户申请退换货。
售后也同样存在各种状态,当发起售后申请后生成售后订单,售后订单状态为待审核,等待
商家审核,商家审核通过后订单状态变更为待退货,等待用户将商品寄回,商家收货后订单
状态更新为待退款状态,退款到用户原账户后订单状态更新为售后成功。

2.订单流程

订单流程是指从订单产生到完成整个流转的过程,从而行程了一套标准流程规则。而不同的
产品类型或业务类型在系统中的流程会千差万别,比如上面提到的线上实物订单和虚拟订单
的流程,线上实物订单与 O2O 订单等,所以需要根据不同的类型进行构建订单流程。
不管类型如何订单都包括正向流程和逆向流程,对应的场景就是购买商品和退换货流程,正
向流程就是一个正常的网购步骤:订单生成–>支付订单–>卖家发货–>确认收货–>交易成功。
而每个步骤的背后,订单是如何在多系统之间交互流转的,可概括如下图
在这里插入图片描述

2.1、订单创建与支付

(1) 、订单创建前需要预览订单,选择收货信息等
(2) 、订单创建需要锁定库存,库存有才可创建,否则不能创建
(3) 、订单创建后超时未支付需要解锁库存
(4) 、支付成功后,需要进行拆单,根据商品打包方式,所在仓库,物流等进行拆单
(5) 、支付的每笔流水都需要记录,以待查账
(6) 、订单创建,支付成功等状态都需要给 MQ 发送消息,方便其他系统感知订阅

2.2、逆向流程

(1) 、修改订单,用户没有提交订单,可以对订单一些信息进行修改,比如配送信息,
优惠信息,及其他一些订单可修改范围的内容,此时只需对数据进行变更即可。
(2) 、订单取消,用户主动取消订单和用户超时未支付,两种情况下订单都会取消订
单,而超时情况是系统自动关闭订单,所以在订单支付的响应机制上面要做支付的
限时处理,尤其是在前面说的下单减库存的情形下面,可以保证快速的释放库存。
另外需要需要处理的是促销优惠中使用的优惠券,权益等视平台规则,进行相应补
回给用户。
(3) 、退款,在待发货订单状态下取消订单时,分为缺货退款和用户申请退款。如果是
全部退款则订单更新为关闭状态,若只是做部分退款则订单仍需进行进行,同时生
成一条退款的售后订单,走退款流程。退款金额需原路返回用户的账户。
(4) 、发货后的退款,发生在仓储货物配送,在配送过程中商品遗失,用户拒收,用户
收货后对商品不满意,这样情况下用户发起退款的售后诉求后,需要商户进行退款
的审核,双方达成一致后,系统更新退款状态,对订单进行退款操作,金额原路返
回用户的账户,同时关闭原订单数据。仅退款情况下暂不考虑仓库系统变化。如果
发生双方协调不一致情况下,可以申请平台客服介入。在退款订单商户不处理的情
况下,系统需要做限期判断,比如 5 天商户不处理,退款单自动变更同意退款。

3、幂等性处理

参照幂等性文档

4、订单业务

4.1、搭建环境

订单服务引入页面,nginx 配置动静分离,上传静态资源到 nginx。编写 controller 跳转逻辑

4.2、订单确认页

在这里插入图片描述
在这里插入图片描述
可以发现订单结算页,包含以下信息:

  1. 收货人信息:有更多地址,即有多个收货地址,其中有一个默认收货地址
  2. 支付方式:货到付款、在线支付,不需要后台提供
  3. 送货清单:配送方式(不做)及商品列表(根据购物车选中的 skuId 到数据库中查询)
  4. 发票:不做
  5. 优惠:查询用户领取的优惠券(不做)及可用积分(京豆)

OrderConfirmVo
@Data
public class OrderConfirmVO {
// 收货地址,ums_member_receive_address 表
private List addresses;
// 购物清单,根据购物车页面传递过来的 skuIds 查询
private List orderItems;
// 可用积分,ums_member 表中的 integration 字段
private Integer bounds;
// 订单令牌,防止重复提交
private String orderToken;
}

OrderItemVO(参照 Cart 对象)
public class OrderItemVo {
private Long skuId;
private Boolean check = true;
private String title;
private String image;
private List skuAttr;
private BigDecimal price;
private Integer count;
private BigDecimal totalPrice;

4.3、创建订单

当用户点击提交订单按钮,应该收集页面数据提交到后台并生成订单数据。

1)、数据模型

订单确认页,需要提交的数据:
@Data
public class OrderSubmitVO {
//提交上次订单确认页给你的令牌;
private String orderToken;
private BigDecimal apyPrice; // 校验总价格时,拿计算价格和这个价格比较
private Integer payType;//0-在线支付 1-货到付款
private String delivery_company; // 配送方式
// 订单清单可以不用提交,继续从购物车中获取
// 地址信息,提交地址 id,会员 id 不需要提交
Private Long addrId;
// TODO:发票相关信息略
// TODO:营销信息等
}
提交以后,需要响应的数据:
@Data
public class OrderSubmitResponseVO {
private OrderEntity orderEntity;
private Integer code;
// 1-不可重复提交或页面已过期 2-库存不足 3-价格校验不合法 等
}

2)、防止超卖

数据库 unsigned int 做最后的保证。

4.4、自动关单

订单超时未支付,需要取消订单

4.5、解锁库存

订单关闭,需要解锁已经占用的库存
库存锁定成功,订单回滚,保证最终一致性,也需要库存自动解锁
功能参照消息队列流程完成

5.秒杀

5.1、秒杀业务

秒杀具有瞬间高并发的特点,针对这一特点,必须要做限流 + 异步 + 缓存(页面静态化)

  • 独立部署。
    限流方式:
  1. 前端限流,一些高并发的网站直接在前端页面开始限流,例如:小米的验证码设计
  2. nginx 限流,直接负载部分请求到错误的静态页面:令牌算法 漏斗算法
  3. 网关限流,限流的过滤器
  4. 代码中使用分布式信号量
  5. rabbitmq 限流(能者多劳:chanel.basicQos(1)),保证发挥所有服务器的性能。

5.2、秒杀流程

见秒杀流程图

5.3、限流

参照 Alibaba Sentinel

<think>嗯,用户这次明确要求了解消息队列服务与订阅消息的基本概念,这比之前讨论的具体技术实现更基础。看来用户可能刚接触分布式系统,需要从底层原理开始理解。用户引用的资料[1][2][3]其实已经覆盖了核心定义:消息队列是异步通信机制(生产者-消费者模型),而订阅消息属于发布/订阅模式。但用户似乎希望更直观的对比说明。我上次回答虽然详细但过于技术化,这次要更注重概念本质。注意到用户在引用[1]里提到“解耦”这个关键词,这应该是核心价值点。另外引用[4]的社交网络案例很生动,可以用于具象化说明。不过用户特别强调参考历史对话,所以需要把上次的Redis示例简化为原理示意图。用户之前问过实现细节,但这次聚焦定义,可能有两个学习阶段特征:1)先理解what再研究how2)需要区分消息队列(MQ)和订阅模式(Pub/Sub)的包含关系。根据工业标准[3],AMQP同时支持两种模式,这点必须讲清楚。准备用“邮寄系统”比喻:消息队列像快递柜(指定收件人),订阅消息像报纸投递(按地址分发)。关键要说明订阅消息是消息队列服务的功能子集。华为云SMN的案例[1]可以佐证企业级实现方式。用户可能混淆的认知陷阱:1)认为订阅需要实时连接(实际可持久化)2)以为发布/订阅必用独立服务(其实Redis也能实现)。需要在注意事项里埋入这些知识点。</think> 理解您对消息队列与订阅消息核心概念的疑问,以下是清晰的技术解析: --- ### **一、核心概念定义** 1. **消息队列服务 (Message Queue Service)** 一种**异步通信中间件**,采用生产者-消费者模型: - **生产者**:发送消息到队列(例如:订单系统生成支付消息) - **消费者**:从队列拉取消息处理(例如:库存系统扣减库存) **核心价值**:解耦系统(生产者无需知消费者状态)[^1][^3]。 2. **订阅消息 (Publish/Subscribe)** 消息队列服务中的**分发模式**: - **发布者**:向**主题(Topic)**发送消息(如发送日志到 `logs_topic`) - **订阅者**:绑定主题接收消息(如监控系统订阅 `logs_topic`) **关键特性**:一条消息可被**多个订阅者**同时接收[^2][^4]。 --- ### **二、工作原理对比** #### **消息队列 (点对点模型)** ```mermaid graph LR A[生产者] -->|发送消息| B[消息队列] B -->|推送消息| C[消费者1] B -->|推送消息| D[消费者2] ``` - 消息被**一个消费者消费后即消失** - 典型应用:**任务队列**(如订单处理)[^1] #### **订阅消息 (发布/订阅模型)** ```mermaid graph LR A[发布者] -->|发布消息| B[主题Topic] B -->|广播| C[订阅者1] B -->|广播| D[订阅者2] B -->|广播| E[订阅者3] ``` - 消息被**所有订阅者同时接收** - 典型应用:**实时通知**(如新闻推送、社交动态)[^2][^4] --- ### **三、技术实现关键** 1. **消息代理 (Message Broker)** 路由消息的核心组件(如 **RabbitMQ/Redis/Kafka**): - 接收发布者的消息 - 根据主题匹配订阅关系 - 推送消息给订阅者[^2][^3] 2. **订阅机制类型** | **类型** | **原理** | **案例** | |----------------|-----------------------------|-----------------------| | 精确订阅 | 订阅固定主题名(`order_paid`) | 订单状态更新 | | 通配符订阅 | 模式匹配(`user_*`) | 用户行为日志收集 | | 消费组(Consumer Group) | 同组内竞争消费 | Kafka分区负载均衡 | 3. **消息持久化** - 若订阅者离线,消息队列服务可将消息**存储至磁盘** - 重新上线后继续投递(如 **Kafka/RocketMQ**)[^1][^3] --- ### **四、实际应用场景** 1. **系统解耦** - 支付系统发布支付成功消息 → 物/库存系统订阅处理 2. **实时数据同步** - 数据库变更写入队列 → 缓存系统订阅更新 3. **事件驱动架构** ```python # 发布者(伪代码) mq.publish(topic="user_registered", data={"user_id": 1001}) # 订阅者A(积分服务) mq.subscribe("user_registered", callback=add_welcome_points) # 订阅者B(通知服务) mq.subscribe("user_registered", callback=send_welcome_email) ``` --- ### **五、注意事项** 1. **消息丢失风险** - Redis Pub/Sub 无持久化 → 适合容忍丢失的场景(如实时聊天)[^2] - Kafka/RabbitMQ 支持持久化 → 金融级系统必备 2. **消息顺序保证** - 单个分区内消息有序(Kafka) - 全局有序需单分区单消费者 3. **通配符性能损耗** `user_*.action` 类订阅需避免过多模式匹配[^2][^3] --- **相关实践问题**: 1. 如何用Redis Streams实现支持消息回溯的订阅? 2. RabbitMQ的扇形交换机(fanout exchange)和主题交换机(topic exchange)有何区别? 3. Kafka中订阅者如何从特定时间点重新消费历史消息?
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值