日淘平台的业务链路特别长:用户下单(煤炉代购/乐天代购)→ 爬虫采集商品数据(日本雅虎/日亚)→ 竞拍出价 → 支付 → 仓储 → 发货(日本直邮)。这些业务都依赖消息队列做异步解耦。
早期版本所有业务共用一个死信交换机——爬虫抓取失败的消息、资金扣款异常的消息、推送超时的消息全堆在同一个队列里。某天爬虫服务出了点问题,一下子往队列里塞了十几万条失败消息,内存直接爆了,资金扣款的消息被堵在后面迟迟消费不了,用户付了款订单状态却没更新,客服电话被打爆。
bidfans系统的解决方案是分层故障隔离。按业务划分独立交换机:竞拍、代购订单、仓储、爬虫、站内信各一个。每个交换机绑定专属的正常消费队列和专属死信队列,业务间消息完全物理隔离。
业务交换机:exchange.order / exchange.auction / exchange.crawler / ...
├── 正常队列:queue.order.normal
│ └── 死信转发 → queue.order.dlx
├── 正常队列:queue.auction.normal
│ └── 死信转发 → queue.auction.dlx
└── ...核心配置代码如下:
@Configuration
public class RabbitMQConfig {
@Bean
public DirectExchange orderExchange() {
return new DirectExchange("exchange.order");
}
@Bean
public Queue orderNormalQueue() {
return QueueBuilder.durable("queue.order.normal")
.deadLetterExchange("dlx.exchange")
.deadLetterRoutingKey("order.dlx")
.build();
}
@Bean
public Queue orderDlxQueue() {
return QueueBuilder.durable("queue.order.dlx").build();
}
}不同业务对失败消息的容忍度完全不一样:
@Component
public class DlxRetryHandler {
@RabbitListener(queues = "queue.order.dlx")
public void handleOrderDlx(Message message) {
int retryCount = getRetryCount(message);
if (retryCount < 10) {
// 1分钟后重新投递到正常队列
rabbitTemplate.convertAndSend("exchange.order", "order.normal",
message.getBody(), msg -> {
msg.getMessageProperties().setDelay(60000);
return msg;
});
} else {
// 超过重试上限,写入故障归档
archiveFailure(message);
}
}
}每个死信队列设置堆积阈值,超过就推送到运维告警。爬虫队列堆积了说明采集服务挂了,订单队列堆积了那就是天大的事,得立刻响应。
这套方案上线后,爬虫大规模故障再也不会影响下单和支付的核心流程。对于做日淘平台的技术团队来说,这种隔离设计是基本功——不管是购够网、日拍网还是乐淘、日淘集市,只要业务稍微复杂一点,迟早得面对这个问题。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。