
本文详解如何在单个 spring boot 应用中并行启用 rest(http/1.1,面向前端)与 grpc(http/2,面向内部服务),涵盖依赖配置、端口隔离、启动机制及关键注意事项。
本文详解如何在单个 spring boot 应用中并行启用 rest(http/1.1,面向前端)与 grpc(http/2,面向内部服务),涵盖依赖配置、端口隔离、启动机制及关键注意事项。
在微服务架构中,常需对外暴露 RESTful API 供 Web 或移动端调用,同时对内提供高性能、强类型的 gRPC 接口用于服务间通信。Spring Boot 本身不原生支持 gRPC,但可通过轻量级集成实现“一应用双协议”——即同一进程内同时运行嵌入式 Tomcat(或 Netty)承载 REST,以及独立的 gRPC Netty Server 承载 gRPC,二者互不干扰。
✅ 核心依赖配置(pom.xml)
需引入两套正交依赖:Spring Web 提供 REST 支持,gRPC Java 栈提供服务端能力。注意避免版本冲突,推荐使用兼容性良好的稳定版本(如 gRPC 1.42.x + Spring Boot 2.5.x):
<dependencies><!-- REST: Spring Boot Web(内置 Tomcat) --><dependency><groupid>org.springframework.boot</groupid><artifactid>spring-boot-starter-web</artifactid><!-- 版本由 spring-boot-dependencies 管控,无需显式声明 --></dependency><!-- gRPC: 基础运行时组件 --><dependency><groupid>io.grpc</groupid><artifactid>grpc-netty</artifactid><version>1.42.0</version></dependency><dependency><groupid>io.grpc</groupid><artifactid>grpc-protobuf</artifactid><version>1.42.0</version></dependency><dependency><groupid>io.grpc</groupid><artifactid>grpc-stub</artifactid><version>1.42.0</version></dependency><!-- 可选:gRPC 代码生成插件依赖(仅编译期需要) --><dependency><groupid>org.springframework.boot</groupid><artifactid>spring-boot-configuration-processor</artifactid><optional>true</optional></dependency></dependencies>
⚠️ 注意:Spring Boot 3.x 默认基于 Jakarta EE 9+,而 gRPC 1.42.x 仍依赖 javax. 包。若升级至 Spring Boot 3,请选用 gRPC 1.52.0+(已迁移至 jakarta.)并适配
grpc-netty-shaded。
? 端口分离与启动机制
REST 与 gRPC 使用完全独立的网络服务器,因此可安全绑定不同端口:
-
server.port=8080:由 Spring Boot 自动启动嵌入式 Tomcat(或 Jetty/Netty),托管@RestController。 -
grpc.server.port=9000:需手动创建并启动io.grpc.netty.NettyServer,通常通过@PostConstruct或ApplicationRunner实现。
application.properties 配置示例:
# REST 端口(Spring Boot 内置) server.port=8080 # 自定义 gRPC 端口(供自定义 Bean 读取) grpc.server.port=9000
典型 gRPC Server 初始化(Java Config):
@Component
public class GrpcServerRunner implements ApplicationRunner {
private final int grpcPort;
private Server server;
public GrpcServerRunner(@Value("${grpc.server.port}") int grpcPort) {
this.grpcPort = grpcPort;
}
@Override
public void run(ApplicationArguments args) throws Exception {
server = ServerBuilder.forPort(grpcPort)
.addService(new YourGrpcServiceImpl()) // 实现你的 gRPC service
.build()
.start();
System.out.println("gRPC Server started on port " + grpcPort);
}
@PreDestroy
public void stop() throws InterruptedException {
if (server != null && !server.isShutdown()) {
server.shutdown().awaitTermination(30, TimeUnit.SECONDS);
}
}
}
? 关键注意事项
- 线程模型隔离:REST 走 Servlet 容器线程池,gRPC 使用 Netty EventLoop,无需额外线程同步。
-
健康检查与监控:建议为 gRPC 端点添加
/actuator/health/grpc自定义健康指示器;Prometheus 可通过grpc-spring-boot-starter(社区库)一键集成指标。 -
TLS 支持:生产环境 gRPC 强烈建议启用 TLS。
NettyServerBuilder.useTransportSecurity()可加载server.crt与server.key。 -
开发体验优化:配合
protoc+protobuf-maven-plugin自动生成 Java stub,避免手写序列化逻辑。
综上,REST 与 gRPC 在 Spring Boot 中并非互斥,而是互补——前者保障开放性与生态兼容,后者提升内部通信效率与类型安全。合理分层、明确边界,即可构建兼具灵活性与高性能的现代服务。











