当前位置: 首页 > 工具软件 > Go-kit > 使用案例 >

4.【go-kit教程】go-kit集成grpc和protobuf

施选
2023-12-01

环境准备

  • 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)

  1. 编写协议文件在 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 结构体。
  2. 在项目根目录下运行以下命令生成 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)
}

完整代码

  • https://github.com/daniuEvan/go-kit-demo/tree/main/kit-grpc-demo
 类似资料: