假定我们有一个项目需求,希望用Rpc作为内部API的通讯,同时也想对外提供Restful Api,写两套又太繁琐不符合
于是我们想到了Grpc以及Grpc Gateway,这就是我们所需要的
假设以及安装好go环境以及grpc所需的组件
// +build tools
package tools
import (
_ "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"
)
运行go mod tidy以解决版本。通过运行安装
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
这将在$GOBIN目录中放置三个二进制文件;
your_history_service.proto:
syntax = "proto3";
package example;
message StringMessage {
string value = 1;
}
service YourService {
rpc Echo(StringMessage) returns (StringMessage) {}
}
your_new_service.proto:
syntax = "proto3";
package example;
+
+import "google/api/annotations.proto";
+
message StringMessage {
string value = 1;
}
service YourService {
- rpc Echo(StringMessage) returns (StringMessage) {}
+ rpc Echo(StringMessage) returns (StringMessage) {
+ option (google.api.http) = {
+ post: "/v1/example/echo"
+ body: "*"
+ };
+ }
}
您将需要向protoc编译器提供所需的第三方protobuf文件。它们包含在此存储库中的third_party/googleapis文件夹下,建议将它们复制到protoc生成文件结构中。如果您已按照Buf样式指南的要求来构造原型文件,则可以将文件复制到顶级./google文件夹中。
上述话是官方文档中所介绍,我将下述目录下的复制粘贴到protoc文件的根目录下
E:\GOPATH\pkg\mod\github.com\grpc-ecosystem\[email protected]\third_party\googleapis
1.这是生成RPC存根serveric.pd.go的命令
protoc -I. --go_out=plugins=grpc,paths=source_relative:./gen/go/ your/service/v1/your_service.proto
2.使用生成反向代理 protoc-gen-grpc-gateway
protoc -I. --grpc-gateway_out=logtostderr=true,paths=source_relative:./gen/go \
your/service/v1/your_service.proto
示例代码
/*
@Time : 2020/6/8 10:21
@Author : zhb
@File : serviceHttp
@Software: GoLand
*/
package main
import (
"context"
"flag"
"github.com/golang/glog"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
pb "grpcDemo/protoc"
"net/http"
)
var (
// command-line options:
// gRPC server endpoint
grpcServerEndpoint = flag.String("grpc-server-endpoint", "localhost:9090", "gRPC server endpoint")
)
type SearchServiceHttp struct{}
func (s *SearchServiceHttp) Search(ctx context.Context, r *pb.SearchRequest) (*pb.SearchResponse, error) {
return &pb.SearchResponse{Query: r.GetQuery() + " Server"}, nil
}
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 := pb.RegisterSearchServiceHandlerServer(ctx, mux, &SearchServiceHttp{})
if err != nil {
return err
}
// Start HTTP server (and proxy calls to gRPC server endpoint)
return http.ListenAndServe(":8081", mux)
}
func main() {
flag.Parse()
defer glog.Flush()
if err := run(); err != nil {
glog.Fatal(err)
}
}
完整代码示例