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

gRPC使用的分析

彭高畅
2023-12-01

看了docker的源码就不得不了解一下gRPC这个鬼东西。下面借鉴一下别人的实例,让我这个初次接触的人做一个,最直接的分析。

  1. 首先编译安装protobuf 工具。

    go get google.golang.org/grpc
    go get -u github.com/golang/protobuf/{proto,protoc-gen-go} //下载proto转换为go语言的工具
    export PATH=$PATH:$GOPATH/bin // 将其加入环境变量
  2. 创建一个rpcsrv.proto文件。

    syntax = "proto3"; 
    package xcl;  
    enum UserStatus {  
    OFFLINE = 0;  
    ONLINE = 1;  
    }  
    message UserInfo {  
    int32 id = 1;   
    string name = 2;   
    UserStatus status = 3 ;  
    }  
    message UserID {  
    int32 id = 1;   
    }  
    message funcResponse {      
    string reply = 1;  
    }
    // 定义将要用到的rpc调用方法,参数和返回值都在上面进行了定义
    service UserService { 
    rpc Login(UserInfo) returns (funcResponse){};  
    rpc Logout(UserID) returns (funcResponse){};  
    } 
    
  3. 编译生成对应的go代码。

    protoc rpcsrv.go --go_out=plugins=grpc:

    rpcsrv.pb.go文件如下,主要就是生成了相应的结构体:

    type UserInfo struct {  
    Id     int32      `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`  
    Name   string     `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`  
    Status UserStatus `protobuf:"varint,3,opt,name=status,enum=xcl.UserStatus" json:"status,omitempty"`  
    }  
    type UserID struct {  
    Id int32 `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`  
    }  
    type FuncResponse struct {  
    Reply string `protobuf:"bytes,1,opt,name=reply" json:"reply,omitempty"`  
    }  
  4. 变成服务端程序:

    package main  
    import (  
    pb "xcl"  
    "log"  
    "net"  
    "os"  
    "golang.org/x/net/context"  
    "google.golang.org/grpc"  
    )  
    func main() {  
    log.SetOutput(os.Stdout)  
    lis, err := net.Listen("tcp", port)  
    if err != nil {  
        log.Fatalf("failed to listen: %v", err)  
    }  
    s := grpc.NewServer()  
    pb.RegisterUserServiceServer(s, &server{})  
    log.Println("Server......")  
    s.Serve(lis)  
    }  
    const (  
    port = ":50051"  //监听的端口
    )  
    type server struct{}  //定义server的结构体
    // 实现Login的方法,参数和返回值与最上面定义的proto都有对应的关系。
    func (s *server) Login(ctx context.Context, usr *pb.UserInfo) (*pb.FuncResponse, error) {  
    log.Println("Server...... Login() UserInfo:", usr)  
    usr.Id = 100  
    strId := "100" //strconv.Itoa(usr.Id)  
    return &pb.FuncResponse{Reply: strId}, nil  
    }  
    // 实现Logout的方法  
    func (s *server) Logout(ctx context.Context, uid *pb.UserID) (*pb.FuncResponse, error) {  
    log.Println("Server...... Logout() UserID:", uid)  
    return &pb.FuncResponse{Reply: "Logout Successed."}, nil  
    }  
  5. 定义客户端:

    package main  
    import (  
    "log"  
    "os"  
    "strconv"  
    pb "xcl"  
    "golang.org/x/net/context"  
    "google.golang.org/grpc"  
    )  
    const (  
    address = "localhost:50051"  // 服务器的套接字
    )  
    func main() {  
    log.SetOutput(os.Stdout)  
    conn, err := grpc.Dial(address)  //首先创建一个 gRPC channel 和服务器交互
    if err != nil {  
        log.Fatalf("did not connect: %v", err)  
    }  
    defer conn.Close()  
    // 一旦 gRPC channel 建立起来,我们需要一个客户端存根去执行RPC。我们通过.proto生成的pb包提供的NewUserServiceClient方法来完成。
    c := pb.NewUserServiceClient(conn)  
    var status pb.UserStatus  
    status = pb.UserStatus_ONLINE  
    userInfo := &pb.UserInfo{  
        //Id:     10,         //proto.Int32(10),  
        Name:   "XCL-gRPC", //proto.String("XCL-gRPC"),  
        Status: status,  
    }  
    
    // 直接调用相应的方法,来远程调用服务端。
    r, err := c.Login(context.Background(), userInfo)  
    if err != nil {  
        log.Fatalf("登录失败!  %v", err)  
    }  
    log.Println("Login():", r)  
    
    uid, err := strconv.ParseInt(r.Reply, 10, 32)  
    if err != nil {  
        log.Fatalf("非数字  %v", err)  
    }  
    
    userID := &pb.UserID{int32(uid)}  
    out, err := c.Logout(context.Background(), userID)  
    log.Println("Logout():", out)  
    }  

参考:

[1] gRPC官方文档

 类似资料: