[英]Why do I have double request to authentication endpoint when I use Spring Security + WebFlux
[英]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.