[英]Why do I have to use .fluxTransform(f -> f) on an inbound webflux gateways when using Java DSL?
I've run into failed replies when using the webflux gateway Java DSL in Spring Integration.在 Spring 集成中使用 webflux 网关 Java DSL 时,我遇到了失败的回复。 It only works for the first few requests (<8 to be specific), I'm getting reply errors afterwards:
它仅适用于前几个请求(具体为<8),之后我收到回复错误:
org.springframework.integration.MessageTimeoutException: failed to receive JMS response within timeout of: 5000ms
at org.springframework.integration.jms.JmsOutboundGateway.handleRequestMessage(JmsOutboundGateway.java:741) ~[spring-integration-jms-5.3.2.RELEASE.jar:5.3.2.RELEASE]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
When I use .fluxTransform(f -> f)
on the inbound gateway OR when I use the non-reactive http outbound gateway , I don't get the errors, even on a jmeter benchmark with thousands of requests.当我在入站网关上使用
.fluxTransform(f -> f)
或当我使用非反应式http 出站网关时,即使在具有数千个请求的 jmeter 基准测试中,我也不会收到错误。
fluxTransform(f -> f)
in the first flow to make it work?fluxTransform(f -> f)
才能使其工作?fluxTransform(f -> f)
when I use Http.outboundGateway
in the second flow ?Http.outboundGateway
时,为什么它在没有fluxTransform(f -> f)
的情况下工作? Scenario设想
I've created a route using four gateways for a rather complex setup to make a web request on a remote machine, but I'm我已经使用四个网关创建了一个路由,以进行相当复杂的设置,以便在远程机器上发出 web 请求,但我
Integration Flow 1:整合流程一:
inbound webflux gateway -> outbound jms gateway
入站 webflux 网关 -> 出站 jms 网关
@Bean
public IntegrationFlow step1() {
// request-reply pattern using the jms outbound gateway
var gateway = Jms.outboundGateway(jmsConnectionFactory)
.requestDestination("inboundWebfluxQueue")
.replyDestination("outboundWebfluxQueue")
.correlationKey("JMSCorrelationID");
// send a request to jms, wait for the reply and return message payload as response
return IntegrationFlows.from(webfluxServer("/example/webflux"))
// won't work consistently without the next line
.fluxTransform(f -> f)
.handle(gateway).get();
}
Integration Flow 2:集成流程 2:
inbound jms gateway -> outbound webflux gateway
入站 jms 网关 -> 出站 webflux 网关
@Bean
public IntegrationFlow step2_using_webflux() {
var gateway = WebFlux.outboundGateway("http://localhost:8080/actuator/health")
.httpMethod(HttpMethod.GET)
.expectedResponseType(String.class)
// ignore headers
.mappedResponseHeaders();
return IntegrationFlows.from(jmsInboundGateway())
// use webflux outbound gateway to send the request to the TEST_URL
.handle(gateway).get();
}
The complete route looks like this:完整的路线如下所示:
client web request -> flow 1 -> (message broker) -> flow 2 -> server web request
客户端 web 请求 -> 流 1 ->(消息代理)-> 流 2 -> 服务器 web 请求
Another way is to use a .channel(MessageChannels.flux())
instead of that .fluxTransform(f -> f)
.另一种方法是使用
.channel(MessageChannels.flux())
而不是.fluxTransform(f -> f)
。 This way we really bring a back-pressure to the the WebFlux container making it waiting for available slot in the request event loop.通过这种方式,我们真正为 WebFlux 容器带来了背压,使其等待请求事件循环中的可用插槽。
With that we just send to JMS queue not-honoring back-pressure and and your JMS consumer on the other side can't keep up.有了这个,我们只是向 JMS 队列发送不尊重背压,而另一端的 JMS 使用者无法跟上。 Plus we send a request to the same Netty server internally acquiring an event loop slot again for those internal requests.
另外,我们向同一个 Netty 服务器内部发送一个请求,再次为这些内部请求获取一个事件循环槽。
If you are interested I wrote a unit test like this to see what is going on:如果你有兴趣,我写了一个这样的单元测试来看看发生了什么:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class IntegrationApplicationTests {
@Autowired
private TestRestTemplate template;
@Test
void testSpringIntegrationWebFlux() {
var executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(100);
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(10);
executor.afterPropertiesSet();
var numberOfExecutions = new AtomicInteger();
for (var i = 0; i < 100; i++) {
executor.execute(() -> {
var responseEntity = this.template.getForEntity("/example/webflux", String.class);
if (responseEntity.getStatusCode().is2xxSuccessful()) {
numberOfExecutions.getAndIncrement();
}
});
}
executor.shutdown();
assertThat(numberOfExecutions.get()).isEqualTo(100);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.