Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring integration spring集成amqp出站适配器争用条件?_Spring Integration_Spring Amqp - Fatal编程技术网

Spring integration spring集成amqp出站适配器争用条件?

Spring integration spring集成amqp出站适配器争用条件?,spring-integration,spring-amqp,Spring Integration,Spring Amqp,我们的一个生产应用程序中有一个相当复杂的spring integration amqp用例,我们在启动时看到一些“org.springframework.integration.MessageDispatchingException:Dispatcher没有订户”异常。在启动时出现初始错误之后,我们再也看不到来自相同组件的异常。这看起来像是依赖于AMQP出站适配器的组件上的某种启动竞争条件,最终在生命周期的早期使用它们 我可以通过调用一个网关来重现这一点,该网关以PostConstruct方法发

我们的一个生产应用程序中有一个相当复杂的spring integration amqp用例,我们在启动时看到一些“org.springframework.integration.MessageDispatchingException:Dispatcher没有订户”异常。在启动时出现初始错误之后,我们再也看不到来自相同组件的异常。这看起来像是依赖于AMQP出站适配器的组件上的某种启动竞争条件,最终在生命周期的早期使用它们

我可以通过调用一个网关来重现这一点,该网关以PostConstruct方法发送到连接到出站适配器的通道

配置:

package gadams;

import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.integration.annotation.IntegrationComponentScan;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.dsl.amqp.Amqp;
import org.springframework.integration.dsl.channel.MessageChannels;
import org.springframework.messaging.MessageChannel;

@SpringBootApplication
@IntegrationComponentScan
public class RabbitRace {

    public static void main(String[] args) {
        SpringApplication.run(RabbitRace.class, args);
    }

    @Bean(name = "HelloOut")
    public MessageChannel channelHelloOut() {
        return MessageChannels.direct().get();
    }

    @Bean
    public Queue queueHello() {
        return new Queue("hello.q");
    }

    @Bean(name = "helloOutFlow")
    public IntegrationFlow flowHelloOutToRabbit(RabbitTemplate rabbitTemplate) {
        return IntegrationFlows.from("HelloOut").handle(Amqp.outboundAdapter(rabbitTemplate).routingKey("hello.q"))
                .get();
    }

}
网关:

package gadams;

import org.springframework.integration.annotation.Gateway;
import org.springframework.integration.annotation.MessagingGateway;

@MessagingGateway
public interface HelloGateway {

    @Gateway(requestChannel = "HelloOut")
    void sendMessage(String message);
}
组成部分:

package gadams;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;

@Component
@DependsOn("helloOutFlow")
public class HelloPublisher {

    @Autowired
    private HelloGateway helloGateway;

    @PostConstruct
    public void postConstruct() {
        helloGateway.sendMessage("hello");
    }
}

在我的生产用例中,我们有一个具有PostConstruct方法的组件,其中我们使用TaskScheduler来调度一组组件,其中一些组件依赖于AMQP出站适配器,而其中一些组件最终会立即执行。我曾尝试将bean名称放在涉及出站适配器的IntegrationFlows上,并在使用网关和/或网关本身的bean上使用@DependsOn,但这并不能消除启动时的错误。

一切都称为
生命周期。任何Spring集成端点仅在执行其
start()
时才开始侦听或生成消息

通常,对于标准默认值
autoStartup=true
,它是在
ApplicationContext.finishresh()中完成的作为

// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
@PostConstruct
afterPropertiesSet()
)开始向频道生成消息真的很早,因为它离
finishRefresh()
很远

您确实应该重新考虑您的生产逻辑和实现,进入
SmartLifecycle.start()
阶段


更多信息请参见。

我将复制测试用例放在github上:感谢您的提示,我以前从未阅读过手册的这一部分。我是否应该更改HelloPublisher以实现SmartLifecycle,将网关发送调用放入start(),并从getPhase()返回Integer.MAX_值?这似乎解决了问题,我只是想检查一下我是否正确理解。