[英]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.