无法为gRPC服务执行HTTP/1.x请求的问题排查求助
问题分析与解决方案
问题原因
- gRPC服务默认基于HTTP/2协议通信,直接发送HTTP/1.x请求(比如浏览器的GET请求)会被拒绝,这就是报错
Unexpected HTTP/1.x request的根本原因。 - 你在
.proto中添加的google.api.http注解仅用于定义HTTP与gRPC接口的映射规则,但原生gRPC服务不会自动处理HTTP请求,必须通过gRPC网关(grpc-gateway) 实现HTTP/1.x到gRPC的协议转换。 - 另外,你的
.proto中HTTP映射存在字段不匹配:get: "/author/{id}"里的id对应不上Author消息中的author_id字段,会导致参数无法正确解析。
修复步骤与Java示例
1. 修正.proto文件
修正HTTP映射的字段名,确保和消息字段一致:
syntax = "proto3"; package com.myapp.grpc_server.proto; option java_multiple_files = true; import "google/api/annotations.proto"; message Book { int32 book_id = 1; string title = 2; float book_price = 3; int32 pages = 4; int32 author_id = 5; } message Author { int32 author_id = 1; string first_name = 2; string last_name = 3; string gender = 4; int32 book_id = 5; } service BookAuthorService { rpc getAuthor(Author) returns (Author) { option (google.api.http) = { // 修正字段为author_id,和消息中的字段对应 get: "/author/{author_id}" // 可选:定义响应格式为JSON response_body: "*" }; } }
2. 添加依赖(Spring Boot项目)
在pom.xml中添加grpc-gateway相关依赖:
<!-- gRPC Server --> <dependency> <groupId>net.devh</groupId> <artifactId>grpc-server-spring-boot-starter</artifactId> <version>2.14.0.RELEASE</version> </dependency> <!-- gRPC Client --> <dependency> <groupId>net.devh</groupId> <artifactId>grpc-client-spring-boot-starter</artifactId> <version>2.14.0.RELEASE</version> </dependency> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>3.24.4</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-protobuf</artifactId> <version>1.51.0</version> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-stub</artifactId> <version>1.51.0</version> </dependency> <!-- 用于生成代码的Maven插件 --> <build> <extensions> <extension> <groupId>kr.motd.maven</groupId> <artifactId>os-maven-plugin</artifactId> <version>1.7.1</version> </extension> </extensions> <plugins> <plugin> <groupId>org.xolstice.maven.plugins</groupId> <artifactId>protobuf-maven-plugin</artifactId> <version>0.6.1</version> <configuration> <protocArtifact>com.google.protobuf:protoc:3.24.4:exe:${os.detected.classifier}</protocArtifact> <pluginId>grpc-java</pluginId> <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.51.0:exe:${os.detected.classifier}</pluginArtifact> <!-- 添加grpc-gateway代码生成插件 --> <plugins> <plugin> <groupId>io.grpc</groupId> <artifactId>protoc-gen-grpc-gateway</artifactId> <version>1.51.0</version> <executable>protoc-gen-grpc-gateway-${os.detected.classifier}</executable> </plugin> </plugins> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
3. 生成网关代码
执行mvn clean compile,会自动生成gRPC服务代码和对应的HTTP网关代码(如BookAuthorServiceGatewayGrpc.java)。
4. 配置gRPC网关路由
创建网关配置类,将HTTP请求转发到gRPC服务:
package com.myapp.grpcserver.config; import com.myapp.grpc_server.proto.Author; import com.myapp.grpc_server.proto.BookAuthorServiceGrpc; import com.myapp.grpc_server.proto.BookAuthorServiceGatewayGrpc; import io.grpc.StatusRuntimeException; import net.devh.boot.grpc.client.inject.GrpcClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpStatus; import org.springframework.web.server.ResponseStatusException; @Configuration public class GrpcGatewayConfig { @GrpcClient("book-author-service") // 对应@GrpcService的服务名称 private BookAuthorServiceGrpc.BookAuthorServiceBlockingStub grpcStub; @Bean public BookAuthorServiceGatewayGrpc.BookAuthorServiceGatewayImplBase bookAuthorServiceGateway() { return new BookAuthorServiceGatewayGrpc.BookAuthorServiceGatewayImplBase() { @Override public void getAuthor(Author request, io.grpc.stub.StreamObserver<Author> responseObserver) { try { Author response = grpcStub.getAuthor(request); responseObserver.onNext(response); responseObserver.onCompleted(); } catch (StatusRuntimeException e) { responseObserver.onError(new ResponseStatusException( HttpStatus.NOT_FOUND, "Author not found", e)); } } }; } }
5. 配置端口
在application.properties中分别配置HTTP网关端口和gRPC服务端口:
# gRPC服务端口(默认9090) grpc.server.port=9090 # HTTP网关端口(独立于gRPC端口,比如8080) server.port=8080 # gRPC客户端指向本地服务 grpc.client.book-author-service.address=static://localhost:9090 grpc.client.book-author-service.enableKeepAlive=true
6. 测试HTTP请求
启动应用后,通过curl或浏览器发送请求:
curl http://localhost:8080/author/1
网关会自动将HTTP请求转换为gRPC请求,转发到后端服务后,再将响应转为JSON返回。
关键说明
- gRPC网关作为中间层,负责处理HTTP/1.x请求与gRPC协议的双向转换。
- 必须保证
.proto中的HTTP映射字段与消息字段严格对应,否则参数无法绑定。 - gRPC服务和HTTP网关使用不同端口,避免协议冲突。
内容的提问来源于stack exchange,提问作者Pushpak
相关产品推荐
相关产品推荐

