go 使用grpc和grpcurl

安装依赖和工具

# ubuntu安装protobuf
apt install libprotobuf-dev protobuf-compiler protoc-gen-go protoc-gen-go-grpc -y
# 查看protobuf版本
protoc --version

# 安装grpcurl
wget https://github.com/fullstorydev/grpcurl/releases/download/v1.8.7/grpcurl_1.8.7_linux_x86_64.tar.gz
tar -zxvf grpcurl_1.8.7_linux_x86_64.tar.gz -C /usr/bin
rm -f /usr/bin/LICENSE
# 查看grpcurl版本
grpcurl --version

运行代码

目录结构

student.proto

syntax = "proto3";

package pb;

option go_package = "./pb";

message GetStudentRequest {
    string name = 1;
}

message GetStudentResponse {
    int32 age = 1;
}

service StudentService {
    rpc getStudent(GetStudentRequest) returns (GetStudentResponse) {};
}

server.go

package main

import (
	"context"
	"fmt"
	"net"

	"test/proto/pb"

	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
)

type StudentService struct{}

func (s *StudentService) GetStudent(ctx context.Context, req *pb.GetStudentRequest) (*pb.GetStudentResponse, error) {
	return &pb.GetStudentResponse{Age: 10}, nil
}

func main() {
	listener, err := net.Listen("tcp", "127.0.0.1:1000")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer listener.Close()

	grpcServer := grpc.NewServer()
	reflection.Register(grpcServer)
	pb.RegisterStudentServiceServer(grpcServer, &StudentService{})
	if err = grpcServer.Serve(listener); err != nil {
		fmt.Println(err)
	}
}

client.go

package main

import (
	"context"
	"fmt"

	"test/proto/pb"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
)

func main(){
	conn, err := grpc.Dial("127.0.0.1:1000", grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		fmt.Println(err)
		return
	}
	defer conn.Close()

	client := pb.NewStudentServiceClient(conn)
	if response, err := client.GetStudent(context.Background(), &pb.GetStudentRequest{
		Name: "1",
	}); err != nil {
		fmt.Println(err)
		return
	} else {
		fmt.Printf("student age is %d", response.Age)
	}
}

生成pb对应的go文件

protoc student.proto --go_out=./ --go-grpc_out=./ --go-grpc_opt=require_unimplemented_servers=false

运行

JWT(JSON Web Tokens)完成认证鉴权,与加解密无关。
grpc枚举类型必须是int32,与go枚举类型支持自定义类型有所不同。

使用grpcurl

查看服务列表

grpcurl -plaintext 127.0.0.1:1000 list

查看服务方法

grpcurl -plaintext localhost:1000 list pb.StudentService

查看服务方法详情

grpcurl -plaintext localhost:1000 describe pb.StudentService

查看服务方法参数类型

grpcurl -plaintext localhost:1000 describe pb.GetStudentRequest

调用服务方法

grpcurl -plaintext -d '{"name":""}' localhost:1000 pb.StudentService/getStudent

问题

grpc不支持服务端返回nil

func (s *StudentService) GetStudent(ctx context.Context, req *pb.GetStudentRequest) (*pb.GetStudentResponse, error) {
	return nil, nil
}

使用google.golang.org/grpc v1.61.0,在发送数据时序列化因msg是nil而报错rpc error: code = Internal desc = grpc: error while marshaling: proto: Marshal called with nil。

使用google.golang.org/grpc v1.66.0,在发送数据时序列化不会因msg是nil而报错,返回零值,不是nil。

即服务端返回nil,client拿到的是非nil结果。

posted on 2024-09-07 10:12  王景迁  阅读(22)  评论(0编辑  收藏  举报

导航