Fix reply producing to not block reactive thread
When `DirectChannel` is used for reply producing, the data is handled on the same thread which has produced it (normally), so if we have a request-reply afterwards (e.g. `gateway()`), this thread is blocked waiting for reply. When the thread is assumed to be non-blocked (e.g. Netty event loop), the request-reply withing such a thread for the same non-blocking client causes a deadlock: the thread waits for reply, but at the same time it supposes to fulfil a synchronization barrier with that reply * Fix `AbstractMessageProducingHandler.asyncNonReactiveReply()` to use a `publishOn(Schedulers.boundedElastic())` for reply `Mono` to free producing thread from potential downstream blocking * Demonstrate deadlock with a new test in the `RSocketDslTests`; the original report was against WebFlux, but conditions are really the same: `reactor-netty` is used as a low-level client **Cherry-pick to `5.4.x`**
This commit is contained in:
committed by
Gary Russell
parent
fe300ebc38
commit
0f2285d5a3
@@ -55,6 +55,7 @@ import org.springframework.util.concurrent.SettableListenableFuture;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.scheduler.Schedulers;
|
||||
|
||||
/**
|
||||
* The base {@link AbstractMessageHandler} implementation for the {@link MessageProducer}.
|
||||
@@ -362,7 +363,9 @@ public abstract class AbstractMessageProducingHandler extends AbstractMessageHan
|
||||
else {
|
||||
reactiveReply = Mono.from((Publisher<?>) reply);
|
||||
}
|
||||
reactiveReply.subscribe(settableListenableFuture::set, settableListenableFuture::setException);
|
||||
reactiveReply
|
||||
.publishOn(Schedulers.boundedElastic())
|
||||
.subscribe(settableListenableFuture::set, settableListenableFuture::setException);
|
||||
future = settableListenableFuture;
|
||||
}
|
||||
future.addCallback(new ReplyFutureCallback(requestMessage, replyChannel));
|
||||
|
||||
Reference in New Issue
Block a user