4.【go-kit教程】go-kit集成grpc和protobuf
环境准备
- gokit工具集:
go get github.com/go-kit/kit
; - http请求路由组件:
go get github.com/gorilla/mux
; - grpc:参考博客 https://bigox.top/pages/39b3f2/
- protobuf:参考博客 https://bigox.top/pages/8deba5/
目录结构
.
├── pb
│ └── hello.proto
├── cmd
│ └── server
│ └── main.go
├── pkg
│ ├── endpoint.go
│ ├── service.go
│ └── transport.go
└── go.mod
定义api(protobuf)
-
编写协议文件在
pb
目录下创建hello.proto
文件,内容如下:protobufCopy code syntax = "proto3"; package pb; service HelloService { rpc SayHello (HelloRequest) returns (HelloResponse); } message HelloRequest { string name = 1; } message HelloResponse { string message = 1; }
- 该协议文件定义了一个名为
HelloService
的服务,该服务只有一个方法SayHello
,它需要一个HelloRequest
参数并返回一个HelloResponse
结构体。
- 该协议文件定义了一个名为
-
在项目根目录下运行以下命令生成 gRPC 代码(生成代码在pb文件夹目录下):
protoc --go-grpc_out=./pb --go_out=./pb ./pb/hello.proto # 以下是生成的文件 ─ pb ├── hello.pb.go ├── hello.proto └── hello_grpc.pb.go
grpcServer
-
main.go
package main import ( "fmt" "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" "google.golang.org/grpc" pb "kit-grpc/pb" "kit-grpc/pkg" "net" "os" ) func main() { logger := log.NewLogfmtLogger(os.Stderr) ln, err := net.Listen("tcp", "127.0.0.1:9090") if err != nil { level.Error(logger).Log("err", err) os.Exit(-1) } endpoints := pkg.MakeEndpoints(pkg.HelloService{}) grpcServer := pkg.NewGRPCServer(endpoints, logger) grpc := grpc.NewServer() pb.RegisterHelloServiceServer(grpc, grpcServer) err = grpc.Serve(ln) if err != nil { fmt.Printf("failed to serve: %v", err) return } }
-
service.go
package pkg import "context" type Service interface { SayHello(ctx context.Context, name string) (string, error) } type HelloService struct{} func (s HelloService) SayHello(ctx context.Context, name string) (string, error) { return "Hello, " + name + "!", nil }
-
endpoint.go
package pkg import ( "context" "github.com/go-kit/kit/endpoint" pb "kit-grpc/pb" ) type Endpoints struct { SayHello endpoint.Endpoint } func MakeEndpoints(s Service) Endpoints { return Endpoints{ SayHello: makeSayHelloEndpoint(s), } } func makeSayHelloEndpoint(s Service) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { req := request.(*pb.HelloRequest) res, err := s.SayHello(ctx, req.Name) if err != nil { return nil, err } return pb.HelloResponse{ Message: res, }, nil } }
-
transport.go
package pkg import ( "context" "github.com/go-kit/kit/log" "github.com/go-kit/kit/transport/grpc" pb "kit-grpc/pb" ) func NewGRPCServer(endpoints Endpoints, logger log.Logger) pb.HelloServiceServer { options := []grpc.ServerOption{} return &grpcServer{ sayHello: grpc.NewServer( endpoints.SayHello, decodeHelloRequest, encodeHelloResponse, options..., ), } } func decodeHelloRequest(_ context.Context, request interface{}) (interface{}, error) { req := request.(*pb.HelloRequest) return &pb.HelloRequest{Name: req.Name}, nil } func encodeHelloResponse(_ context.Context, response interface{}) (interface{}, error) { res := response.(pb.HelloResponse) return &pb.HelloResponse{Message: res.Message}, nil } type grpcServer struct { pb.UnimplementedHelloServiceServer sayHello grpc.Handler } func (s *grpcServer) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloResponse, error) { _, resp, err := s.sayHello.ServeGRPC(ctx, req) if err != nil { return nil, err } return resp.(*pb.HelloResponse), nil }
grpcClient
/**
* @date: 2023/2/19
* @desc:
*/
package main
import (
"context"
"google.golang.org/grpc"
pb "kit-grpc/pb"
"log"
)
func main() {
conn, err := grpc.Dial("127.0.0.1:9090", grpc.WithInsecure())
if err != nil {
log.Fatal("failed to dial server: ", err)
}
defer conn.Close()
client := pb.NewHelloServiceClient(conn)
resp, err := client.SayHello(context.Background(), &pb.HelloRequest{Name: "Alice"})
if err != nil {
log.Fatal("failed to call SayHello: ", err)
}
log.Println(resp.Message)
}