gRPC-Gateway 是一个强大的工具,它能够将 gRPC 服务自动暴露为 RESTful API,让客户端无需直接使用 gRPC 协议即可调用后端服务。它在微服务架构中尤其有价值,可以同时支持高性能的内部 gRPC 通信和便捷的外部 REST API。
核心原理
通过在 Protobuf 文件中添加 google.api.http 注解,gRPC-Gateway 能自动生成反向代理代码,将 HTTP/JSON 请求转换为 gRPC 调用,并将响应转换回 JSON。
// api/v1/user.proto
service UserService {
rpc GetUser(GetUserRequest) returns (User) {
option (google.api.http) = {
get: "/v1/users/{user_id}"
};
}
rpc ListUsers(ListUsersRequest) returns (ListUsersResponse) {
option (google.api.http) = {
get: "/v1/users"
};
}
rpc CreateUser(CreateUserRequest) returns (User) {
option (google.api.http) = {
post: "/v1/users"
body: "user"
};
}
}
message GetUserRequest {
string user_id = 1 [(google.api.field_behavior) = REQUIRED];
}
protobuf
// api/v1/user.proto
service UserService {
rpc GetUser(GetUserRequest) returns (User) {
option (google.api.http) = {
get: "/v1/users/{user_id}"
};
}
rpc ListUsers(ListUsersRequest) returns (ListUsersResponse) {
option (google.api.http) = {
get: "/v1/users"
};
}
rpc CreateUser(CreateUserRequest) returns (User) {
option (google.api.http) = {
post: "/v1/users"
body: "user"
};
}
}
message GetUserRequest {
string user_id = 1 [(google.api.field_behavior) = REQUIRED];
}Go 网关集成
生成网关代码后,在 Go 主程序中注册服务并启动 HTTP 和 gRPC 双端口监听:
package main
import (
"context"
"net/http"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
gw "path/to/generated/gateway"
)
func main() {
ctx := context.Background()
mux := runtime.NewServeMux()
opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
err := gw.RegisterUserServiceHandlerFromEndpoint(ctx, mux, "localhost:9090", opts)
if err != nil {
panic(err)
}
http.ListenAndServe(":8080", mux)
}
go
package main
import (
"context"
"net/http"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
gw "path/to/generated/gateway"
)
func main() {
ctx := context.Background()
mux := runtime.NewServeMux()
opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
err := gw.RegisterUserServiceHandlerFromEndpoint(ctx, mux, "localhost:9090", opts)
if err != nil {
panic(err)
}
http.ListenAndServe(":8080", mux)
}请求/响应转换模式
gRPC-Gateway 支持多种映射模式:URL 路径参数绑定、请求体映射、查询参数绑定,以及自定义 HTTP 响应头。它还支持自定义错误处理、Swagger/OpenAPI 文档自动生成,以及与 OAuth 认证的无缝集成。合理运用这些模式,开发者可以构建出既遵循 REST 惯例又具备 gRPC 高性能优势的统一 API 层。