syntax = "proto3"; package pet.service.v1; option go_package = ".;petpb"; import "google/protobuf/empty.proto"; import "google/api/annotations.proto"; import "google/protobuf/timestamp.proto"; service PetService { rpc ListPet (google.protobuf.Empty) returns (PetList) { option (google.api.http) = { get: "/v1/pets" }; } rpc GetPet (Id) returns (Pet) { option (google.api.http) = { get: "/v1/pets/{id}" }; } rpc CreatePet (Pet) returns (Pet) { option (google.api.http) = { post: "/v1/pets" }; } rpc UpdatePet (Pet) returns (Pet) { option (google.api.http) = { put: "/v1/pets/{id}" }; } rpc DeletePet (Id) returns (google.protobuf.Empty) { option (google.api.http) = { delete: "/v1/pets/{id}" }; } } message Id { string id = 1; } message PetList { repeated Pet items = 1; } message Pet { string id = 1; google.protobuf.Timestamp createdAt = 2; google.protobuf.Timestamp updatedAt = 3; string name = 4; string type = 5; string sex = 6; uint32 age = 7; bool owned = 8; }
先決條件:html
# MacOS brew install protobuf
go install \ github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway \ github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2 \ google.golang.org/protobuf/cmd/protoc-gen-go \ google.golang.org/grpc/cmd/protoc-gen-go-grpc
生成樁代碼及 swagger 文檔:nginx
protoc -I/usr/local/include -I. \ -I${GOPATH}/protobuf \ --go_out . --go_opt paths=source_relative \ --go-grpc_out . --go-grpc_opt paths=source_relative \ --grpc-gateway_out . --grpc-gateway_opt paths=source_relative \ --grpc-gateway_opt logtostderr=true \ --grpc-gateway_opt generate_unbound_methods=true \ --grpc-gateway_opt register_func_suffix=GW \ --grpc-gateway_opt allow_delete_body=true \ --openapiv2_out . --openapiv2_opt logtostderr=true \ pet.proto
先決條件:git
有了 swagger.json
藉助 swagger 相關的工具咱們就能夠生成文檔了。這裏咱們使用 redoc,經過容器啓動一個 server 渲染文檔:github
docker run -it --rm -p 80:80 \ -v $$(pwd)/pet.swagger.json:/usr/share/nginx/html/swagger.yaml \ -e SPEC_URL=swagger.yaml redocly/redoc
瀏覽器訪問 localhost,就能打開漂亮的文檔頁面了:golang
先啓動 grpc server,這裏同時經過 grpc-middleware 注入了一些經常使用中間件:docker
s := grpc.NewServer( grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer( grpc_opentracing.UnaryServerInterceptor(), grpc_prometheus.UnaryServerInterceptor, grpc_logrus.UnaryServerInterceptor(logrusEntry), grpc_recovery.UnaryServerInterceptor(), )), ) petpb.RegisterPetServiceServer(s, petsvc.NewPetService()) log.Infof("grpc server start: %s", addr) if err := s.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) }
再啓動 grpc-gateway,這裏依賴 grpc server 的地址:shell
err := gw.RegisterPetServiceGWFromEndpoint(ctx, mux, grpcAddr, opts) if err != nil { return err } log.Infof("gateway server start: %s", gatewayAddr) http.ListenAndServe(gatewayAddr, mux)
原理是在 grpc server 以前作了一層 http 反向代理,將 http 請求轉爲 protobuf 送給後端的 grpc server,對返回值再作一次轉換。官方架構圖 畫的比較清楚了。json
先決條件:segmentfault
proto 及 swagger:https://github.com/win5do/go-...後端
執行 make gen
生成 grpc 樁代碼及 swagger.json 文檔。
執行 make serve-docs
啓動容器渲染文檔。
grpc 及 gateway:https://github.com/win5do/go-...