Processing messages through named:channels with prefetch >= 1

自作多情 提交于 2019-11-30 17:04:52

The problem seems to be a reply coming back on a channel that is already closed. When that occurs, the connection is torn down and all users will get that exception. As far as I can tell from the rabbit client code, that shouldn't happen.

Everything should recover though.

Spring AMQP has a channel cache to avoid closing channels and allows them to be reused; increasing the channel cache size (from the default 1), might solve the issue. You seem to be churning a lot of channels.

Spring XD currently doesn't expose the channel cache size as a property. To work around that, put the following file (named rabbit-bus.xml) under xd/config/META-INF/spring-xd/bus.

<?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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="rabbitConnectionFactory" class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory">
        <constructor-arg ref="rabbitFactory" />
        <property name="addresses" value="${spring.rabbitmq.addresses}" />
        <property name="username" value="${spring.rabbitmq.username}" />
        <property name="password" value="${spring.rabbitmq.password}" />
        <property name="virtualHost" value="${spring.rabbitmq.virtual_host}" />
        <property name="channelCacheSize" value="${spring.rabbitmq.channelCacheSize:100}" />
    </bean>

    <bean id="rabbitFactory" class="org.springframework.amqp.rabbit.connection.RabbitConnectionFactoryBean">
        <property name="useSSL" value="${spring.rabbitmq.useSSL:false}" />
        <property name="sslPropertiesLocation" value="${spring.rabbitmq.sslProperties:}"/>
    </bean>

    <bean id="messageBus" class="org.springframework.xd.dirt.integration.rabbit.RabbitMessageBus">
        <constructor-arg ref="rabbitConnectionFactory" />
        <constructor-arg ref="codec"/>
        <property name="defaultAcknowledgeMode" value="#{T(org.springframework.amqp.core.AcknowledgeMode).${xd.messagebus.rabbit.default.ackMode}}" />
        <property name="defaultBackOffInitialInterval" value="${xd.messagebus.rabbit.default.backOffInitialInterval}" />
        <property name="defaultBackOffMaxInterval" value="${xd.messagebus.rabbit.default.backOffMaxInterval}" />
        <property name="defaultBackOffMultiplier" value="${xd.messagebus.rabbit.default.backOffMultiplier}" />
        <property name="defaultChannelTransacted" value="${xd.messagebus.rabbit.default.transacted}" />
        <property name="defaultConcurrency" value="${xd.messagebus.rabbit.default.concurrency}" />
        <property name="defaultDefaultDeliveryMode" value="#{T(org.springframework.amqp.core.MessageDeliveryMode).${xd.messagebus.rabbit.default.deliveryMode}}" />
        <property name="defaultDefaultRequeueRejected" value="${xd.messagebus.rabbit.default.requeue}" />
        <property name="defaultMaxAttempts" value="${xd.messagebus.rabbit.default.maxAttempts}" />
        <property name="defaultMaxConcurrency" value="${xd.messagebus.rabbit.default.maxConcurrency}" />
        <property name="defaultPrefetchCount" value="${xd.messagebus.rabbit.default.prefetch}" />
        <property name="defaultPrefix" value="${xd.messagebus.rabbit.default.prefix}" />
        <property name="defaultReplyHeaderPatterns" value="${xd.messagebus.rabbit.default.replyHeaderPatterns}" />
        <property name="defaultRequestHeaderPatterns" value="${xd.messagebus.rabbit.default.requestHeaderPatterns}" />
        <property name="defaultTxSize" value="${xd.messagebus.rabbit.default.txSize}" />
        <property name="defaultAutoBindDLQ" value="${xd.messagebus.rabbit.default.autoBindDLQ}" />
        <property name="defaultRepublishToDLQ" value="${xd.messagebus.rabbit.default.republishToDLQ}" />
        <property name="defaultBatchingEnabled" value="${xd.messagebus.rabbit.default.batchingEnabled}" />
        <property name="defaultBatchSize" value="${xd.messagebus.rabbit.default.batchSize}" />
        <property name="defaultBatchBufferLimit" value="${xd.messagebus.rabbit.default.batchBufferLimit}" />
        <property name="defaultBatchTimeout" value="${xd.messagebus.rabbit.default.batchTimeout}" />
        <property name="defaultCompress" value="${xd.messagebus.rabbit.default.compress}" />
        <property name="compressingPostProcessor">
            <bean class="org.springframework.amqp.support.postprocessor.GZipPostProcessor">
                <property name="level" value="${xd.messagebus.rabbit.compressionLevel:#{T(java.util.zip.Deflater).BEST_SPEED}}" />
            </bean>
        </property>
        <property name="decompressingPostProcessor">
            <bean class="org.springframework.amqp.support.postprocessor.DelegatingDecompressingPostProcessor">
                <!-- set a map of decompressors here if using other than the default -->
            </bean>
        </property>
        <property name="defaultDurableSubscription" value="${xd.messagebus.rabbit.default.durableSubscription}" />
        <property name="addresses" value="${spring.rabbitmq.addresses:}" />
        <property name="adminAddresses" value="${spring.rabbitmq.adminAddresses:}" />
        <property name="nodes" value="${spring.rabbitmq.nodes:}" />
        <property name="username" value="${spring.rabbitmq.username:}" />
        <property name="password" value="${spring.rabbitmq.password:}" />
        <property name="vhost" value="${spring.rabbitmq.virtual_host:}" />
        <property name="useSSL" value="${spring.rabbitmq.useSSL:false}" />
        <property name="sslPropertiesLocation" value="${spring.rabbitmq.sslProperties:}" />
    </bean>

</beans>

This replaces the standard bus configuration (it's a copy except for the connection factory configuration).

It will set the cache to 100 by default, but you can override it in servers.yml with

spring:
  rabbitmq:
    channelCacheSize: 200

EDIT

There is a better work-around, using the bus extension mechanism - simply put he replacement connection factory beans in the bus exension directory...

$ cat xd/config/META-INF/spring-xd/bus/ext/cf.xml 

<?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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="rabbitConnectionFactory" class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory">
        <constructor-arg ref="rabbitFactory" />
        <property name="addresses" value="${spring.rabbitmq.addresses}" />
        <property name="username" value="${spring.rabbitmq.username}" />
        <property name="password" value="${spring.rabbitmq.password}" />
        <property name="virtualHost" value="${spring.rabbitmq.virtual_host}" />
        <property name="channelCacheSize" value="${spring.rabbitmq.channelCacheSize:100}" />
    </bean>

</beans>

Any file name ending .xml will be found in that directory.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!