|
本帖最后由 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文件夹
执行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
使用postman调用restful接口,成功!!!
|
|