grpc-gateway是protoc的一个插件。它读取gRPC服务定义,并生成一个反向代理服务器,将RESTful JSON API转换为gRPC。此服务器是根据gRPC定义中的自定义选项生成的。
image.png

安装

安装插件

  1. go get \
  2. github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway \
  3. github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2 \
  4. google.golang.org/protobuf/cmd/protoc-gen-go \
  5. google.golang.org/grpc/cmd/protoc-gen-go-grpc

下载需要使用到的proto
google/protobuf下载参考https://www.yuque.com/jw-go/mqm3eb/gy8npv
google/api 下载地址https://github.com/googleapis/googleapis
文件相互依赖,一次性下载后比较省心

  1. lxdeMacBook-Pro-2:src lx$ pwd
  2. /Users/lx/gopath/src
  3. lxdeMacBook-Pro-2:src lx$ tree google/
  4. google/
  5. ├── api
  6. ├── BUILD.bazel
  7. ├── README.md
  8. ├── annotations.proto
  9. ├── auth.proto
  10. ├── backend.proto
  11. ├── billing.proto
  12. ├── client.proto
  13. ├── config_change.proto
  14. ├── consumer.proto
  15. ├── context.proto
  16. ├── control.proto
  17. ├── distribution.proto
  18. ├── documentation.proto
  19. ├── endpoint.proto
  20. ├── error_reason.proto
  21. ├── expr
  22. ├── BUILD.bazel
  23. ├── cel.yaml
  24. ├── v1alpha1
  25. ├── BUILD.bazel
  26. ├── checked.proto
  27. ├── conformance_service.proto
  28. ├── eval.proto
  29. ├── explain.proto
  30. ├── syntax.proto
  31. └── value.proto
  32. └── v1beta1
  33. ├── BUILD.bazel
  34. ├── decl.proto
  35. ├── eval.proto
  36. ├── expr.proto
  37. ├── source.proto
  38. └── value.proto
  39. ├── field_behavior.proto
  40. ├── http.proto
  41. ├── httpbody.proto
  42. ├── label.proto
  43. ├── launch_stage.proto
  44. ├── log.proto
  45. ├── logging.proto
  46. ├── metric.proto
  47. ├── monitored_resource.proto
  48. ├── monitoring.proto
  49. ├── quota.proto
  50. ├── resource.proto
  51. ├── service.proto
  52. ├── serviceconfig.yaml
  53. ├── servicecontrol
  54. ├── BUILD.bazel
  55. ├── README.md
  56. └── v1
  57. ├── BUILD.bazel
  58. ├── check_error.proto
  59. ├── distribution.proto
  60. ├── http_request.proto
  61. ├── log_entry.proto
  62. ├── metric_value.proto
  63. ├── operation.proto
  64. ├── quota_controller.proto
  65. ├── service_controller.proto
  66. ├── servicecontrol.yaml
  67. └── servicecontrol_gapic.yaml
  68. ├── servicemanagement
  69. ├── BUILD.bazel
  70. ├── README.md
  71. └── v1
  72. ├── BUILD.bazel
  73. ├── resources.proto
  74. ├── servicemanagement_gapic.legacy.yaml
  75. ├── servicemanagement_gapic.yaml
  76. ├── servicemanagement_grpc_service_config.json
  77. ├── servicemanagement_v1.yaml
  78. └── servicemanager.proto
  79. ├── source_info.proto
  80. ├── system_parameter.proto
  81. └── usage.proto
  82. └── protobuf
  83. ├── any.proto
  84. ├── api.proto
  85. ├── compiler
  86. └── plugin.proto
  87. ├── descriptor.proto
  88. ├── duration.proto
  89. ├── empty.proto
  90. ├── field_mask.proto
  91. ├── source_context.proto
  92. ├── struct.proto
  93. ├── timestamp.proto
  94. ├── type.proto
  95. └── wrappers.proto

跑通流程

image.png
1.准备proto文件

  1. syntax = "proto3";
  2. package protobuf;
  3. import "google/api/annotations.proto";
  4. option go_package = "protobuf;protobuf";
  5. message StringMessage{
  6. string value = 1;
  7. }
  8. service EchoService{
  9. rpc Echo(StringMessage) returns (StringMessage){
  10. option (google.api.http) = {
  11. post: "/v1/example/echo"
  12. };
  13. }
  14. }

2.生成grpc存根

  1. protoc --proto_path=/Users/lx/gopath/src --proto_path=. \
  2. --go_out=plugins=grpc,paths=source_relative:. \
  3. test.proto

3.生成代理文件

  1. protoc --proto_path=/Users/lx/gopath/src --proto_path=. \
  2. --grpc-gateway_out . \
  3. --grpc-gateway_opt logtostderr=true \
  4. --grpc-gateway_opt paths=source_relative \
  5. test.proto

4.service端

  1. package main
  2. import (
  3. "log"
  4. "net"
  5. pb "commons/grpc/protobuf"
  6. "golang.org/x/net/context"
  7. "google.golang.org/grpc"
  8. )
  9. const (
  10. RPCPORT = ":9192"
  11. )
  12. type server struct{}
  13. func (s *server) Echo(ctx context.Context, in *pb.StringMessage) (*pb.StringMessage, error) {
  14. log.Println("request: ", in.Value)
  15. return &pb.StringMessage{Value: "Hello " + in.Value}, nil
  16. }
  17. func main() {
  18. lis, err := net.Listen("tcp", RPCPORT)
  19. if err != nil {
  20. log.Fatalf("failed to listen: %v", err)
  21. }
  22. s := grpc.NewServer()
  23. pb.RegisterEchoServiceServer(s, &server{})
  24. log.Println("rpc服务已经开启")
  25. s.Serve(lis)
  26. }

5.gateway

  1. package main
  2. import (
  3. "context"
  4. "flag"
  5. "log"
  6. "net/http"
  7. gw "commons/grpc/protobuf"
  8. "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
  9. "google.golang.org/grpc"
  10. )
  11. var (
  12. echoEndpoint = flag.String("echo_endpoint", "localhost:9192", "endpoint of Gateway")
  13. )
  14. func run() error {
  15. ctx := context.Background()
  16. ctx, cancel := context.WithCancel(ctx)
  17. defer cancel()
  18. mux := runtime.NewServeMux()
  19. opts := []grpc.DialOption{grpc.WithInsecure()}
  20. err := gw.RegisterEchoServiceHandlerFromEndpoint(ctx, mux, *echoEndpoint, opts)
  21. if err != nil {
  22. return err
  23. }
  24. log.Println("服务开启")
  25. return http.ListenAndServe(":8080", mux)
  26. }
  27. func main() {
  28. flag.Parse()
  29. if err := run(); err != nil {
  30. log.Fatal(err)
  31. }
  32. }
  1. 测试
  • 404

image.png

  • ok

image.png

  • methmod not allowed

image.png