官方项目地址
demo搭建过程
遵循官方文档搭建即可
项目初始化
建立项目后编辑go.mod文件
// +build tools
package tools
import (
_ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway"
_ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2"
_ "google.golang.org/grpc/cmd/protoc-gen-go-grpc"
_ "google.golang.org/protobuf/cmd/protoc-gen-go"
)
运行go mod tidy.
也可以:
$ 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
检查命令行下是否已有以下文件:
protoc-gen-grpc-gateway
protoc-gen-openapiv2
protoc-gen-go
protoc-gen-go-grpc
demo搭建
以下过程使用了官方说明的命令行工具,和依赖protobuffer文件option配置的方式生成扩展
编写proto buffer文件
your_service.proto
:
syntax = "proto3";
package your.service.v1;
option go_package = "github.com/yourorg/yourprotos/gen/go/your/service/v1";
message StringMessage {
string value = 1;
}
service YourService {
rpc Echo(StringMessage) returns (StringMessage) {}
}
生成gRPC stubs
protoc -I . \
--go_out ./gen/go/ --go_opt paths=source_relative \
--go-grpc_out ./gen/go/ --go-grpc_opt paths=source_relative \
your/service/v1/your_service.proto
实现grpc服务
server.go
package main
import (
"context"
"google.golang.org/grpc"
pb "grpcGatewayTest/gen/go"
"log"
"net"
)
type server struct {
pb.UnimplementedYourServiceServer
}
func (s *server) Echo(ctx context.Context, in *pb.StringMessage) (*pb.StringMessage, error) {
log.Printf("Received: %v", in.GetValue())
//return in, nil
return &pb.StringMessage{Value: "_" + in.GetValue()}, nil
}
func main() {
lis, err := net.Listen("tcp", ":50001")
if err != nil {
log.Fatalf("failed to listen : %v", err)
}
s := grpc.NewServer()
pb.RegisterYourServiceServer(s, &server{})
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve : %v", err)
}
}
client.go
package main
import (
"context"
"google.golang.org/grpc"
pb "grpcGatewayTest/gen/go"
"log"
"os"
"time"
)
const address = "localhost:50001"
func main() {
conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewYourServiceClient(conn)
string := "hello"
if len(os.Args) > 1 {
string = os.Args[1]
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.Echo(ctx, &pb.StringMessage{Value: string})
if err != nil {
log.Fatalf("echo failed : %v", err)
}
log.Printf("get echo: %v", r.GetValue())
}
启动
服务端:
go run your_service_server/main.go
启动客户端:
go run your_service_client/main.go
得到预期的返回结果.
2021/03/04 11:47:43 get echo: _hello
使用protoc-gen-grpc-gateway生成反向代理
protoc -I . --grpc-gateway_out ./gen/go \
--grpc-gateway_opt logtostderr=true \
--grpc-gateway_opt paths=source_relative \
your/service/v1/your_service.proto
编写http反向代理服务端点:
直接用官方实例就行了.
package main
import (
"context"
"flag"
"net/http"
"github.com/golang/glog"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"google.golang.org/grpc"
gw "grpcGatewayTest/gen/go"
)
var (
// command-line options:
// gRPC server endpoint
grpcServerEndpoint = flag.String("grpc-server-endpoint", "localhost:50001", "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.RegisterYourServiceHandlerFromEndpoint(ctx, mux, *grpcServerEndpoint, opts)
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)
}
}
启动http反向代理:
通过
curl -X POST http://localhost:8081/v1/example/echo -H "Content-Type: application/json" -d'{"value": "foo"}'
可以得到返回值
{"value":"_foo"}%
continue
可以继续依照官方文档生成swagger文件.