spring-amqp+docker+rabbitmq连接每10分钟左右断开次

lengmianshi 发布于 2018/06/19 08:26
阅读 1K+
收藏 0

大神好,项目使用spring amqp为客户端,rabbitmq放在centos7的docker容器中。现在发现客户端和服务器的长连接会每隔10分钟左右断开一次(已配置20s心跳一次)。我在idea上跑项目,长连接断开了会重连。可把项目部署到centos的tomcat容器(也是docker)上,长连接断开了tomcat也停止运行了。

rabbmit客户端配置代码:

package com.sign.conf;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.config.DirectRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.retry.backoff.ExponentialBackOffPolicy;
import org.springframework.retry.support.RetryTemplate;

@Configuration
@EnableRabbit
@Slf4j
public class RabbitMQConfig {

    @Value("${spring.rabbitmq.host}")
    private String host;
    @Value("${spring.rabbitmq.port}")
    private int port;
    @Value("${spring.rabbitmq.username}")
    private String username;
    @Value("${spring.rabbitmq.password}")
    private String password;
    @Value("${spring.rabbitmq.virtual-host}")
    private String virtualHost;
    @Value("${spring.rabbitmq.publisher-confirms}")
    private boolean publisherConfirms;
    @Value("${spring.rabbitmq.requested-heartbeat}")
    private int requestHeartbeat;

    /**
     * 定义连接工厂
     *
     * @return
     */
    @Bean("connectionFactory")
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setHost(host);
        connectionFactory.setPort(port);
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setVirtualHost(virtualHost);
        connectionFactory.setRequestedHeartBeat(requestHeartbeat);//20
        connectionFactory.setPublisherConfirms(publisherConfirms);
        connectionFactory.setPublisherReturns(true);
        /** 如果要进行消息回调,则这里必须要设置为true */
        connectionFactory.setPublisherConfirms(publisherConfirms);
        connectionFactory.setChannelCacheSize(50);

        return connectionFactory;
    }

    /**
     * 因为要设置回调类,所以应是prototype类型,如果是singleton类型,则回调类为最后一次设置
     */
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        template.setMandatory(true);
        template.setReceiveTimeout(-1);//无消息时无限等待

        //配置重试机制
        RetryTemplate retryTemplate = new RetryTemplate();
        ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
        backOffPolicy.setInitialInterval(500);
        backOffPolicy.setMultiplier(2.0); //指定延迟的倍数,比如delay=5000l,multiplier=2时,第一次重试为5秒后,第二次为10秒,第三次为20秒
        backOffPolicy.setMaxInterval(10000);
        retryTemplate.setBackOffPolicy(backOffPolicy);
        template.setRetryTemplate(retryTemplate);
        return template;
    }

    @Bean("emailQueue")
    public Queue emailQueue() {
        Queue queue = new Queue("sign.email.queue", true);
        return queue;
    }

    @Bean("singLogQueue")
    public Queue singLogQueue() {
        Queue queue = new Queue("sign.log.queue", true);
        return queue;
    }

    @Bean
    public DirectExchange directExchange() {
        DirectExchange exchange = new DirectExchange("sign.exchange");
        return exchange;
    }

    /**
     * 队列与交换机绑定
     *
     * @param queue
     * @param exchange
     * @return
     */
    @Bean
    public Binding emailBinding(@Qualifier("emailQueue") Queue queue, DirectExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with("sign.email");
    }

    @Bean
    public Binding singLogBinding(@Qualifier("singLogQueue") Queue queue, DirectExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with("sign.log");
    }

    @Bean
    public RabbitAdmin admin() {
        RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory());
        return rabbitAdmin;
    }


    @Bean
    public DirectRabbitListenerContainerFactory messageContainer(ConnectionFactory connectionFactory) {
        DirectRabbitListenerContainerFactory container = new DirectRabbitListenerContainerFactory();
        container.setConnectionFactory(connectionFactory);
        container.setConsumersPerQueue(1);
        container.setMessageConverter(new Jackson2JsonMessageConverter());
        return container;
    }
}

异常信息如下:

ERROR 2018-06-18 18:34:23.096 [AMQP Connection 47.106.131.138:5672] ERROR o.s.a.rabbit.connection.CachingConnectionFactory - Channel shutdown: connection error
ERROR 2018-06-18 18:34:23.098 [AMQP Connection 47.106.131.138:5672] ERROR o.s.a.rabbit.connection.CachingConnectionFactory - Channel shutdown: connection error
ERROR 2018-06-18 18:34:26.214 [null-consumerMonitor-1] ERROR o.s.a.r.listener.DirectMessageListenerContainer - Consumer canceled - channel closed SimpleConsumer [queue=sign.email.queue, consumerTag=amq.ctag-KYCswj9Zl9kI_gAzYS_-7g identity=2519d53b]
ERROR 2018-06-18 18:34:26.559 [null-consumerMonitor-1] ERROR o.s.a.r.listener.DirectMessageListenerContainer - Consumer canceled - channel closed SimpleConsumer [queue=sign.log.queue, consumerTag=amq.ctag-9iS3X7HZ7EVVv9ICbLKhAw identity=1d62944e]
ERROR 2018-06-18 18:34:26.701 [null-consumerMonitor-1] ERROR o.s.a.r.listener.DirectMessageListenerContainer - Failed to check/redeclare auto-delete queue(s).
org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused (Connection refused)
	at org.springframework.amqp.rabbit.support.RabbitExceptionTranslator.convertRabbitAccessException(RabbitExceptionTranslator.java:62)
	at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.createBareConnection(AbstractConnectionFactory.java:476)
	at org.springframework.amqp.rabbit.connection.CachingConnectionFactory.createConnection(CachingConnectionFactory.java:614)
	at org.springframework.amqp.rabbit.connection.CachingConnectionFactory.createBareChannel(CachingConnectionFactory.java:564)
	at org.springframework.amqp.rabbit.connection.CachingConnectionFactory.getCachedChannelProxy(CachingConnectionFactory.java:538)
	at org.springframework.amqp.rabbit.connection.CachingConnectionFactory.getChannel(CachingConnectionFactory.java:520)
	at org.springframework.amqp.rabbit.connection.CachingConnectionFactory.access$1500(CachingConnectionFactory.java:94)
	at org.springframework.amqp.rabbit.connection.CachingConnectionFactory$ChannelCachingConnectionProxy.createChannel(CachingConnectionFactory.java:1171)
	at org.springframework.amqp.rabbit.core.RabbitTemplate.doExecute(RabbitTemplate.java:1803)
	at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:1771)
	at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:1752)
	at org.springframework.amqp.rabbit.core.RabbitAdmin.getQueueProperties(RabbitAdmin.java:345)
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.redeclareElementsIfNecessary(AbstractMessageListenerContainer.java:1604)
	at org.springframework.amqp.rabbit.listener.DirectMessageListenerContainer.doRedeclareElementsIfNecessary(DirectMessageListenerContainer.java:492)
	at org.springframework.amqp.rabbit.listener.DirectMessageListenerContainer.lambda$actualStart$4(DirectMessageListenerContainer.java:406)
	at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
	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 (Connection refused)
	at java.net.PlainSocketImpl.socketConnect(Native Method)
	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
	at java.net.Socket.connect(Socket.java:589)
	at com.rabbitmq.client.impl.SocketFrameHandlerFactory.create(SocketFrameHandlerFactory.java:60)
	at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:955)
	at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:907)
	at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:1066)
	at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.createBareConnection(AbstractConnectionFactory.java:458)
	... 21 common frames omitted
ERROR 2018-06-18 18:34:26.705 [null-consumerMonitor-1] ERROR o.s.a.r.listener.DirectMessageListenerContainer - Cannot connect to server
org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused (Connection refused)
	at org.springframework.amqp.rabbit.support.RabbitExceptionTranslator.convertRabbitAccessException(RabbitExceptionTranslator.java:62)
	at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.createBareConnection(AbstractConnectionFactory.java:476)
	at org.springframework.amqp.rabbit.connection.CachingConnectionFactory.createConnection(CachingConnectionFactory.java:614)
	at org.springframework.amqp.rabbit.listener.DirectMessageListenerContainer.doConsumeFromQueue(DirectMessageListenerContainer.java:553)
	at org.springframework.amqp.rabbit.listener.DirectMessageListenerContainer.lambda$actualStart$4(DirectMessageListenerContainer.java:413)
	at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
	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 (Connection refused)
	at java.net.PlainSocketImpl.socketConnect(Native Method)
	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
	at java.net.Socket.connect(Socket.java:589)
	at com.rabbitmq.client.impl.SocketFrameHandlerFactory.create(SocketFrameHandlerFactory.java:60)
	at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:955)
	at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:907)
	at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:1066)
	at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.createBareConnection(AbstractConnectionFactory.java:458)
	... 11 common frames omitted

长连接断开间隔好像有一定规律,不知道是不是centos上的配置问题。按理说,只要心跳正常,连接是不会断开的。

加载中
0
javaxiaoz
javaxiaoz

这。。。没遇到过,同问。

难道和系统有关系?

l
lengmianshi
有的,是内核版本低了
0
卖爷爷的老红薯
卖爷爷的老红薯

这肯定是参数控制的,长时间没有数据发过来,timeout。

l
lengmianshi
已解决
0
l
lengmianshi

已解决,docker对系统内核有要求,把内核升级到最新版就正常了

返回顶部
顶部