Add virtual thread support for gRPC and HTTP servers on JDK 25+#13705
Open
Add virtual thread support for gRPC and HTTP servers on JDK 25+#13705
Conversation
Introduce VirtualThreads utility that enables virtual-thread-per-task executors for all gRPC servers when running on JDK 25+, with automatic fallback to platform thread pools on older JDKs. JDK 25 is required as the first LTS with the synchronized pinning fix (JEP 491). Each gRPC server gets a distinct thread pool name (core-grpc, receiver-grpc, als-grpc, ebpf-grpc) for log identification, with virtual threads prefixed by "vt:" in their names. A kill switch (SW_VIRTUAL_THREADS_ENABLED=false) allows disabling virtual threads at runtime. Also documents SW_OAL_ENGINE_DEBUG alongside the new flag in configuration-vocabulary.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Armeria's blockingTaskExecutor (default max 200 cached platform threads per server) runs all @Blocking handler methods. On JDK 25+, replace it with a fully virtual-thread-backed ScheduledExecutorService. VirtualThreadScheduledExecutor implements scheduling by sleeping in virtual threads (which does not block OS threads), requiring zero platform threads. VirtualScheduledFuture provides the ScheduledFuture contract backed by virtual thread futures. Each HTTP server gets a distinct name (core-http, receiver-http, promql-http, logql-http, zipkin-query-http, zipkin-http, firehose-http). Document thread pool changes in changes.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
JDK 25 is now the default Docker image (eclipse-temurin:25-jre). JDK 11 is kept as a -java11 variant, alongside existing -java17 and -java21. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR adds virtual thread support for gRPC and HTTP server handler threads on JDK 25+, significantly reducing platform thread usage from 800+ threads to approximately 9 ForkJoinPool carrier threads. The implementation uses runtime reflection for backward compatibility with JDK 11/17/21, requiring JDK 25+ for virtual threads due to the critical synchronized pinning fix in JEP 491. The feature can be disabled via SW_VIRTUAL_THREADS_ENABLED=false.
Changes:
- Introduced
VirtualThreadsutility with reflection-based JDK 25+ detection and executor factory methods - Created
VirtualThreadScheduledExecutorto wrap virtual threads asScheduledExecutorServicefor Armeria compatibility - Updated gRPC and HTTP servers across all receiver/query plugins to use virtual thread executors with descriptive names
- Changed default Docker base image from JDK 11 to JDK 25, keeping JDK 11/17/21 as tagged variants
- Added comprehensive documentation for the new environment variable and thread pool changes
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/VirtualThreads.java | Core utility for creating virtual thread executors with reflection-based JDK 25+ detection |
| oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/VirtualThreadScheduledExecutor.java | ScheduledExecutorService wrapper that delegates to virtual threads with sleep-based scheduling |
| oap-server/server-library/library-util/src/test/java/org/apache/skywalking/oap/server/library/util/VirtualThreadsTest.java | Comprehensive tests for virtual thread executor creation and scheduling functionality |
| oap-server/server-library/library-server/src/main/java/org/apache/skywalking/oap/server/library/server/grpc/GRPCServer.java | Updated gRPC server to use VirtualThreads.createExecutor() with descriptive thread pool names |
| oap-server/server-library/library-server/src/main/java/org/apache/skywalking/oap/server/library/server/http/HTTPServer.java | Updated HTTP server to use virtual thread scheduled executor for Armeria blocking tasks |
| oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleProvider.java | Set thread pool names for core gRPC and HTTP servers |
| oap-server/server-receiver-plugin/zipkin-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/zipkin/ZipkinReceiverProvider.java | Set blocking task name for Zipkin HTTP receiver |
| oap-server/server-receiver-plugin/skywalking-sharing-server-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/sharing/server/SharingServerModuleProvider.java | Set thread pool names for shared receiver HTTP and gRPC servers |
| oap-server/server-receiver-plugin/skywalking-ebpf-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/ebpf/provider/EBPFReceiverProvider.java | Set thread pool name for eBPF gRPC receiver |
| oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/EnvoyMetricReceiverProvider.java | Set thread pool name for Envoy ALS gRPC receiver |
| oap-server/server-receiver-plugin/aws-firehose-receiver/src/main/java/org/apache/skywalking/oap/server/receiver/aws/firehose/AWSFirehoseReceiverModuleProvider.java | Set blocking task name for AWS Firehose HTTP receiver |
| oap-server/server-query-plugin/zipkin-query-plugin/src/main/java/org/apache/skywalking/oap/query/zipkin/ZipkinQueryProvider.java | Set blocking task name for Zipkin query HTTP server |
| oap-server/server-query-plugin/promql-plugin/src/main/java/org/apache/skywalking/oap/query/promql/PromQLProvider.java | Set blocking task name for PromQL HTTP server |
| oap-server/server-query-plugin/logql-plugin/src/main/java/org/apache/skywalking/oap/query/logql/LogQLProvider.java | Set blocking task name for LogQL HTTP server |
| docs/en/setup/backend/configuration-vocabulary.md | Documented SW_VIRTUAL_THREADS_ENABLED environment variable |
| docs/en/changes/changes.md | Added changelog entry describing virtual thread support and thread pool changes |
| docker/oap/Dockerfile | Changed default base image from eclipse-temurin:11-jre to eclipse-temurin:25-jre |
| .github/workflows/publish-docker.yaml | Reordered Java 11 build step and removed explicit Java 25 variant (now default) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
.../main/java/org/apache/skywalking/oap/server/library/util/VirtualThreadScheduledExecutor.java
Show resolved
Hide resolved
.../main/java/org/apache/skywalking/oap/server/library/util/VirtualThreadScheduledExecutor.java
Show resolved
Hide resolved
.../main/java/org/apache/skywalking/oap/server/library/util/VirtualThreadScheduledExecutor.java
Show resolved
Hide resolved
.../main/java/org/apache/skywalking/oap/server/library/util/VirtualThreadScheduledExecutor.java
Show resolved
Hide resolved
- List all 11 thread pools (4 gRPC + 7 HTTP) in changelog table - Mention both gRPC and HTTP in SW_VIRTUAL_THREADS_ENABLED doc Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add virtual thread support for gRPC and Armeria HTTP server handler threads (JDK 25+)
Design summary:
Uses runtime reflection to detect JDK 25+ virtual thread APIs — zero compile-time
dependency, fully backward compatible with JDK 11/17/21. JDK 25 is required (not 21)
because JDK 21-23 has a critical
synchronizedpinning bug fixed byJEP 491 in JDK 24, and JDK 25 is the first LTS with
that fix.
core-grpc)core-http,receiver-http,promql-http,logql-http,zipkin-query-http,zipkin-http,firehose-http)On JDK 25+, all gRPC/HTTP handler pools share ~9 ForkJoinPool carrier threads instead
of up to 800+ platform threads.
Key components:
VirtualThreads— reflection-based detection & executor factoryVirtualThreadScheduledExecutor— wraps virtual threads asScheduledExecutorServicefor ArmeriaSW_VIRTUAL_THREADS_ENABLED=falseCHANGESlog.