【问题标题】:Spring Integration 4 - configuring a LoadBalancingStrategy in Java DSLSpring Integration 4 - 在 Java DSL 中配置 LoadBalancingStrategy
【发布时间】:2014-08-12 12:31:52
【问题描述】:

我有一个简单的 Spring Integration 4 Java DSL 流程,它使用 DirectChannelLoadBalancingStrategy 循环 Message 对许多可能的 REST 服务的请求(即从两个可能的服务之一调用 REST 服务服务端点 URI)。

我的流程当前是如何配置的:

@Bean(name = "test.load.balancing.ch")
public DirectChannel testLoadBalancingCh() {

    LoadBalancingStrategy loadBalancingStrategy = new RoundRobinLoadBalancingStrategy();
    DirectChannel directChannel = new DirectChannel(loadBalancingStrategy);
    return directChannel;
}

@Bean
public IntegrationFlow testLoadBalancing0Flow() {

    return IntegrationFlows.from("test.load.balancing.ch")
            .handle(restHandler0())
            .channel("test.result.ch")
            .get();     
}

@Bean
public IntegrationFlow testLoadBalancing1Flow() {

    return IntegrationFlows.from("test.load.balancing.ch")
            .handle(restHandler1())
            .channel("test.result.ch")
            .get();     
}

@Bean
public HttpRequestExecutingMessageHandler restHandler0() {
    return createRestHandler(endpointUri0, 0);
}

@Bean
public HttpRequestExecutingMessageHandler restHandler1() {
    return createRestHandler(endpointUri1, 1);
}

private HttpRequestExecutingMessageHandler createRestHandler(String uri, int order) {

    HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler(uri);
    // handler configuration goes here..
    handler.setOrder(order);
    return handler;

}

我的配置有效,但我想知道是否有使用 Spring Integration 的 Java DSL 配置流的更简单/更好的方法?

干杯, 下午

【问题讨论】:

    标签: spring-integration spring-dsl


    【解决方案1】:

    首先RoundRobinLoadBalancingStrategyDirectChannel 的默认值。 所以,可以完全摆脱testLoadBalancingCh() bean 定义。

    此外,为避免.channel("test.result.ch") 重复,您可以在HttpRequestExecutingMessageHandler 上将其配置为setOutputChannel()

    从另一方面看,您的配置非常简单,我看不出使用 DSL 的理由。你可以通过注解配置来达到同样的效果:

    @Bean(name = "test.load.balancing.ch")
    public DirectChannel testLoadBalancingCh() {
        return new DirectChannel();
    }
    
    @Bean(name = "test.result.ch")
    public DirectChannel testResultCh() {
        return new DirectChannel();
    }
    
    @Bean
    @ServiceActivator(inputChannel = "test.load.balancing.ch")
    public HttpRequestExecutingMessageHandler restHandler0() {
        return createRestHandler(endpointUri0, 0);
    }
    
    @Bean
    @ServiceActivator(inputChannel = "test.load.balancing.ch")
    public HttpRequestExecutingMessageHandler restHandler1() {
        return createRestHandler(endpointUri1, 1);
    }
    
    private HttpRequestExecutingMessageHandler createRestHandler(String uri, int order) {
    
        HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler(uri);
        // handler configuration goes here..
        handler.setOrder(order);
        handler.setOutputChannel(testResultCh());
        return handler;
    
    }
    

    从另一边有MessageChannels builder factory 允许为您的案例简化loadBalancer

    @Bean(name = "test.load.balancing.ch")
    public DirectChannel testLoadBalancingCh() {
        return MessageChannels.direct()
                 .loadBalancer(new RoundRobinLoadBalancingStrategy())
                 .get();
    }
    

    但是,我可以猜测您希望避免在 DSL 流定义中重复到 DRY,但现在不可能。这是因为IntegrationFlow 是线性的,可以绕过标准对象创建的样板代码来绑定 endoint。

    如您所见,要实现Round-Robin,我们必须至少复制inputChannel,以便将多个MessageHandlers 订阅到同一频道。我们在 XML 中,通过注解,当然还有 DSL 来做到这一点。

    我不确定它是否对真正的应用程序有用,它提供一个钩子来配置多个处理程序,使用单个.handle() 为同一个Round-Robin 通道。因为进一步的下游流程可能没有你的.channel("test.result.ch")那么简单。

    干杯

    【讨论】:

    • DirectChannels 默认情况下已经设置了循环负载平衡策略。我将使用@ServiceActivator 注释处理程序bean,并完全取消DSL 部分,如您所展示的。谢谢!