You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@dubbo.apache.org by "polarisGitHub (via GitHub)" <gi...@apache.org> on 2026/07/12 13:31:53 UTC
[D] [Q/A][Java SDK (Component)] For asynchronous calls, should I use asyncCall or virtual threads? [dubbo]
GitHub user polarisGitHub created a discussion: [Q/A][Java SDK (Component)] For asynchronous calls, should I use asyncCall or virtual threads?
### Pre-check
- [X] I am sure that all the content I provide is in English.
### Apache Dubbo Component
Java SDK (apache/dubbo)
### Details
Which way is better?
```java
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
Future<A> fa = executor.submit(() -> remoteService.query(req));
// do somethings
A a = fa.get();
Result result = future.get();
}
```
```java
CompletableFuture<Result> future = RpcContext.getServiceContext().asyncCall(() -> remoteService.query(req));
// do somethings
Result result = future.get();
```
### Code of Conduct
- [X] I agree to follow this project's [Code of Conduct](https://www.apache.org/foundation/policies/conduct)
GitHub link: https://github.com/apache/dubbo/discussions/16379
----
This is an automatically sent email for notifications@dubbo.apache.org.
To unsubscribe, please send an email to: notifications-unsubscribe@dubbo.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org
Re: [D] [Q/A][Java SDK (Component)] For asynchronous calls, should I use asyncCall or virtual threads? [dubbo]
Posted by "LI123456mo (via GitHub)" <gi...@apache.org>.
GitHub user LI123456mo added a comment to the discussion: [Q/A][Java SDK (Component)] For asynchronous calls, should I use asyncCall or virtual threads?
Here let me try to answer from what I researched on
When you use virtual threads, creating a virtual thread (and the executor to manage it) isn't free — it's cheap, way cheaper than a real OS thread, but it's not zero. There's a small bit of memory and bookkeeping overhead per virtual thread.
Using the AsyncCall() style which dubbo uses, you are being handed back the thread by the CompletableFuture, and since dubbo has background threads(netty I/O threads) that hands the result once ready, this is completely non-blocking and dubbo was implementing this asynchronous style way before virtual thread.
So choose option asyncCall() which was already doing the same thing even before the virtual thread.
@polarisGitHub @zrlw @oxsean @RainYuY did I answered well?
GitHub link: https://github.com/apache/dubbo/discussions/16379#discussioncomment-18593977
----
This is an automatically sent email for notifications@dubbo.apache.org.
To unsubscribe, please send an email to: notifications-unsubscribe@dubbo.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org
Re: [D] [Q/A][Java SDK (Component)] For asynchronous calls, should I use asyncCall or virtual threads? [dubbo]
Posted by "rikhmaier (via GitHub)" <gi...@apache.org>.
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 notifications@dubbo.apache.org.
To unsubscribe, please send an email to: notifications-unsubscribe@dubbo.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org
Re: [D] [Q/A][Java SDK (Component)] For asynchronous calls, should I use asyncCall or virtual threads? [dubbo]
Posted by "polarisGitHub (via GitHub)" <gi...@apache.org>.
GitHub user polarisGitHub edited a discussion: [Q/A][Java SDK (Component)] For asynchronous calls, should I use asyncCall or virtual threads?
### Pre-check
- [x] I am sure that all the content I provide is in English.
### Apache Dubbo Component
Java SDK (apache/dubbo)
### Details
Which way is better?
```java
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
Future<A> fa = executor.submit(() -> remoteService.query(req));
// do somethings
A a = fa.get();
Result result = future.get();
}
```
```java
CompletableFuture<Result> future = RpcContext.getServiceContext().asyncCall(() -> remoteService.query(req));
// do somethings
Result result = future.get();
```
### Code of Conduct
- [X] I agree to follow this project's [Code of Conduct](https://www.apache.org/foundation/policies/conduct)
GitHub link: https://github.com/apache/dubbo/discussions/16379
----
This is an automatically sent email for notifications@dubbo.apache.org.
To unsubscribe, please send an email to: notifications-unsubscribe@dubbo.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org
Re: [D] [Q/A][Java SDK (Component)] For asynchronous calls, should I use asyncCall or virtual threads? [dubbo]
Posted by "polarisGitHub (via GitHub)" <gi...@apache.org>.
GitHub user polarisGitHub edited a discussion: [Q/A][Java SDK (Component)] For asynchronous calls, should I use asyncCall or virtual threads?
### Pre-check
- [ ] I am sure that all the content I provide is in English.
### Apache Dubbo Component
Java SDK (apache/dubbo)
### Details
Which way is better?
```java
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
Future<A> fa = executor.submit(() -> remoteService.query(req));
// do somethings
A a = fa.get();
Result result = future.get();
}
```
```java
CompletableFuture<Result> future = RpcContext.getServiceContext().asyncCall(() -> remoteService.query(req));
// do somethings
Result result = future.get();
```
### Code of Conduct
- [X] I agree to follow this project's [Code of Conduct](https://www.apache.org/foundation/policies/conduct)
GitHub link: https://github.com/apache/dubbo/discussions/16379
----
This is an automatically sent email for notifications@dubbo.apache.org.
To unsubscribe, please send an email to: notifications-unsubscribe@dubbo.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org
Re: [D] [Q/A][Java SDK (Component)] For asynchronous calls, should I use asyncCall or virtual threads? [dubbo]
Posted by "LI123456mo (via GitHub)" <gi...@apache.org>.
GitHub user LI123456mo 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/
Thank you so much for your response @rikhmaier , learned a lot here .
@polarisGitHub hope this answers?
GitHub link: https://github.com/apache/dubbo/discussions/16379#discussioncomment-18624914
----
This is an automatically sent email for notifications@dubbo.apache.org.
To unsubscribe, please send an email to: notifications-unsubscribe@dubbo.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org