最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot rabbitmq長鏈接及域名TTL多機(jī)房切換配置重連能力(完整配置方案)

 更新時(shí)間:2026年02月05日 09:05:43   作者:請(qǐng)叫我頭頭哥  
本文介紹了在SpringBoot中配置RabbitMQ以解決長連接穩(wěn)定性、域名TTL問題及機(jī)房切換后的自動(dòng)重連能力的完整配置方案,通過優(yōu)化連接工廠參數(shù)、刷新DNS緩存和增強(qiáng)重連策略,確保RabbitMQ在各種網(wǎng)絡(luò)環(huán)境下穩(wěn)定運(yùn)行,感興趣的朋友跟隨小編一起看看吧

在Spring Boot中配置RabbitMQ以解決長連接穩(wěn)定性、域名TTL問題及機(jī)房切換后的自動(dòng)重連能力,需結(jié)合 連接工廠參數(shù)優(yōu)化、DNS緩存刷新、自定義重連策略 三個(gè)核心方向。下面將介紹可直接落地的完整配置方案。

一、基礎(chǔ)依賴與核心配置

首先確保pom.xml 中引入Spring AMQP依賴(默認(rèn)集成RabbitMQ 客戶端):

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

二、連接工廠配置(解決長連接穩(wěn)定性)

通過ConnectionFactory配置RabbitMQ連接參數(shù),重點(diǎn)優(yōu)化心跳檢測、自動(dòng)恢復(fù)、超時(shí)控制等參數(shù),確保長連接穩(wěn)定。在application.yml中配置:

spring:
  rabbitmq:
    addresses: rabbitmq.example.com:5672  # 域名+端口(多節(jié)點(diǎn)用逗號(hào)分隔)
    username: admin
    password: your_password
    virtual-host: /
    # 連接超時(shí)設(shè)置
    connection-timeout: 30000  # 連接超時(shí)30秒
    # 心跳檢測(關(guān)鍵:檢測連接存活)
    requested-heartbeat: 60  # 心跳間隔60秒,避免被防火墻/負(fù)載均衡器斷開
    # 自動(dòng)恢復(fù)配置(客戶端內(nèi)置重連機(jī)制)
    publisher-confirm-type: CORRELATED  # 確保消息發(fā)布確認(rèn)可靠性
    publisher-returns: true  # 開啟消息返回機(jī)制
    listener:
      simple:
        retry:
          enabled: true  # 開啟消費(fèi)者重試(避免連接抖動(dòng)導(dǎo)致消息丟失)
          max-attempts: 3  # 最大重試次數(shù)
          initial-interval: 1000  # 重試初始間隔1秒
    # 連接工廠高級(jí)配置(通過Java代碼進(jìn)一步定制)

三、解決域名 TTL(DNS 緩存)問題

JVM會(huì)緩存DNS解析結(jié)果,機(jī)房切換后域名IP變更時(shí),需強(qiáng)制刷新解析。通過以下兩種方式實(shí)現(xiàn):

3.1.JVM 層面控制 DNS 緩存(全局生效)

在應(yīng)用啟動(dòng)參數(shù)中添加JVM系統(tǒng)屬性,縮短DNS緩存時(shí)間:

java -Dsun.net.inetaddr.ttl=10 -Dsun.net.inetaddr.negative.ttl=5 -jar your-app.jar
  • sun.net.inetaddr.ttl=10:正緩存(成功解析的 IP)10 秒后過期,強(qiáng)制重新解析。
  • sun.net.inetaddr.negative.ttl=5:負(fù)緩存(解析失敗的記錄)5 秒后過期,避免長期無法連接。

3.2連接工廠層面主動(dòng)刷新 DNS(精準(zhǔn)控制)

通過自定義ConnectionFactory,在每次創(chuàng)建連接前主動(dòng)解析域名獲取最新IP,繞過本地緩存:

import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionListener;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.rabbitmq.client.Connection;
import java.net.InetAddress;
import java.net.UnknownHostException;
@Configuration
public class RabbitMQConfig {
    @Value("${spring.rabbitmq.addresses}")
    private String addresses;  // 原始配置的域名地址(如 rabbitmq.example.com:5672)
    @Value("${spring.rabbitmq.username}")
    private String username;
    @Value("${spring.rabbitmq.password}")
    private String password;
    @Value("${spring.rabbitmq.virtual-host}")
    private String virtualHost;
    @Bean
    public ConnectionFactory connectionFactory() {
        // 1. 解析域名獲取最新IP(核心:繞過DNS緩存)
        String resolvedAddresses = resolveDomainToIp(addresses);
        // 2. 創(chuàng)建RabbitMQ連接工廠
        CachingConnectionFactory factory = new CachingConnectionFactory();
        factory.setAddresses(resolvedAddresses);  // 使用解析后的IP地址
        factory.setUsername(username);
        factory.setPassword(password);
        factory.setVirtualHost(virtualHost);
        factory.setConnectionTimeout(30000);  // 連接超時(shí)30秒
        factory.setRequestedHeartbeat(60);  // 心跳間隔60秒
        // 3. 啟用自動(dòng)恢復(fù)(關(guān)鍵:連接斷開后自動(dòng)重建)
        factory.setAutomaticRecoveryEnabled(true);  // 開啟自動(dòng)恢復(fù)
        factory.setNetworkRecoveryInterval(5000);  // 網(wǎng)絡(luò)恢復(fù)重試間隔5秒
        factory.setTopologyRecoveryEnabled(true);  // 恢復(fù)隊(duì)列/交換機(jī)綁定(拓?fù)浠謴?fù))
        // 4. 注冊連接監(jiān)聽器(監(jiān)控連接狀態(tài),觸發(fā)自定義重連)
        factory.addConnectionListener(new ConnectionListener() {
            @Override
            public void onClose(Connection connection) {
                // 連接關(guān)閉時(shí)觸發(fā)(非主動(dòng)關(guān)閉)
                if (!connection.isOpen()) {
                    System.out.println("RabbitMQ連接已關(guān)閉,準(zhǔn)備重連...");
                    // 可在此處添加額外重連邏輯(如刷新IP后重建連接)
                    refreshConnection(factory);
                }
            }
            @Override
            public void onShutDown(ShutdownSignalException signal) {
                // 處理服務(wù)端主動(dòng)關(guān)閉信號(hào)
                if (!signal.isInitiatedByApplication()) {
                    System.err.println("RabbitMQ連接被強(qiáng)制關(guān)閉,原因:" + signal.getReason());
                    refreshConnection(factory);
                }
            }
        });
        return factory;
    }
    // 解析域名獲取最新IP(替換域名中的主機(jī)為IP)
    private String resolveDomainToIp(String addresses) {
        try {
            // 分割多節(jié)點(diǎn)地址(如 "host1:5672,host2:5672")
            String[] addressArray = addresses.split(",");
            StringBuilder resolved = new StringBuilder();
            for (String addr : addressArray) {
                String[] hostPort = addr.split(":");
                String host = hostPort[0];
                String port = hostPort.length > 1 ? hostPort[1] : "5672";
                // 解析域名獲取最新IP
                InetAddress[] inetAddresses = InetAddress.getAllByName(host);
                String latestIp = inetAddresses[0].getHostAddress();  // 取第一個(gè)IP(多IP可輪詢)
                resolved.append(latestIp).append(":").append(port).append(",");
            }
            // 移除最后一個(gè)逗號(hào)
            return resolved.substring(0, resolved.length() - 1);
        } catch (UnknownHostException e) {
            System.err.println("域名解析失敗,使用原始地址:" + e.getMessage());
            return addresses;  // 解析失敗時(shí) fallback 到原始域名
        }
    }
    // 刷新連接(重建連接工廠)
    private void refreshConnection(CachingConnectionFactory factory) {
        try {
            // 1. 關(guān)閉舊連接
            factory.destroy();
            // 2. 重新解析域名獲取新IP
            String newAddresses = resolveDomainToIp(addresses);
            // 3. 更新連接工廠地址并重建連接
            factory.setAddresses(newAddresses);
            factory.createConnection();  // 主動(dòng)創(chuàng)建新連接
            System.out.println("RabbitMQ重連成功,新地址:" + newAddresses);
        } catch (Exception e) {
            System.err.println("重連失敗,5秒后重試:" + e.getMessage());
            // 延遲重試(避免頻繁失敗)
            try {
                Thread.sleep(5000);
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
            }
            refreshConnection(factory);  // 遞歸重試
        }
    }
}

四、機(jī)房切換重連能力增強(qiáng)(關(guān)鍵機(jī)制)

上述配置已實(shí)現(xiàn)基礎(chǔ)重連,若需應(yīng)對(duì)極端場景(如機(jī)房完全切換、多節(jié)點(diǎn)故障),可補(bǔ)充以下增強(qiáng)策略:

4.1多機(jī)房節(jié)點(diǎn)優(yōu)先級(jí)配置

若RabbitMQ部署在多機(jī)房(如主機(jī)房rabbitmq-primary.example.com、備機(jī)房rabbitmq-secondary.example.com),可在addresses中按優(yōu)先級(jí)配置,重連時(shí)優(yōu)先嘗試主機(jī)房,失敗后自動(dòng)切換到備機(jī)房:

spring:
  rabbitmq:
    addresses: rabbitmq-primary.example.com:5672,rabbitmq-secondary.example.com:5672  # 主備順序

客戶端會(huì)按順序嘗試連接,主機(jī)房故障時(shí)自動(dòng)切換到備機(jī)房。

4.2結(jié)合服務(wù)發(fā)現(xiàn)動(dòng)態(tài)獲取節(jié)點(diǎn)(適合大規(guī)模部署)

若使用服務(wù)發(fā)現(xiàn)組件(如 Nacos、Consul)管理RabbitMQ節(jié)點(diǎn),可在resolveDomainToIp方法中從服務(wù)發(fā)現(xiàn)獲取健康節(jié)點(diǎn),動(dòng)態(tài)更新連接地址:

// 從服務(wù)發(fā)現(xiàn)獲取健康節(jié)點(diǎn)(偽代碼)
private List<String> getHealthyNodes() {
    // 調(diào)用服務(wù)發(fā)現(xiàn)API,獲取健康的RabbitMQ節(jié)點(diǎn)(如 "10.0.1.1:5672,10.0.2.1:5672")
    return serviceDiscovery.getHealthyInstances("rabbitmq-service");
}

4.3重連時(shí)的資源恢復(fù)保障

開啟topologyRecoveryEnabled: true后,客戶端會(huì)自動(dòng)恢復(fù)隊(duì)列、交換機(jī)、綁定關(guān)系及消費(fèi)者。若需更嚴(yán)格的資源校驗(yàn),可在重連成功后主動(dòng)檢查:

// 重連成功后校驗(yàn)隊(duì)列是否存在(示例)
@Autowired
private RabbitAdmin rabbitAdmin;
public void validateQueue(String queueName) {
    if (!rabbitAdmin.getQueueProperties(queueName).containsKey("queue")) {
        // 隊(duì)列不存在,重新聲明
        Queue queue = QueueBuilder.durable(queueName)
                .withArgument("x-message-ttl", 28800000)
                .build();
        rabbitAdmin.declareQueue(queue);
    }
}

五、監(jiān)控與告警(確保問題可感知)

通過Spring Boot Actuator監(jiān)控RabbitMQ連接狀態(tài),配置如下:

management:
  endpoints:
    web:
      exposure:
        include: rabbithealth,health
  endpoint:
    rabbithealth:
      enabled: true  # 開啟RabbitMQ專屬健康檢查

健康檢查會(huì)返回連接狀態(tài)、通道數(shù)、消費(fèi)者數(shù)等信息,結(jié)合Prometheus + Grafana 可實(shí)時(shí)監(jiān)控連接波動(dòng),機(jī)房切換時(shí)及時(shí)告警。

注意:Spring Boot Actuator 是一個(gè)非常強(qiáng)大的監(jiān)控和管理工具,但如果配置不當(dāng),確實(shí)會(huì)帶來??嚴(yán)重的安全風(fēng)險(xiǎn)??。確保Actuator安全的關(guān)鍵在于遵循 ??“最小權(quán)限原則”?? ,即只暴露最少必要的信息,并嚴(yán)格控制訪問。

六、核心配置總結(jié)

配置方向關(guān)鍵操作
長連接穩(wěn)定性啟用心跳檢測(requested-heartbeat)、設(shè)置合理超時(shí)(connection-timeout
DNS 緩存問題縮短 JVM DNS 緩存時(shí)間 + 重連時(shí)主動(dòng)解析域名
機(jī)房切換重連啟用自動(dòng)恢復(fù)(automaticRecoveryEnabled)+ 自定義重連監(jiān)聽器 + 多節(jié)點(diǎn)優(yōu)先級(jí)
資源一致性開啟拓?fù)浠謴?fù)(topologyRecoveryEnabled)+ 主動(dòng)校驗(yàn)隊(duì)列 / 交換機(jī)

博客總結(jié)

通過以上配置,Spring Boot應(yīng)用可在RabbitMQ機(jī)房切換時(shí)自動(dòng)刷新DNS解析、重建連接并恢復(fù)資源,確保消息通信不中斷。

其他參考/學(xué)習(xí)資料:

源碼地址

https://github.com/toutouge/javademosecond

到此這篇關(guān)于SpringBoot rabbitmq長鏈接及域名TTL多機(jī)房切換配置重連能力(完整配置方案)的文章就介紹到這了,更多相關(guān)springboot rabbitmq長鏈接內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java 二維碼的生成與解析示例代碼

    java 二維碼的生成與解析示例代碼

    本文主要介紹java二維碼的生成與解析,這里提供示例代碼以便大家參考和理解,希望能幫助開發(fā)Java 二維碼的朋友
    2016-08-08
  • 深入分析JAVA Synchronized關(guān)鍵字

    深入分析JAVA Synchronized關(guān)鍵字

    這篇文章主要介紹了析JAVA Synchronized關(guān)鍵字的相關(guān)知識(shí),文中代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • 使用SpringAI整合Ollama實(shí)現(xiàn)工具鏈調(diào)用功能

    使用SpringAI整合Ollama實(shí)現(xiàn)工具鏈調(diào)用功能

    文章介紹了SpringAI的ToolCalling能力,允許大模型自主調(diào)用外部工具以完成多步驟任務(wù),具體而言,通過@Tool注解標(biāo)記方法,SpringAI自動(dòng)解析生成JSONSchema,@Tools注解注冊多個(gè)工具,模型可自主選擇調(diào)用順序和組合,需要的朋友可以參考下
    2026-05-05
  • Java 中的跨域問題解決方法

    Java 中的跨域問題解決方法

    跨域問題本質(zhì)上是瀏覽器的一種安全機(jī)制,與Java本身無關(guān),但Java后端開發(fā)者需要理解其來源以便正確解決,下面給大家介紹Java 中的跨域問題解決方法,感興趣的朋友一起看看吧
    2025-05-05
  • Spring 使用 feign時(shí)設(shè)置header信息的操作

    Spring 使用 feign時(shí)設(shè)置header信息的操作

    這篇文章主要介紹了Spring 使用 feign時(shí)設(shè)置header信息的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • java random.nextInt的坑及解決

    java random.nextInt的坑及解決

    這篇文章主要介紹了java random.nextInt的坑及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • SpringBoot整合MyBatisPlus詳解

    SpringBoot整合MyBatisPlus詳解

    這篇文章詳細(xì)介紹了SpringBoot整合mybatisplus的全過程,文中有詳細(xì)的代碼示例,具有一定的參考價(jià)值,需要的朋友可以參考一下
    2023-04-04
  • JPA原生SQL(自定義SQL)分頁查詢邏輯詳解

    JPA原生SQL(自定義SQL)分頁查詢邏輯詳解

    這篇文章主要介紹了JPA原生SQL(自定義SQL)分頁查詢邏輯詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • SpringBoot利用redis集成消息隊(duì)列的方法

    SpringBoot利用redis集成消息隊(duì)列的方法

    這篇文章主要介紹了SpringBoot利用redis集成消息隊(duì)列的方法,需要的朋友可以參考下
    2017-08-08
  • java結(jié)合HADOOP集群文件上傳下載

    java結(jié)合HADOOP集群文件上傳下載

    這篇文章主要介紹了java結(jié)合HADOOP集群文件上傳下載的方法和示例,非常的實(shí)用,這里推薦給大家,希望大家能夠喜歡。
    2015-03-03

最新評(píng)論

韶关市| 黄山市| 南京市| 江永县| 高要市| 屏东县| 沭阳县| 通道| 栾城县| 鹤山市| 文登市| 临夏市| 绥阳县| 双柏县| 文山县| 四子王旗| 永宁县| 八宿县| 湘潭市| 海口市| 大英县| 安平县| 桓仁| 莫力| 米林县| 桃江县| 湖北省| 通州市| 台山市| 安乡县| 汾西县| 弋阳县| 通山县| 剑河县| 昌乐县| 怀来县| 汝阳县| 镶黄旗| 台东县| 西城区| 元朗区|