eumnq8 发表于 2020-12-20 18:00:11

win+go+grpc+gateway踩坑记录

本帖最后由 eumnq8 于 2020-12-20 18:04 编辑

近一段时间在搭建grpc-gateway环境,网上教程很多,但都千篇一律;不懂go语言,公司又不让上外网,照着教程摸索了很久,仔细操作还是踩了不少坑,记录一下


1、proto文件的option go_package
原理目前还不清楚,proto文件如果不加option go_package = "./your";,运行时会提示 Missing 'go_package' option in "your.proto",大意是pb文件的生成目录,和protoc有关,详细见2
参考:https://blog.csdn.net/ayqy42602/article/details/111151466

2、生成pb文件
一开始参考github教程使用的命令是:protoc -I . --go_out ./go --go_opt paths=source_relative --go-grpc_out ./go --go-grpc_opt paths=source_relative your.proto,结合1,需要在当前目录创建go文件夹,然后会自动在go文件夹中创建your文件夹,生成的相关文件就在这个目录,但是在启动grpc服务的时候报错
# command-line-arguments
.\grpc.go:32:34: cannot use &server literal (type *server) as type your.YourServer in argument to your.RegisterYourServer:
      *server does not implement your.YourServer (missing your.mustEmbedUnimplementedYourServer method)
后来修改生成pb文件的命令后,grpc服务启动成功,命令如下,需要包含grpc插件
protoc --go_out=plugins=grpc:./go/ ./your.proto

参考:http://m.aluaa.com/articles/2019 ... 9.html#b3_solo_h2_1

相关文件以及目录介绍
your.proto
syntax = "proto3";
package your;
option go_package = "./your";

import "google/api/annotations.proto";

message StringMessage {
   string value = 1;
}

service Your {
rpc Echo(StringMessage) returns (StringMessage) {
    option (google.api.http) = {
      post: "/v1/example/echo"
      body: "*"
    };
}
}

2go.bat(涉及生成grpc、grpc-gateway相关文件,所以写成了bat脚本,方便执行)
echo 生成grpc
protoc --go_out=plugins=grpc:./go/ ./your.proto
pause

echo 生成grpc-gateway
protoc -I . --grpc-gateway_out ./go your.proto
pause

echo 生产openapi
protoc -I . --openapiv2_out ./go your.proto
pause


your.proto和2go.bat放在同一目录,并在当前目录创建go文件夹
https://img.alicdn.com/imgextra/i2/827639724/O1CN01MCKy5p2LhdzLKCT3X_!!827639724.png
执行2go.bat,会在go目录生成your.swagger.json,在go/your目录生成2个文件,your.pb.go和your.pb.gw.go

切换到go安装目录,编写启动grpc、grpc-gateway服务的代码
grpc.go
package main

import (
      "log"
      "net"
               

      "google.golang.org/grpc"
      "golang.org/x/net/context"

      pb "github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/go/your"
)

const (
      PORT = ":12000"
)

type server struct{}

func (s *server) Echo(ctx context.Context, in *pb.StringMessage) (*pb.StringMessage, error) {
      log.Println("request: ", in.Value)
      return &pb.StringMessage{Value: "Hello " + in.Value}, nil
}

func main() {
      lis, err := net.Listen("tcp", PORT)
      if err != nil {
                log.Fatalf("failed to listen: %v", err)
      }

      s := grpc.NewServer()
      pb.RegisterYourServer(s, &server{})
      log.Println("rpc服务已经开启")
      s.Serve(lis)
}


gw.go
package main

import (
"context"
"flag"
"net/http"
"log"

"github.com/golang/glog"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"google.golang.org/grpc"

gw "github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/go/your"// Update
)

var (
// command-line options:
// gRPC server endpoint
grpcServerEndpoint = flag.String("grpc-server-endpoint","localhost:12000", "gRPC server endpoint")
)

func run() error {
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
defer cancel()

// Register gRPC server endpoint
// Note: Make sure the gRPC server is running properly and accessible
mux := runtime.NewServeMux()
opts := []grpc.DialOption{grpc.WithInsecure()}
err := gw.RegisterYourHandlerFromEndpoint(ctx, mux,*grpcServerEndpoint, opts)
log.Println("gw register end")
if err != nil {
    return err
}

log.Println("gw register ok")
// Start HTTP server (and proxy calls to gRPC server endpoint)
return http.ListenAndServe(":12001", mux)
}

func main() {
flag.Parse()
defer glog.Flush()

if err := run(); err != nil {
    log.Println("gw register err")
    glog.Fatal(err)
}
log.Println("gateway服务已经开启")
}


分别启动2个服务
go run grpc.go
go run gw.go
https://img.alicdn.com/imgextra/i3/827639724/O1CN01J5MfDk2LhdzQiwgvZ_!!827639724.png

使用postman调用restful接口,成功!!!
https://img.alicdn.com/imgextra/i4/827639724/O1CN01Y0p1G62LhdzLrZl1r_!!827639724.png

{:2_28:}{:2_28:}{:2_28:}
页: [1]
查看完整版本: win+go+grpc+gateway踩坑记录