乐趣区

关于golang:golang-使用-gRPC

RPC

RPC(Remote Procedure Call: 近程过程调用)是一个计算机通信协议,该协定容许运行于一台计算机的程序调用另一个地址空间(通常为一个凋谢网络的一台计算机)的子程序,而程序员就像调用本地程序一样,无需额定地为这个交互作用编程(无需关注细节)。

gRPC(https://grpc.io/about)

gRPC 是一个古代的开源高性能近程过程调用(RPC)框架,能够在任何环境中运行。它能够高效地连贯数据中心中和跨数据中心的服务,并反对可插入的负载平衡、跟踪、健康检查和身份验证。它还实用于分布式计算,以连贯设施、挪动应用程序和浏览器到后端服务。

  1. 编写.proto 文件,创立 user.proto 文件
syntax = "proto3";
option go_package = "./pb_protobuf/white_board;white_board";
import "google/api/annotations.proto";
package white_board;


message ImCreateBoardRequest {
    int64  id = 1;
    int32  page_count = 2;
    string room_no = 3;
    string doc_id = 4;

    string url_background = 5;
    string page_pos = 6;
    string file_url = 7;

    string uuid = 8;
    string nickname = 9;
}

message ImBoardInfoResponse{
    int64 id = 1;
    int32 page_count = 2;
    string doc_id = 3;
    string create_time = 4;
    string update_time = 5;
}

message ImGetBoardListByRoomNoResponse{repeated ImBoardInfoResponse BoardList = 1;}
message ImGetBoardByIdRequest{int64   id = 1;}
message ImGetBoardByRoomNoRequest{string   room_no = 1;}
message ImBoardResponse{
}

service Board{rpc CreateBoard(ImCreateBoardRequest) returns (ImBoardInfoResponse){}
    rpc DeleteBoardById(ImGetBoardByIdRequest) returns (ImBoardResponse){}
    rpc DeleteBoardByRoomNo(ImGetBoardByRoomNoRequest) returns (ImBoardResponse){}
    rpc GetBoardListByRoomNo(ImGetBoardByRoomNoRequest) returns(ImGetBoardListByRoomNoResponse){}}

syntax = "proto3";

其中第一行指定了咱们应用 protocol buffers 的版本,这里应用 proto3.

option go_package = "path;name";

path:指定生成 buffers 文件的寄存目录,name:给 package 定义别名,能够与 package 不统一。

我的项目目录构造

.
├── README.md
├── app
│   ├── api
│   │   ├── board.go
│   ├── dao
│   │   ├── board.go
│   ├── model
│   │   ├── board.go
│   └── service
│       ├── board.go
├── config
│   ├── config.go
│   ├── config.local.yml
│   ├── config.yml
│   ├── database
│   │   └── database.go
│   └── init.go
├── constant
│   └── constant.go
├── gateway
│   └── gateway.go
├── go.mod
├── go.sum
├── interfaces
│   ├── impls
│   │   ├── api_error.go
│   │   └── rpc.go
│   └── inter.go
├── log
│   └── debug.log
├── main.go
├── middleware
│   ├── auth.go
│   ├── grpc_exception.go
│   ├── recovery.go
│   └── zap_log.go
├── pb_protobuf
│   ├── white_board
│   │   ├── board.pb.go
├── protobuf
│   ├── white_board
│   │   ├── board.proto
├── s.sh
└── util
    ├── grpc.go
    └── util.go

编写 shell 脚本 s.sh

# !bin/sh

proto_files=`find ./protobuf -maxdepth 2 -name "*.proto"`
for proto_file in ${proto_files[*]}
do
    echo  `protoc --proto_path=../ -I/$GOPATH/pkg/mod/github.com/grpc-ecosystem/grpc-gateway@v1.14.6/third_party/googleapis -I./protobuf --go_out=plugins=grpc:. ${proto_file}`
done

执行 shell 脚本文件./s.sh,在 pb_protobuf 文件下主动生成 white_board 文件夹,以及对应的 board.pb.go 文件。

测试
创立 grpc 服务端,新建 serve.go 文件

package main

import (
    "google.golang.org/grpc"
    "im-whiteboard/app/api"
    "im-whiteboard/pb_protobuf/white_board"

    "log"
    "net"
)

func main() {
    // 创立 Tcp 连贯
    listener, err := net.Listen("tcp", ":8028")
    if err != nil {log.Fatalf("监听失败: %v", err)
    }

    // 创立 gRPC 服务
    grpcServer := grpc.NewServer()

    // Tester 注册服务实现者
    // 此函数在 board.pb.go 中,主动生成
    white_board.RegisterBoardServer(grpcServer,&api.Board{})

    err = grpcServer.Serve(listener)
    if err != nil {log.Fatalf("failed to serve: %v", err)
    }
}

创立 grpc 客户端 client.go 文件

package main

import (
    "context"
    im_service "im-whiteboard/pb_protobuf/white_board"
    "log"
    "google.golang.org/grpc"
)

// 定义申请地址
const (
    //ADDRESS string = constant.WhiteBoardMedia
    ADDRESS string = "127.0.0.1:8028"
)

// main 办法实现对 gRPC 接口的申请
func main() {conn, err := grpc.Dial(ADDRESS, grpc.WithInsecure())
    if err != nil {log.Fatalln("Can't connect: " + ADDRESS)
    }
    defer conn.Close()
    
    client := im_service.NewBoardClient(conn)
    res, err := client.GetBoardListByRoomNo(context.Background(),&im_service.ImGetBoardByRoomNoRequest{RoomNo:               "c0c6487ab418dabab0ccc9f32c36531b",})
    
    if err != nil {log.Fatalln("Do Format error:" + err.Error())
    }else{log.Println("res",res)
    }

}

而后别离启动 server 和 client 端,我的项目波及 mysql,redis,mongodb 这里不开展阐明。

功败垂成,此时客户端与服务端以及实现全副通信。

退出移动版