前言
虚拟权益系统是一个用于管理和对接各个上游权益供应商,同时提供管理和对接下游分销商的系统。由于上游供应商服务能力不统一,能够支持的请求并发不统一,在分销商做活动等下游分销商请求量激增的情况下,如果把请求全部打到上游供应商,对于一些能力有限的供应商,会导致失败率大大增加,甚至导致上游供应商服务瘫痪不可用。为了避免虚拟权益系统受上游供应商能力限制,对上游供应商做限流是有必要的。
一、先介绍下虚拟权益系统的发券流程
虚拟权益系统的主要功能是接收下游分销商采购和请求上游供应商获取卡券。通常系统设计为分销商提供三个主要的对接接口下单、查询、回调通知。分销商向虚拟权益系统采购卡券的完整流程如下:
- 分销商需要先调用下单接口,权益系统接收到请求后校验账户余额等必要校验信息,校验通过后,先把订单信息落入数据库。
- 虚拟权益系统调用上游供应商接口获取真实的卡券,得到卡券信息后,通过回调接口通知下游分销商。
- 下游分销商也可以在下单成功后,定时通过订单号查询订单结果。
需求分析
- 根据上游供应商能力不同可分别配置限流值,限流值更新快速生效
- 下游分销商请求量激增,上游供应商能力达到限流值时,不会导致下游分销商订单失败
代码设计
1. 为每一个上游供应商添加一个限流值time_rate(单位毫秒),表示针对此供应商的请求时间间隔为time_rate毫秒,间隔大于time_rate毫秒才可以请求上游
2. 将下游分销商请求权益系统下单与权益系统请求上游供应商发券解耦
解耦可以采用异步调用的方式、消息中间件的方式。考虑到异步线程池在并发较高的情况下队列任务过载导致溢出,本设计采用rabbitmq消息中间件的方式实现解耦。订单入库成功后发送消息到指定队列,如下:
旧代码:providerBaseService.orderSubmit(orderNo);
解耦后代码:rabbitTemplate.convertAndSend("exchange", providerCode, order);
其中"exchange"
为交换机名,providerCode
为供应商编号,同一供应商商品的采购订单发送到同一队列。
3. 初始化交换机、队列、队列交换机的绑定,动态添加监听
1)初始化消息监听容器,用于动态添加监听
@Bean
@Primary
public SimpleMessageListenerContainer submitListener() {
SimpleMessageListenerContainer listener = new SimpleMessageListenerContainer(connectionFactory());
listener.setAcknowledgeMode(AcknowledgeMode.MANUAL);
listener.setExposeListenerChannel(true);
listener.setPrefetchCount(1);
listener.setConcurrentConsumers(1);
listener.setMaxConcurrentConsumers(1);
return listener;
}
2)编写下单消息处理类,限流主要逻辑
@Component("submitMessageListener")
@Slf4j
public cl