SpringBoot 禁用RabbitMQ自启动、设置RabbitMQ启动开关

这篇具有很好参考价值的文章主要介绍了SpringBoot 禁用RabbitMQ自启动、设置RabbitMQ启动开关。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、需求背景

SpringBoot项目里使用了RabbitMQ,但某些场景下,不希望项目启动时自动检查RabbitMQ连接,例如:

  • 场景1:在开发过程中,若RabbitMQ服务未启动,会导致SpringBoot项目启动失败。
  • 场景2:RabbitMQ做为系统里的一个插件功能,可能不同的客户部署环境中,并不需要启动RabbitMQ,但是要保证项目正常运行。

因此需要在项目里实现开关配置,可以动态的配置在项目启动时,是否自动启动RabbitMQ连接。

启动错误示例:

[2022-10-12 11:18:11.456] traceId= [RMI TCP Connection(8)-192.168.18.118] WARN  o.s.boot.actuate.amqp.RabbitHealthIndicator - Rabbit health check failed
org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused: connect
	at org.springframework.amqp.rabbit.support.RabbitExceptionTranslator.convertRabbitAccessException(RabbitExceptionTranslator.java:61)
	at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.createBareConnection(AbstractConnectionFactory.java:602)
	at org.springframework.amqp.rabbit.connection.CachingConnectionFactory.createConnection(CachingConnectionFactory.java:725)
	at org.springframework.amqp.rabbit.connection.ConnectionFactoryUtils.createConnection(ConnectionFactoryUtils.java:252)
	at org.springframework.amqp.rabbit.core.RabbitTemplate.doExecute(RabbitTemplate.java:2173)
	at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:2146)
	at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:2126)
	at org.springframework.boot.actuate.amqp.RabbitHealthIndicator.getVersion(RabbitHealthIndicator.java:49)
	at org.springframework.boot.actuate.amqp.RabbitHealthIndicator.doHealthCheck(RabbitHealthIndicator.java:44)
	at org.springframework.boot.actuate.health.AbstractHealthIndicator.health(AbstractHealthIndicator.java:82)
	at org.springframework.boot.actuate.health.HealthIndicator.getHealth(HealthIndicator.java:37)
	at org.springframework.boot.actuate.health.HealthEndpoint.getHealth(HealthEndpoint.java:77)
	at org.springframework.boot.actuate.health.HealthEndpoint.getHealth(HealthEndpoint.java:40)
	at org.springframework.boot.actuate.health.HealthEndpointSupport.getContribution(HealthEndpointSupport.java:130)
	at org.springframework.boot.actuate.health.HealthEndpointSupport.getAggregateContribution(HealthEndpointSupport.java:141)
	at org.springframework.boot.actuate.health.HealthEndpointSupport.getContribution(HealthEndpointSupport.java:126)
	at org.springframework.boot.actuate.health.HealthEndpointSupport.getHealth(HealthEndpointSupport.java:95)
	at org.springframework.boot.actuate.health.HealthEndpointSupport.getHealth(HealthEndpointSupport.java:66)
	at org.springframework.boot.actuate.health.HealthEndpoint.health(HealthEndpoint.java:71)
	at org.springframework.boot.actuate.health.HealthEndpoint.health(HealthEndpoint.java:61)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282)
	at org.springframework.boot.actuate.endpoint.invoke.reflect.ReflectiveOperationInvoker.invoke(ReflectiveOperationInvoker.java:74)
	at org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredOperation.invoke(AbstractDiscoveredOperation.java:60)
	at org.springframework.boot.actuate.endpoint.jmx.EndpointMBean.invoke(EndpointMBean.java:122)
	at org.springframework.boot.actuate.endpoint.jmx.EndpointMBean.invoke(EndpointMBean.java:97)
	at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
	at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
	at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1468)
	at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:76)
	at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1309)
	at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1401)
	at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:829)
	at sun.reflect.GeneratedMethodAccessor212.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:357)
	at sun.rmi.transport.Transport$1.run(Transport.java:200)
	at sun.rmi.transport.Transport$1.run(Transport.java:197)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:573)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.net.ConnectException: Connection refused: connect
	at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
	at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:81)
	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:476)
	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:218)
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:200)
	at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:162)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:394)
	at java.net.Socket.connect(Socket.java:606)
	at com.rabbitmq.client.impl.SocketFrameHandlerFactory.create(SocketFrameHandlerFactory.java:60)
	at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:1223)
	at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:1173)
	at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.connectAddresses(AbstractConnectionFactory.java:640)
	at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.connect(AbstractConnectionFactory.java:615)
	at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.createBareConnection(AbstractConnectionFactory.java:565)
	... 50 common frames omitted

二、实现方案

方案一、配置autoStartup环境变量,关闭自启动(不推荐)

在bootstrap.yml中配置:

spring:
  rabbitmq:
    listener:
      direct:
        auto-startup: false
      simple:
        auto-startup: false
      stream:
        auto-startup: false
rabbitmq:
  start: false

在SpringBootApplicaiton启动类中配置:


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistry;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;

import javax.annotation.Resource;

@SpringBootApplication
public class TestServerApp {

    static Logger logger = LoggerFactory.getLogger(TestServerApp .class);

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(TestServerApp .class, args);
        RabbitMQStart rabbitMQRun = context.getBean(RabbitMQStart.class);
        rabbitMQRun.start();
    }

    @Bean
    public RabbitMQStart rabbitMQRun() {
        return new RabbitMQStart();
    }

    private static class RabbitMQStart {
        //为了在main中的static方法中使用@value注解只能用这种办法
        @Value("${rabbitmq.start}")
        private Boolean rabbitmqStart;

        @Resource
        RabbitListenerEndpointRegistry rabbitListenerEndpointRegistry;
        public void start() {
            if(rabbitmqStart)
                rabbitListenerEndpointRegistry.start();
            else
                rabbitListenerEndpointRegistry.stop();
            System.out.println("=================== Rabbitmq:"+rabbitmqStart+"===================");
        }
    }
}

缺点:

1、配置麻烦,而且不能放到Nacos配置中心

2、代码侵入多,需要改代码。

3、项目启动时,RabbitMQ仍会触发一次尝试连接,控制台会报错。

拓展:

1、autoStartup变量在RabbitMQ包中的位置:

org.springframework.boot.autoconfigure.amqp.RabbitProperties下的:

        org.springframework.boot.autoconfigure.amqp.RabbitProperties.BaseContainer下的:

                private boolean autoStartup = true;

2、三种container(有啥区别?还没研究~)

org.springframework.boot.autoconfigure.amqp.RabbitProperties.StreamContainer

org.springframework.boot.autoconfigure.amqp.RabbitProperties.DirectContainer

org.springframework.boot.autoconfigure.amqp.RabbitProperties.SimpleContainer(默认)

方案二、排除RabbitMQ的自动配置(不推荐)

在SpringBootApplication启动类上使用exclude排除

@SpringBootApplication(exclude = {RabbitAutoConfiguration.class})

或者在yaml中配置

spring:
  autoconfigure:
    exclude: org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration

注意:SpringBoot加载AutoConfig的时机,要早于连接配置中心(比如Nacos),因此该yaml配置不能放到配置中心上的文件中,需要放在项目本地的bootstrap.yml或者application.yml中。

缺点:

1、不能放到Nacos配置中心,在bootstrap.yml中配置,在发布版本时会被一起打包发布。

2、若想恢复项目启动时,RabbitMQ自动初始化连接,在fat jar启动时必须指定运行参数来去掉该配置,若是用docker镜像运行则更麻烦,需要配置环境变量:

java -Dspring.autoconfigure.exclude=空 -jar app.jar

方案三、自定义RabbitMQ自动配置类(推荐)

自定义RabbitMQ的自动配置类(使用@Configuration)

import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;

/**
 * @desccription 自定义RabbitMQ的启动配置类,可以通过配置变量来控制启用、禁用
 * @auth wangshaopeng@talkweb.com.cn
 * @date 2022/10/12
 */
@Configuration
@ConditionalOnProperty("spring.rabbitmq.enable")
public class MyRabbitAutoConfiguration extends RabbitAutoConfiguration {
}

配置bootstrap.yal,排除默认的RabbitMQ自动配置类

spring:
  autoconfigure:
    exclude: org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration

再配置RabbitMQ自动配置开关,此配置可以放在Nacos配置中心,因为使用的是@Configuration机制,而不是项目启动自动配置机制,因此读取开关配置的时机被延迟,可以等到读取配置中心完毕后再初始化RabbitMQ。

例如在nacos上配置rabbitmq.yml文章来源地址https://www.toymoban.com/news/detail-784765.html

spring:
  rabbitmq:
    #配置rabbitMq启用开关
    enable: true
    host: 127.0.0.1
    port: 5672
    username: wsp
    password: bugaosuni
    virtual-host: /wsp

到了这里,关于SpringBoot 禁用RabbitMQ自启动、设置RabbitMQ启动开关的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • springboot 设置自定义启动banner背景图 教程

    Spring Boot中的banner是在应用程序启动时显示的一个ASCII艺术字符或文本。它被用来给用户展示一些关于应用程序的信息,例如名称、版本号或者公司标志等。 使用Spring Boot的默认设置,如果项目中有一个名为“banner.txt”的文件放置在classpath下的“/META-INF”目录中,那么这个文

    2024年02月12日
    浏览(30)
  • springboot整合rabbitmq的发布确认,消费者手动返回ack,设置备用队列,以及面试题:rabbitmq确保消息不丢失

    目录 1.生产者发消息到交换机时候的消息确认 2.交换机给队列发消息时候的消息确认 3.备用队列 3.消费者手动ack   rabbitmq的发布确认方式,可以有效的保证我们的数据不丢失。   消息正常发送的流程是:生产者发送消息到交换机,然后交换机通过路由键把消息发送给对应的队

    2024年02月09日
    浏览(70)
  • Rabbitmq 服务启动自动关闭(已解决)

    晚上弄了一晚上都没有弄好,结果配置个环境变量就好了 变量名 RABBITMQ_BASE  变量值 自己安装的Rabbitmq的目录 3. 然后 管理员运行cmd然后打开RabbitMQ安装目录 4. rabbitmq-service.bat remove 5. rabbitmq-service.bat install 6. rabbitmq-plugins enable rabbitmq_management 7. rabbitmq-service.bat start 启动服务

    2024年02月16日
    浏览(46)
  • springboot如何用jar包启动,同时为不同机房设置不同的配置文件

    示例代码: 利用maven-assembly-plugin,抽取配置文件到conf目录下, 示例代码: 最终效果如下: 示例代码如下: 最终达到的效果是: 将springboot的jar包解压后,可以看到.MF文件中加了一个类路径 ../conf 特别注意: java -jar XX 使用-jar启动java进程的,-classpath不会生效了,如果要加类

    2024年02月05日
    浏览(32)
  • springBoot如何【禁用Swagger】

    生产环境下,需要关闭swagger配置,避免接口暴露。 1、使用注解@Value() 2、使用注解@Profile({“dev”,“test”}) 表示在开发或测试环境开启,而在生产关闭。 3、使用注解@ConditionalOnProperty(name = “swagger.enable”, havingValue = “true”) 然后在测试配置或者开发配置中 添加 swagger.enabl

    2024年02月05日
    浏览(28)
  • springboot 去掉netflix 禁用Eureka

    目录 报错 解决方法 方法一:去掉maven依赖 方法二:直接在application配置文件里禁用eureka(偷懒方法) 方法三:检查eureka配置的地址是否正确(确实需要使用eureka) 如果你接手别人的项目,启动的时候会一直报这个错:发现有netflix,eureka相关字眼, 但你项目只是一个简单的

    2024年02月07日
    浏览(47)
  • SpringBoot + 自定义注解 + AOP 打造通用开关

    前言 最近在工作中迁移代码的时候发现了以前自己写的一个通用开关实现,发现挺不错,特地拿出来分享给大家。 为了有良好的演示效果,我特地重新建了一个项目,把核心代码提炼出来加上了更多注释说明,希望xdm喜欢。 案例 1、项目结构 2、引入依赖 3、yml配置 连接Re

    2024年01月23日
    浏览(40)
  • SpringBoot+自定义注解+AOP高级玩法打造通用开关

    1.项目结构 2.引入依赖 3.yml配置 4.自定义注解 5.定义常量 6.AOP核心实现 7.使用注解 8.工具类 9.测试接口 10.Redis中把开关加上 11.启动服务 将redis中开关置为1 欢迎大家积极留言交流学习心得,点赞的人最美丽!

    2024年02月07日
    浏览(35)
  • Ubuntu设置kubelet启动脚本关闭swap分区

    查看swap分区 打开swap分区 查看/etc/fstab下所有固化的swap分区,注释 修改kubelet.conf文件 添加 生效

    2024年02月04日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包