The grpc-gateway is a plugin of the Google protocol buffers compiler protoc. It reads protobuf service definitions and generates a reverse-proxy server which 'translates a RESTful HTTP API into gRPC. This server is generated according to the google.api.http
annotations in your service definitions.
grpc-gateway是protoc的一个插件。它读取gRPC服务定义,并生成一个反向代理服务器,将RESTful JSON API转换为gRPC。此服务器是根据gRPC定义中的自定义选项生成的。
安装
protoc:https://github.com/protocolbuffers/protobuf/releases
go install github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger github.com/golang/protobuf/protoc-gen-go
简单示例
https://github.com/grpc-ecosystem/grpc-gateway示例项目目录:
.
├── cmd
│ ├── echoclient
│ │ └── client.go
│ ├── echohttp
│ │ └── httpserver.go
│ └── echoserver
│ └── server.go
├── echopb
│ ├── echo.pb.go
│ ├── echo.pb.gw.go
│ ├── echo.proto
│ ├── echo.swagger.json
│ └── google
│ ├── api
│ │ ├── annotations.proto
│ │ ├── httpbody.proto
│ │ └── http.proto
│ └── rpc
│ ├── code.proto
│ ├── error_details.proto
│ └── status.proto
├── go.mod
├── go.sum
echopb/google拷贝自grpc-gateway/third_party。
echo.proto增加 a google.api.http
annotation:
syntax = "proto3"; package echopb; import "google/api/annotations.proto"; message StringMessage{ string value = 1; } service EchoService{ rpc Echo(StringMessage) returns (StringMessage){ option (google.api.http) = { post: "/v1/example/echo" body: "*" }; } }
echo.pb.go echo.pb.gw.go和echo.swagger.json都是工具生成的。
protoc -I ./echopb/ --go_out=plugins=grpc:echopb echopb/echo.proto protoc -I echopb --grpc-gateway_out=logtostderr=true:echopb/ echopb/echo.proto protoc -I echopb/ --swagger_out=logtostderr=true:echopb/ echopb/echo.proto
server.go,监听在localhost:8088
package main import ( "context" "log" "net" "google.golang.org/grpc" pb "example/echopb" ) const ( port = ":8088" ) type server struct{ pb.UnimplementedEchoServiceServer } func (s *server) Echo(ctx context.Context, req *pb.StringMessage) (*pb.StringMessage, error) { return &pb.StringMessage{Value: req.GetValue()}, nil } func main(){ lis, err := net.Listen("tcp", port) if err != nil { log.Fatalf("failed to listen: %v ", err) } s := grpc.NewServer() pb.RegisterEchoServiceServer(s, &server{}) if err := s.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) } }
client.go
package main import ( "context" "log" "time" "google.golang.org/grpc" pb "example/echopb" ) const ( addr = "localhost:8088" ) func main(){ ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() conn, err := grpc.DialContext(ctx, addr, grpc.WithBlock(), grpc.WithInsecure()) if err != nil { log.Fatalf("did not connect: %v ", err) } defer conn.Close() c := pb.NewEchoServiceClient(conn) log.Printf("echo request: wang ") r, err := c.Echo(ctx, &pb.StringMessage{Value: "wang"}) if err != nil { log.Fatalf("could not echo: %v ", err) } log.Printf("Echo reply: %s ", r.GetValue()) }
httpserver.go
package main import ( "context" "flag" "net/http" "github.com/golang/glog" "github.com/grpc-ecosystem/grpc-gateway/runtime" "google.golang.org/grpc" gw "example/echopb" ) var ( grpcServerEndpoint = flag.String("grpc-server-endpoint", "localhost:8088", "gRPC server endpoint") ) func run() error{ ctx := context.Background() ctx, cancel := context.WithCancel(ctx) defer cancel() mux := runtime.NewServeMux() opts := []grpc.DialOption{grpc.WithInsecure()} err := gw.RegisterEchoServiceHandlerFromEndpoint(ctx, mux, *grpcServerEndpoint, opts) if err != nil { return err } return http.ListenAndServe(":8081", mux) } func main(){ flag.Parse() defer glog.Flush() if err := run(); err != nil { glog.Fatal(err) } }
可通过如下命令本地查看swagger接口:
swagger serve --host=0.0.0.0 --port=9000 --no-open echopb/echo.swagger.json
http://localhost:9000/docs 查看到POST地址: /v1/example/echo
POST: curl -XPOST --data '{"value":"wangqing"}' http://localhost:8081/v1/example/echo
openNESS应用
eaa.proto:https://gitee.com/yuxio/specs/blob/master/schema/pb/eaa.proto
syntax = "proto3"; package openness.eaa; option go_package = "github.com/open-ness/eaa;eaa"; import "google/protobuf/empty.proto"; import "google/api/annotations.proto"; import "protoc-gen-swagger/options/annotations.proto";
生成swagger:
protoc -I./pb -I../../ben-krieger/grpc-gateway -I../../ben-krieger/grpc-gateway/third_party/googleapis --swagger_out=allow_repeated_fields_in_body=true,logtostderr=true:eaa ./pb/eaa.proto
参考:
1. https://github.com/grpc-ecosystem/grpc-gateway https://grpc-ecosystem.github.io/grpc-gateway/
2. grpc-gateway应用 煎鱼 grpc + grpc gateway
3. OpenNESS eaa.proto生成swagger yaml
4. gRPC 调试工具 gRPC-swagger java版本的调试工具