首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

RabbitMQ 在分布式系統中的 Spring 整合實戰:生產者/消費者配置詳解

     編輯:Java 綜合教學

架構概覽

RabbitMQ 架構圖

  • Exchange:rest-content-exchange (Topic 類型,持久化)
  • Queues:rest-sms-queue、rest-jpush-queue、rest-sysmsg-queue(均持久化)
  • Bindings:Routing Key 模式匹配綁定
  • 消費者:三個 Handler 分別監聽對應隊列

配置文件 applicationContext-rabbitmq.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
       xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
       xmlns:rabbit="https://www.springframework.org/schema/rabbit"
       xsi:schemaLocation="https://www.springframework.org/schema/beans
           https://www.springframework.org/schema/beans/spring-beans.xsd
           https://www.springframework.org/schema/rabbit
           https://www.springframework.org/schema/rabbit/spring-rabbit.xsd">

    <!-- 1. 連接工廠 -->
    <rabbit:connection-factory id="connectionFactory"
        host="${rabbitmq.host}" port="${rabbitmq.port}"
        username="${rabbitmq.username}" password="${rabbitmq.password}"
        virtual-host="${rabbitmq.vhost}" />

    <!-- 2. 管理員(自動聲明 Exchange/Queue/Binding) -->
    <rabbit:admin connection-factory="connectionFactory"/>

    <!-- 3. 生產者端配置 -->
    <rabbit:topic-exchange name="rest-content-exchange" durable="true" auto-declare="true">
        <rabbit:bindings>
            <rabbit:binding queue="rest-sms-queue" pattern="rest.sms.#"/>
            <rabbit:binding queue="rest-jpush-queue" pattern="rest.jpush.#"/>
            <rabbit:binding queue="rest-sysmsg-queue" pattern="rest.sysmsg.#"/>
        </rabbit:bindings>
    </rabbit:topic-exchange>

    <rabbit:template id="rabbitTemplate" connection-factory="connectionFactory" 
                     exchange="rest-content-exchange"/>

    <!-- 4. 消費者端配置 -->
    <rabbit:queue name="rest-sms-queue" durable="true" auto-declare="true"/>
    <rabbit:queue name="rest-jpush-queue" durable="true" auto-declare="true"/>
    <rabbit:queue name="rest-sysmsg-queue" durable="true" auto-declare="true"/>

    <bean id="smsHandler" class="com.dingli.components.mq.handler.SmsHandler"/>
    <bean id="jpushHandler" class="com.dingli.components.mq.handler.JpushHandler"/>
    <bean id="saveSysMsgHandler" class="com.dingli.components.mq.handler.SaveSysMsgHandler"/>

    <!-- 關鍵:acknowledge="none" 避免異常重試無限循環 -->
    <rabbit:listener-container connection-factory="connectionFactory" acknowledge="none">
        <rabbit:listener ref="smsHandler" method="execute" queue-names="rest-sms-queue"/>
        <rabbit:listener ref="jpushHandler" method="execute" queue-names="rest-jpush-queue"/>
        <rabbit:listener ref="saveSysMsgHandler" method="saveMsgExecute" queue-names="rest-sysmsg-queue"/>
    </rabbit:listener-container>

</beans>

核心配置解析

acknowledge 模式選擇

  • auto(默認):自動確認,異常時消息丟失
  • manual:手動確認,需在代碼中調用 channel.basicAck(),支持重試但需防無限循環
  • none:無確認模式,消息發送即視為成功,適合業務允許極少量丟失、追求高吞吐的場景

本項目選用 none,因為業務為異步通知(短信、推送、系統消息),允許極低概率丟失,優先保證性能。

生產者實現

@Component
public class SendMsgRestProducerImpl implements SendMsgRestProducer {
    @Autowired private RabbitTemplate rabbitTemplate;

    @Override public void sendSMS(String mqSMSMessageJson) {
        rabbitTemplate.convertAndSend("rest.sms.send", mqSMSMessageJson);
    }
    @Override public void jpushContent(String mqJPushMessageJson) {
        rabbitTemplate.convertAndSend("rest.jpush.send", mqJPushMessageJson);
    }
    @Override public void saveContent(String mqSysMessageJson) {
        rabbitTemplate.convertAndSend("rest.sysmsg.send", mqSysMessageJson);
    }
}

調用示例:sendMsgRestProducer.sendSMS(jsonStr),三業務完全異步解耦。

消費者 Handler 示例

@Component
public class SmsHandler {
    private static final Logger log = LoggerFactory.getLogger(SmsHandler.class);
    
    public void execute(String messageJson) {
        try {
            // 解析 JSON -> 發送短信業務邏輯
            SmsMessage msg = JSON.parseObject(messageJson, SmsMessage.class);
            smsService.send(msg.getMobile(), msg.getContent());
            log.info("短信發送成功: {}", msg.getMobile());
        } catch (Exception e) {
            log.error("短信發送失敗: {}", messageJson, e);
            // acknowledge="none" 時,異常不會導致消息重回隊列
        }
    }
}

資源文件配置

# rabbitmq.properties
rabbitmq.host=192.168.1.188
rabbitmq.port=5672
rabbitmq.username=lee
rabbitmq.password=lee
rabbitmq.vhost=danger

設計決策總結

決策點選擇理由
Exchange 類型Topic支持通配符路由,擴展性強
持久化全鏈路持久化防止 Broker 重啟丟失數據
確認機制acknowledge="none"業務允許極少丟失,換取高吞吐
異步處理RabbitTemplate.convertAndSend非阻塞發送,主流程無感知
錯誤處理日誌記錄 + 監控告警不重試,避免死循環;人工介入補償

適用場景判斷

核心業務(訂單、支付、庫存)嚴禁使用無確認模式,需採用手動 ACK + 幂等性設計 + 死信隊列重試機制。
輔助業務(日誌、通知、統計、緩存刷新)可根據業務容忍度選擇 none 或 manual。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved