SpringAmqp之connectionFactory

本文详细解析了Spring AMQP中连接工厂(ConnectionFactory)的配置与使用,包括解决特定需求如设置handshakeTimeout参数的方法,以及如何通过自定义配置实现多ConnectionFactory的配置,适用于复杂环境下的消息队列应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

版本说明

    <!--amqp版本--><amqpCient.version>4.0.3</amqpCient.version>
    <!--spring版本--><spring.version>4.2.3.RELEASE</spring.version>
    <!--spring-rabbit版本--><spring.rabbit.version>1.7.5.RELEASE</spring.rabbit.version>

问题产生

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

使用默认的connetcion-factory配置,因为特殊原因需要配置handshakeTimeout参数在哪配置?到底产生的ConnetionFactory对象是什么?

解决方案

rabbit:connection-factory标签中单独配置connection-factory属性,使用原生ConnectionFactory

    <!--自定义connectionFactory-->
    <bean id="customFactory" class="com.rabbitmq.client.ConnectionFactory">
        <property name="handshakeTimeout" value="${rabbit.timeout}"></property>
    </bean>
    <!-- 连接connectionFactory-->
    <rabbit:connection-factory id="connectionFactory"
                               host="${rabbit.host}"
                               port="${rabbit.port}"
                               username="${rabbit.username}"
                               password="${rabbit.password}"
                               virtual-host="${rabbit.vhost}"
                               connection-factory="customFactory"
    />

模拟内部实现

    URI uri =new URI("amqp://root:root@192.168.189.131:5672");
        ConnectionFactory connectionFactory=new ConnectionFactory();
        connectionFactory.setUri(uri);
        connectionFactory.setHandshakeTimeout(20000);
        AbstractConnectionFactory abFactory = new AbstractConnectionFactory(connectionFactory) {
            @Override
            public Connection createConnection() throws AmqpException {
                try {
                    return  new SimpleConnection(connectionFactory.newConnection(),0);
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            }
        };

CachingConnectionFactory

原文引用

https://docs.spring.io/spring-amqp/docs/1.7.3.RELEASE/reference/html/_reference.html

The central component for managing a connection to the RabbitMQ broker is the ConnectionFactory interface. The responsibility of a ConnectionFactory implementation is to provide an instance of org.springframework.amqp.rabbit.connection.Connection which is a wrapper for com.rabbitmq.client.Connection. The only concrete implementation we provide is CachingConnectionFactory which, by default, establishes a single connection proxy that can be shared by the application. Sharing of the connection is possible since the “unit of work” for messaging with AMQP is actually a “channel” (in some ways, this is similar to the relationship between a Connection and a Session in JMS). As you can imagine, the connection instance provides a createChannel method. The CachingConnectionFactory implementation supports caching of those channels, and it maintains separate caches for channels based on whether they are transactional or not. When creating an instance of CachingConnectionFactory, the hostname can be provided via the constructor. The username and password properties should be provided as well. If you would like to configure the size of the channel cache (the default is 25), you could call the setChannelCacheSize() method here as well.
Starting with version 1.3, the CachingConnectionFactory can be configured to cache connections as well as just channels. In this case, each call to createConnection() creates a new connection (or retrieves an idle one from the cache). Closing a connection returns it to the cache (if the cache size has not been reached). Channels created on such connections are cached too. The use of separate connections might be useful in some environments, such as consuming from an HA cluster, in conjunction with a load balancer, to connect to different cluster members. Set the cacheMode to CacheMode.CONNECTION.

对象说明

使用rabbit:connection-factory默认配置时,是生成一个ConnectionFactory包装的CachingConnectionFactory,此对象没有handshakeTimeout属性,此对象是继承了抽象类AbstractConnectionFactory

        URI uri =new URI("amqp://root:root@192.168.189.131:5672");
        CachingConnectionFactory connectionFactory =new CachingConnectionFactory(uri);
        connectionFactory.getRabbitConnectionFactory().setHandshakeTimeout(20000);

使用父类方法的getRabbitConnectionFactory能获取到原生的ConnectionFactory,源码如下

	/**
	 * Return a reference to the underlying Rabbit Connection factory.
	 * @return the connection factory.
	 * @since 1.5.6
	 */
	public com.rabbitmq.client.ConnectionFactory getRabbitConnectionFactory() {
		return this.rabbitConnectionFactory;
	}

多ConnectionFactory配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rabbit="http://www.springframework.org/schema/rabbit"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
     http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
     http://www.springframework.org/schema/rabbit
     http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd">
    <!--自定义connectionFactory-->
    <bean id="customFactory" class="com.rabbitmq.client.ConnectionFactory">
        <property name="handshakeTimeout" value="${rabbit.timeout}"></property>
    </bean>


    <!-- 连接connectionFactory-->
    <rabbit:connection-factory id="connectionFactoryV2"
                               host="${rabbit.host2}"
                               port="${rabbit.port2}"
                               username="${rabbit.username2}"
                               password="${rabbit.password2}"
                               virtual-host="${rabbit.vhost2}"
                               connection-factory="customFactory"
    />


    <!-- 连接connectionFactory-->
    <rabbit:connection-factory id="connectionFactory"
                               host="${rabbit.host}"
                               port="${rabbit.port}"
                               username="${rabbit.username}"
                               password="${rabbit.password}"
                               virtual-host="${rabbit.vhost}"
                               connection-factory="customFactory"
    />
    <!--配置多个connectionFactory-->
    <bean id="multiConnectionFactory" class="org.springframework.amqp.rabbit.connection.SimpleRoutingConnectionFactory">
        <property name="targetConnectionFactories">
            <map>
                <entry key="connectionFactory" value-ref="connectionFactory"></entry>
                <entry key="connectionFactoryV2" value-ref="connectionFactoryV2"></entry>
            </map>
        </property>
    </bean>


    <!--当前producer中的exchange和queue会在rabbitmq服务器里自动生成-->
    <rabbit:admin id="rabbitAdmin" connection-factory="connectionFactory"/>
    <rabbit:admin id="rabbitAdminV2" connection-factory="connectionFactoryV2"/>
    <!--监听器-->
    <bean id="rabbitListenerConnectionFactory"
          class="org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory">
        <property name="connectionFactory" ref="connectionFactory"/>
        <property name="concurrentConsumers" value="16"/>
        <property name="maxConcurrentConsumers" value="50"/>
    </bean>
    <bean id="rabbitListenerConnectionFactoryV2"
          class="org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory">
        <property name="connectionFactory" ref="connectionFactoryV2"/>
        <property name="concurrentConsumers" value="16"/>
        <property name="maxConcurrentConsumers" value="50"/>
    </bean>


    <!--rabbitTemplate用于数据的接收和传输-->
    <rabbit:template id="amqpTemplate" connection-factory="multiConnectionFactory" />

生产者

 @Test
    public void sendMsg() {
        SimpleResourceHolder.bind(rabbitTemplate.getConnectionFactory(), "connectionFactory");
        rabbitTemplate.convertAndSend("springExchange", "ss", "testMultiFactory1");

        SimpleResourceHolder.unbind(rabbitTemplate.getConnectionFactory());

        SimpleResourceHolder.bind(rabbitTemplate.getConnectionFactory(), "connectionFactoryV2");
        rabbitTemplate.convertAndSend("springExchange", "ss", "testMultiFactory2");

    }

springAmqp使用了SimpleResourceHolder获取当前绑定的lookupkey

执行效果

ConnectionFactory
在这里插入图片描述
connectionFactoryV2
在这里插入图片描述

消费者

监听方式可以跟单机情况一样,在xml中配置listener,connection-factory匹配上相应的一台

    <!--消息接收-->
    <bean id="messageReceiver" class="com.lyn.rabbitmq.consumer.MessageConsumer"/>

    <!--自动监听 有消息到达时会通知监听在对应的饿队列上的监听对象-->
    <rabbit:listener-container connection-factory="connectionFactory">
        <rabbit:listener ref="messageReceiver" queues="springDiQueue" />
    </rabbit:listener-container>
public class MessageConsumer implements MessageListener{

    @Override
    public void onMessage(Message message) {
        System.out.println("我收到了一条信息:"+message);
    }
}
执行效果
信息: Created new connection: connectionFactory#1936bc4:0/SimpleConnection@1ac4c86 [delegate=amqp://root@192.168.189.131:5672/, localPort= 11550]
我收到了一条信息:(Body:'testMultiFactory1' MessageProperties [headers={}, timestamp=null, messageId=null, userId=null, receivedUserId=null, appId=null, clusterId=null, type=null, correlationId=null, correlationIdString=null, replyTo=null, contentType=text/plain, contentEncoding=UTF-8, contentLength=0, deliveryMode=null, receivedDeliveryMode=PERSISTENT, expiration=null, priority=0, redelivered=false, receivedExchange=springExchange, receivedRoutingKey=ss, receivedDelay=null, deliveryTag=1, messageCount=0, consumerTag=amq.ctag-b8P_UoEZFHf0wwjE19d3Cg, consumerQueue=springDiQueue])
十一月 02, 2018 4:48:50 下午 org.springframework.amqp.rabbit.connection.CachingConnectionFactory createBareConnection
信息: Attempting to connect to: 192.168.189.132:5672
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值