跳转到内容

Helidon — 让 Java 微服务用同步代码写出反应式性能

是什么

Helidon 是 Oracle 出的 Java 微服务框架,对标 Spring Boot 但走完全不同的路线。它的招牌功能叫 Helidon Nima:第一个用 Java 21 虚拟线程从零写的 web server——不是给老 server 打虚拟线程补丁,而是整个内核重写。

日常类比:以前 Java 高并发就像「每个客户都派一个全职服务员」(OS 线程),人多就吃不消;后来反应式编程让「服务员一边端盘一边记下每个客户位置」(异步回调),人多顶得住但服务员快疯了;虚拟线程是「让酒店随时变出 100 万个临时服务员,每个客户分一个」——酒店(JVM)背后只用几个 OS 线程轮流跑这些临时工。

// Helidon Nima 写一个 GET /hello
WebServer.builder()
.routing(r -> r.get("/hello", (req, res) -> res.send("hi")))
.build()
.start();

代码就是普通同步阻塞写法,但能扛住几万并发——因为 server 给每个请求开一根虚拟线程,阻塞 I/O 不占 OS 线程。

为什么重要

  • 以前 Java 选型只有两条难走的路:Spring Boot 简单但反应式吃力,Netty/反应式 性能好但代码像天书。Helidon Nima 给了第三条
  • 它是 MicroProfile 规范的官方实现之一——/health、/metrics、/openapi、配置注入这些都开箱即用,不用拼一堆 starter
  • Oracle 维护,跟 JDK 21 / JDK 26 的虚拟线程进展同步走在最前面
  • 是观察”虚拟线程到底有没有用”的最直接窗口——它整个内核就是为虚拟线程重写的
  • 学一个 Helidon 等于看清”JVM 里同步代码 + 高并发”这条新路线长什么样

核心要点

记 3 件事:

  1. Nima WebServer = 虚拟线程内核:HTTP 解析 + IO 调度全用虚拟线程实现,不依赖 netty。每个连接、每个请求各一根虚拟线程。
  2. Helidon SE vs MP 两套 API:SE 是裸 server(更轻、自己接管路由);MP 是 MicroProfile(CDI 注解 + JAX-RS,像轻量版 Spring)。同一份 server 内核,两种写法。
  3. 同步代码 + 异步性能:开发体验和 fastapi / gin / axum 这种”同步外表”接近,但 JVM 线程模型完全不同——它靠的是 JDK 自己的 carrier thread 调度,不是 async runtime。

实践案例

案例 1:30 秒起一个 REST 端点(Helidon SE)

public static void main(String[] args) {
WebServer.builder()
.routing(routing -> routing
.get("/greet/{name}", (req, res) -> {
String name = req.path().pathParameters().value("name");
res.send("Hello, " + name);
}))
.port(8080)
.build()
.start();
}

跑起来就是一个能扛高并发的 HTTP server,没有 Spring 那一堆 @Annotation,纯 Java 调用。

案例 2:高并发下游调用——同步代码顶住 1 万 QPS

res -> {
// 同步 HTTP 调下游,看似每个请求会"卡住"
String data = httpClient.get("http://downstream/api").body();
res.send(data);
}

如果是传统 Tomcat(200 OS 线程池),1 万并发立刻打爆;Helidon Nima 里这段代码会被运行时挂在虚拟线程上,OS 线程仍然只有几十个,但能同时挂 1 万根虚拟线程等下游回。

案例 3:MicroProfile 健康检查(Helidon MP)

@ApplicationScoped
@Liveness
public class CustomCheck implements HealthCheck {
public HealthCheckResponse call() {
return HealthCheckResponse.up("custom");
}
}

加这一个类,/health/live 端点自动注册,K8s 探针直接对接——这是 MicroProfile 规范带来的”组件开箱即用”。

案例 4:配置热加载

Config config = Config.create();
String url = config.get("downstream.url").asString().orElse("http://default");

application.yaml 改了,注入点会拿到新值。MP 模式下结合 @ConfigProperty 注入,写起来像 Spring 的 @Value,但底层走的是 MicroProfile Config 规范。

踩过的坑

  1. JDK 版本硬约束:Helidon 4 必须 JDK 21+,Helidon 5 起跟 JDK 26 走。公司还在 JDK 8/11 项目升不动,得先升 JDK
  2. 3.x → 4.x API 大改:老 Helidon SE 代码(Reactive Server / WebServer 旧 API)几乎要重写。不是平滑升级,是迁移
  3. 虚拟线程不是银弹:业务里有 synchronized 长持锁、ThreadLocal 误用,会把虚拟线程钉死在 carrier thread 上——并发优势瞬间消失。要换 ReentrantLock 或者用 ScopedValue
  4. 生态比 Spring Boot 小一个数量级:第三方 starter / Stack Overflow 答案 / 中文资料都少很多。选型前要确认”我用的库有 Helidon 集成吗”
  5. 冷启动不是 Helidon 强项:JVM 起步比 Quarkus Native 慢得多。Serverless 短任务、按请求计费场景要慎选——还是 Quarkus + GraalVM 更合适

适用 vs 不适用场景

适用

  • 新项目、JDK 21+ 起步、想要高并发同步写法
  • 已经在用 MicroProfile 规范(不想全套换 Spring)
  • 微服务网关、IO 密集型 BFF、调用链多但每步都阻塞 IO 的场景

不适用

  • 老项目(JDK 8/11,没法升)→ 用 spring-boot
  • CPU 密集型计算服务(虚拟线程帮不上忙)→ 选什么框架差别不大
  • 团队不熟 Java 生态、想要 Native Image 启动快 → quarkus 更合适
  • 全栈一体(不只 backend,要前后端协同)→ 还是 Spring Boot 生态广

跟同类对比

框架内核主打JDK 要求
Helidon Nima自研虚拟线程同步代码 + 高并发21+
spring-bootTomcat / Netty生态最广17+(多数)
quarkusVert.x / NettyNative Image 启动快17+
micronautNetty + AOT编译期 DI、低内存17+

四家在”JDK 21 虚拟线程支持”上都跟进了,但 Helidon Nima 是唯一从零按虚拟线程设计内核的——其它三家是给老内核打补丁。

怎么选

  • 团队全在 Spring 生态、生态优先 → Spring Boot
  • 想 Native Image / Serverless 冷启动 → Quarkus
  • 编译期 DI、内存敏感(IoT、Lambda)→ Micronaut
  • 高并发 IO 同步写法、JDK 21 起步、不要 Native → Helidon Nima

历史小故事(可跳过)

  • 2018-2019:Oracle 内部要给 Java EE → Jakarta EE 的微服务方向找新框架,启动 Project Helidon
  • 2019 年 9 月:Helidon 1.0 发布,分 SE(响应式)和 MP(MicroProfile)两套 API,底层 Netty
  • 2022-2023:JDK 19/21 推出虚拟线程预览/正式版,Oracle 决定为虚拟线程重写 web server
  • 2023 年:Helidon 4 发布,Nima WebServer 砍掉 Netty,HTTP 全部跑在虚拟线程上——Java 微服务”同步写法 + 高并发”路线第一次有正式答案

学到什么

  1. 运行时模型可以重写:Nima 砍掉 Netty 重做底层证明 JVM 上同步语义和高并发不再矛盾——前提是有虚拟线程
  2. 规范 + 实现要分清:MicroProfile 是规范,Helidon 是实现之一(还有 Open Liberty、Payara)。换框架不等于改业务代码
  3. API 跨大版本不能怕断:3 → 4 的 API 重写让 Oracle 敢用 Nima 重做内核,老用户痛但路径走对了
  4. 看代码风格选语言:同样是”同步外表”,Helidon 跟 fastapi / gin / axum / actix-web 是同一类设计哲学,只是 JVM 用虚拟线程实现,其它语言用 async runtime
  5. 银弹之外要看真实瓶颈:虚拟线程解决 IO 阻塞场景,CPU 密集型/锁竞争重的业务该慢还是慢——选型要看真实负载形态

延伸阅读

关联

  • spring-boot —— 同语言生态,Helidon 是 Spring 之外的轻量选项
  • quarkus —— 同样是 MicroProfile 实现,主打 Native Image
  • micronaut —— 同生态轻量框架,主打编译期 DI
  • fastapi —— Python 里”同步写法 + 高并发”的同思路代表
  • axum —— Rust 里同思路(用 async runtime 而非虚拟线程)
  • gin —— Go 里”goroutine = 虚拟线程”思想的最早工业落地
  • actix-web —— Rust 里另一种异步选型,对照看 JVM/Rust 思路差异