GitHub user rikhmaier added a comment to the discussion: [Q/A][Java SDK 
(Component)] For asynchronous calls, should I use asyncCall or virtual threads?

Neither option is universally “better”; they represent two different 
programming models.

`RpcContext.asyncCall(...)` is appropriate when the surrounding code is already 
asynchronous and you want to compose the result without occupying one 
application thread per request:

```java
CompletableFuture<Result> future =
        RpcContext.getServiceContext()
                .asyncCall(() -> remoteService.query(req));

return future.thenApply(this::transform);
```

Ideally, keep the chain asynchronous instead of eventually calling `get()` on a 
platform thread.

Virtual threads are useful when you prefer straightforward synchronous code. In 
that case, the important part is that the complete request/task is already 
running on a virtual thread. You can then call the synchronous Dubbo proxy 
directly:

```java
Result result = remoteService.query(req);
return transform(result);
```

Wrapping one synchronous call in a newly created executor and immediately 
calling `get()` usually adds another scheduling boundary without providing 
useful concurrency. The caller still waits for the same RPC. A virtual-thread 
executor becomes useful for fan-out, where several independent calls run 
concurrently:

```java
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    Future<A> a = executor.submit(() -> serviceA.query(req));
    Future<B> b = executor.submit(() -> serviceB.query(req));
    return combine(a.get(), b.get());
}
```

Therefore:

* Existing asynchronous/reactive pipeline: use Dubbo's asynchronous API and 
compose the `CompletableFuture`.
* Imperative thread-per-request application on JDK 21+: run the request on a 
virtual thread and use the normal synchronous Dubbo call.
* Parallel fan-out from imperative code: virtual threads are a convenient 
option.
* Do not wrap `asyncCall()` in another executor; Dubbo already performs the 
network operation asynchronously.
* Virtual threads improve scalability/throughput for blocking code, not the 
latency of an individual RPC.

Also be careful with `RpcContext`: it is request/thread context. If you submit 
the call to another thread, set any required attachments inside that submitted 
task or use the supported context-propagation mechanism; do not assume 
arbitrary `ThreadLocal` state will follow it.

Finally, virtual threads should not be used as a downstream concurrency limit. 
If the remote service must receive at most N concurrent calls, use a 
`Semaphore`, bulkhead, or Dubbo-side concurrency controls. Creating cheap 
virtual threads does not provide backpressure.

Oracle’s virtual-thread guidance makes the same distinction: synchronous 
blocking code benefits from virtual threads, while an already non-blocking 
`CompletableFuture` pipeline generally does not:
https://docs.oracle.com/en/java/javase/21/core/virtual-threads.html

Dubbo 3.3 also documents Project Loom support:
https://dubbo.apache.org/en/blog/2024/09/11/apache-dubbo-3.3-released-triple-x-leads-a-new-era-of-microservices-communication/

GitHub link: 
https://github.com/apache/dubbo/discussions/16379#discussioncomment-18604808

----
This is an automatically sent email for [email protected].
To unsubscribe, please send an email to: 
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to