gRPC服务默认不支持HTTP/1.1,需通过h2c启用HTTP/2明文通信;curl需加–http2且服务端用h2c.NewHandler包装;客户端DeadlineExceeded多因拦截器阻塞或超时设置过短;proto变更需手动触发go generate。
Go 的 gRPC 服务默认不支持 HTTP/1.1 请求,直接用浏览器访问 /health 或 curl GET 会返回 404 Not Found 或 HTTP/2 stream error —— 这不是代码写错了,是协议层根本对不上。
为什么 grpc.Server 启动后 curl 报错 “connection refused” 或 “protocol error”
gRPC 基于 HTTP/2,而 curl 默认走 HTTP/1.1;即使加 --http2,也需配合 TLS(或显式启用 h2c)才能连上非加密 gRPC 端口。常见表现:
- 未启用 h2c 时,
curl -v http://localhost:8080直接被拒绝或返回空响应 - 用
grpcurl测试却提示Failed to dial target host,大概率是没开Reflection或端口被防火墙拦截 - Go 服务监听
:0(随机端口)但没打印实际绑定地址,导致客户端连错
实操建议:
– 启动服务时强制指定端口并打印日志:log.Printf("gRPC server listening at %v", lis.Addr())
– 非生产环境快速验证,启用 h2c:grpcServer := grpc.NewServer(grpc.ProtocolVersion(1)) 不行 —— 正确做法是在 http.Server 中用 h2c.NewHandler() 包裹 gRPC handler(见下条)
如何让 gRPC Server 同时支持 h2c(HTTP/2 without TLS)
Go 标准库的 net/http 默认不支持 h2c,必须手动桥接。核心是把 grpc.Server 注册为 http.Handler,再用 h2c 中间件透传 HTTP/2 流量。
关键步骤: