繁体   English   中英

为什么在使用 Java DSL 时,我必须在入站 webflux 网关上使用.fluxTransform(f -> f)?

[英]Why do I have to use .fluxTransform(f -> f) on an inbound webflux gateways when using Java DSL?

在 Spring 集成中使用 webflux 网关 Java DSL 时,我遇到了失败的回复。 它仅适用于前几个请求(具体为<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:

当我在入站网关上使用.fluxTransform(f -> f)当我使用非反应式http 出站网关时,即使在具有数千个请求的 jmeter 基准测试中,我也不会收到错误。

  • 为什么我必须在第一个流程中调用fluxTransform(f -> f)才能使其工作?
  • 当我在第二个流程中使用Http.outboundGateway时,为什么它在没有fluxTransform(f -> f)的情况下工作?

设想
我已经使用四个网关创建了一个路由,以进行相当复杂的设置,以便在远程机器上发出 web 请求,但我

整合流程一:

入站 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();
  }

集成流程 2:

入站 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();
  }

完整的路线如下所示:

客户端 web 请求 -> 流 1 ->(消息代理)-> 流 2 -> 服务器 web 请求

另一种方法是使用.channel(MessageChannels.flux())而不是.fluxTransform(f -> f) 通过这种方式,我们真正为 WebFlux 容器带来了背压,使其等待请求事件循环中的可用插槽。

有了这个,我们只是向 JMS 队列发送不尊重背压,而另一端的 JMS 使用者无法跟上。 另外,我们向同一个 Netty 服务器内部发送一个请求,再次为这些内部请求获取一个事件循环槽。

如果你有兴趣,我写了一个这样的单元测试来看看发生了什么:

@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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM