问题
I have a simple Spring Integration 4 Java DSL flow which uses a DirectChannel
's LoadBalancingStrategy
to round-robin Message
requests to a number of possible REST Services (i.e. calls a REST service from one of two possible service endpoint URIs).
How my flow is currently configured:
@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;
}
My configuration works, but I am wondering whether there is a simpler/better way of configuring the flow using Spring Integration's Java DSL?
Cheers, PM
回答1:
First of all the RoundRobinLoadBalancingStrategy
is the default one for the DirectChannel
.
So, can get rid of the testLoadBalancingCh()
bean definition at all.
Further, to avoid duplication for the .channel("test.result.ch")
you can configure it on the HttpRequestExecutingMessageHandler
as setOutputChannel()
.
From other side your configuration is so simple that I don't see reason to use DSL. You can achieve the same just with annotation configuration:
@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;
}
From other side there is MessageChannels
builder factory to allow to simplify loadBalancer
for your case:
@Bean(name = "test.load.balancing.ch")
public DirectChannel testLoadBalancingCh() {
return MessageChannels.direct()
.loadBalancer(new RoundRobinLoadBalancingStrategy())
.get();
}
However, I can guess that you want to avoid duplication within DSL flow definition to DRY, but it isn't possible now. That's because IntegrationFlow
is linear to tie endoints bypassing the boilerplate code for standard objects creation.
As you see to achieve Round-Robin
we have to duplicate, at least, inputChannel
, to subscribe several MessageHandler
s to the same channel. And we do that in the XML, via Annotations and, of course, from DSL.
I'm not sure that it will be so useful for real applications to provide a hook to configure several handlers using single .handle()
for the same Round-Robin
channel. Because the further downstream flow may not be so simple as your .channel("test.result.ch")
.
Cheers
来源:https://stackoverflow.com/questions/25264395/spring-integration-4-configuring-a-loadbalancingstrategy-in-java-dsl