簡體   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