You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot2.7.4+Java11连接RabbitMQ SSL报Connection reset错误

Spring Boot 2.7.4 + Java 11 连接 RabbitMQ SSL 报错:Connection reset by peer: socket write error

环境与配置信息

应用配置

配置文件(rabbit.properties):

# RabbitMQ Server configuration file.
rabbit.username=admin
rabbit.password=admin
rabbit.host=localhost
rabbit.port=5671
rabbit.ssl=TLSv1.2
rabbit.keystore.name=client_key.p12
rabbit.keystore.password=rabbitstore
rabbit.truststore=server_store.jks
rabbit.truststore.password=rabbitstore

client_key.p12 和 server_store.jks 已放置在类路径下。

配置类(RabbitConfiguration.java):

@Configuration
@PropertySource("classpath:rabbit.properties")
public class RabbitConfiguration {

    /**
     * Default sample channel name to respond for requests from clients.
     */
    public static final String DEFAULT_QUEUE = "sample_queue";

    /**
     * Environment properties file from rabbitmq configuration.
     */
    @Autowired
    private Environment env;

    /**
     * Establish a connection to a rabbit mq server.
     * @return Rabbit connection factory for rabbitmq access.
     * @throws IOException If wrong parameters are used for connection.
     */
    @Bean
    public RabbitConnectionFactoryBean connectionFactoryBean() throws IOException {
        RabbitConnectionFactoryBean connectionFactoryBean = new RabbitConnectionFactoryBean();
        connectionFactoryBean.setHost(Objects.requireNonNull(env.getProperty("rabbit.host")));
        connectionFactoryBean.setPort(Integer.parseInt(Objects.requireNonNull(env.getProperty("rabbit.port"))));
        connectionFactoryBean.setUsername(Objects.requireNonNull(env.getProperty("rabbit.username")));
        connectionFactoryBean.setPassword(Objects.requireNonNull(env.getProperty("rabbit.password")));

        // SSL-Configuration if set
        if(env.getProperty("rabbit.ssl") != null) {
            connectionFactoryBean.setUseSSL(true);
            connectionFactoryBean.setSslAlgorithm(Objects.requireNonNull(env.getProperty("rabbit.ssl")));

            // This information should be stored safely !!!
            connectionFactoryBean.setKeyStore(Objects.requireNonNull(env.getProperty("rabbit.keystore.name")));
            connectionFactoryBean.setKeyStorePassphrase(Objects.requireNonNull(env.getProperty("rabbit.keystore.password")));
            connectionFactoryBean.setTrustStore(Objects.requireNonNull(env.getProperty("rabbit.truststore")));
            connectionFactoryBean.setTrustStorePassphrase(Objects.requireNonNull(env.getProperty("rabbit.truststore.password")));
        }

        return connectionFactoryBean;
    }

    /**
     * Connection factory which established a rabbitmq connection used from a connection factory
     * @param connectionFactoryBean Connection factory bean to create connection.
     * @return A connection factory to create connections.
     * @throws Exception If wrong parameters are used for connection.
     */
    @Bean(name = "GEO_RABBIT_CONNECTION")
    public ConnectionFactory connectionFactory(RabbitConnectionFactoryBean connectionFactoryBean) throws Exception {
        return new CachingConnectionFactory(Objects.requireNonNull(connectionFactoryBean.getObject()));
    }

    /**
     * Queue initialization from rabbitmq to listen a queue.
     * @return An queue to listen for listen receiver.
     */
    @Bean
    public Queue queue() {
        // Create an new queue to handle incoming responds
        return new Queue(DEFAULT_QUEUE, false, false, false, null);
    }

    /**
     * Generates a simple message listener container.
     * @param connectionFactory Established connection to rabbitmq server.
     * @param listenerAdapter   Listener event adapter to listen for messages.
     * @return A simple message container for listening for requests.
     */
    @Bean
    public SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,
                                                    MessageListenerAdapter listenerAdapter) {

        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.setQueueNames(DEFAULT_QUEUE);
        container.setMessageListener(listenerAdapter);
        container.setAcknowledgeMode(AcknowledgeMode.AUTO);
        return container;

    }

    /**
     * Message listener adapter to generate a message listener.
     * @param deviceMonitoringReceiver Device receive to for listening.
     * @return A message listener adapter to receive messages.
     */
    @Bean
    public MessageListenerAdapter listenerAdapter(DeviceMonitoringReceiver deviceMonitoringReceiver) {
        return new MessageListenerAdapter(deviceMonitoringReceiver, "receiveMessage");
    }
}

RabbitMQ 配置

[
  {rabbit, [
     {ssl_listeners, [5671]},
     {ssl_options, [{cacertfile, "D:\\tls-gen\\basic\\result\\ca_certificate.pem"},
                    {certfile,   "D:\\tls-gen\\basic\\result\\server_seliiwvdec53152_certificate.pem"},
                    {keyfile,    "D:\\tls-gen\\basic\\result\\server_seliiwvdec53152_key.pem"},
                    {verify,     verify_peer},
                    {fail_if_no_peer_cert, true}]} 

   ]}
].

报错信息

Caused by: java.net.SocketException: Connection reset by peer: socket write error

排查与解决方案

1. 证书链与信任验证问题

RabbitMQ 配置了verify_peer和fail_if_no_peer_cert=true,强制要求客户端提供合法证书,且服务端证书需被客户端信任:

  • 确认server_store.jks中是否正确导入CA根证书(ca_certificate.pem),而非仅导入服务端证书。客户端信任库必须信任签发服务端证书的CA。
  • 确认client_key.p12中的客户端证书由同一CA签发,且包含完整证书链(若存在中间CA)。

2. 证书格式与密钥库有效性验证

  • 验证client_key.p12是否包含客户端私钥与对应证书:
    keytool -list -v -storetype pkcs12 -keystore client_key.p12 -storepass rabbitstore
    
  • 验证server_store.jks的有效性:
    keytool -list -v -keystore server_store.jks -storepass rabbitstore
    

3. SSL协议与加密套件兼容性检查

  • 确认RabbitMQ服务端启用了TLSv1.2协议,未被禁用。可通过RabbitMQ管理控制台查看SSL配置详情。
  • 检查加密套件兼容性:Java 11默认加密套件可能与RabbitMQ默认配置存在差异,可在客户端显式指定兼容套件,或在RabbitMQ的ssl_options中添加{ciphers, [兼容套件列表]}。

4. RabbitMQ服务端证书配置正确性

  • 确认cacertfile、certfile、keyfile路径正确,文件存在且服务端进程有读取权限。
  • 验证服务端证书与私钥匹配:
    openssl x509 -noout -modulus -in server_seliiwvdec53152_certificate.pem | openssl md5
    openssl rsa -noout -modulus -in server_seliiwvdec53152_key.pem | openssl md5
    
    两个命令输出的MD5值需完全一致。

5. 客户端连接工厂SSL配置优化

在RabbitConnectionFactoryBean配置中,手动构建SSLContext以精确控制证书加载,避免自动加载的潜在问题:

// 在SSL参数设置后添加以下代码
connectionFactoryBean.setSslContext(SSLContexts.custom()
        .loadKeyMaterial(ResourceUtils.getFile("classpath:" + env.getProperty("rabbit.keystore.name")),
                env.getProperty("rabbit.keystore.password").toCharArray(),
                env.getProperty("rabbit.keystore.password").toCharArray())
        .loadTrustMaterial(ResourceUtils.getFile("classpath:" + env.getProperty("rabbit.truststore")),
                env.getProperty("rabbit.truststore.password").toCharArray())
        .build());

6. 网络与防火墙检查

  • 确认5671端口未被占用,RabbitMQ服务正常监听该端口:
    netstat -ano | findstr :5671
    
  • 检查本地防火墙是否允许客户端与RabbitMQ服务端的5671端口通信。

内容的提问来源于stack exchange,提问作者Mohamed Nagy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 14:20:22