乐趣区

关于rpc:最简最速搭建grpc分布式服务的Mac系统开发环境

[TOC]

环境详情

  • golang 1.18
  • macOS Big Sur
  • protobuf 3

基本原理

整个 RPC 过程就是:

  1. 客户端 发送 数据(以字节流的形式)
  2. 服务端接管,并解析。依据约定晓得要晓得执行什么。而后把后果返回客户端

RPC 就是把——

  1. 上述过程封装下,使其操作更加优化
  2. 应用一些大家都认可的协定 使其规范化

那么——GRPC 框架中采纳了 protobuf 作为这个过程中消息传递的数据结构。

什么是 Protobuf

Protobuf 是 Protocol Buffers 的简称,它是 Google 公司开发的一种数据描述语言,用于形容一种轻便高效的结构化数据存储格局,并于 2008 年对外开源。Protobuf 能够用于结构化数据串行化,或者说序列化。它的设计十分实用于在网络通讯中的数据载体,很适宜做数据存储或 RPC 数据交换格局,它序列化进去的数据量少再加上以 K-V 的形式来存储数据,对音讯的版本兼容性十分强,可用于通信协定、数据存储等畛域的语言无关、平台无关、可扩大的序列化构造数据格式。开发者能够通过 Protobuf 附带的工具生成代码并实现将结构化数据序列化的性能。

本教程将在接下来的内容中形容 .proto 文件的语法以及如何通过 .proto 文件生成数据拜访类和 grpc 服务类,并以此为根底搭建繁难的 grpc 服务端开发环境。

工具装置

新建工程,抉择 go modules,配置 GOPROXY 等操作不再赘述;

  1. 下载 grpc 依赖

go get -u google.golang.org/grpc@v1.51.0

  1. brew 装置 protocol

brew install protobuf

装置后能够执行命令 protoc,作为 protocol 编译器应用,可能通过两头文件 .proto 转译成各种语言的 grpc 文件

brew install protoc-gen-go

转译两头文件成 go 文件的插件

brew install protoc-gen-go-grpc

转译两头文件成 go-grpc 文件的插件。

留神:如果装置失败那可能是依赖装置失败,间接 brew intall 装置依赖即可。

至此,工具和依赖装置结束,接下来将构建工程。

环境搭建

工程 go-rpc-server 构造:

.

├── client.go ——用于编写客户端测试

├── go.mod

├── go.sum

├── main.go ——服务端的启动

├── pbfiles ——该目录用于搁置原始 proto 文件

│ └── Prod.proto

├── services ——该目录用于搁置转译出的 go 文件

首先新建 .proto 文件,该示例中演示用于展现商品库存的 API,因而取名为 Prod.proto;

编辑有如下内容:

syntax="proto3";
option go_package ="go-rpc-server/services"; // 相对路径 和 protoc 的 flag go_out 拼接
//package services; // 该选项配置后 客户端申请须要多加上 services. 的门路
message  ProdRequest {int32 prod_id =1;   // 传入的商品 ID}
message ProdResponse{int32 prod_stock=1;// 商品库存}
// 这里的内容其实能够独立配置一个.proto 文件,因为 rpc 服务类的文件会独立于数据拜访类
service ProdService {rpc GetProdStock (ProdRequest) returns (ProdResponse);
}

文档参考 Protocol Buffer Basics: Go

随后通过 protoc 生成——

1. 数据拜访类

protoc –go_out=./../ pbfiles/Prod.proto

2.rpc 服务类

protoc –go-grpc_out=./../ pbfiles/Prod.proto

若报错

只须要在 proto 文件中退出
option go_package =”go-rpc-server/services”;
指定两头文件生成 go 文件的门路即可。

编写服务类的实现

值得一提的是从某个版本开始,服务类的实现接口产生了以下变动:

type ProdServiceServer interface {GetProdStock(context.Context, *ProdRequest) (*ProdResponse, error)
    mustEmbedUnimplementedProdServiceServer() // 这里是新增的}

并且在生成的 grpc 服务类中有——

type UnimplementedProdServiceServer struct {
}

func (UnimplementedProdServiceServer) GetProdStock(context.Context, *ProdRequest) (*ProdResponse, error) {return nil, status.Errorf(codes.Unimplemented, "method GetProdStock not implemented")
}
func (UnimplementedProdServiceServer) mustEmbedUnimplementedProdServiceServer() {}

实现了上述接口;官网举荐咱们在实现服务类时,嵌套该构造体。

因而有以下实现:

type ProdService struct {UnimplementedProdServiceServer}

func (ps *ProdService) GetProdStock(context.Context, *ProdRequest) (*ProdResponse, error) {return &ProdResponse{ProdStock: 233}, nil
}

接口返回了咱们的 mock 数据;

启动服务

编写 main 函数,通过 net 包进行监听, 执行 go run main.go

func main() {rpcServer := grpc.NewServer()
    services.RegisterProdServiceServer(rpcServer, new(services.ProdService))

    lis, _ := net.Listen("tcp", ":8087")

    rpcServer.Serve(lis)
}

至此,咱们的 grpc 服务端环境搭建结束。

客户端测试

多的不说,间接上客户端代码:

func main() {cli, _ := grpc.DialContext(context.Background(),
        "localhost:8087",
        grpc.WithTransportCredentials(insecure.NewCredentials()),
    )
    req := &services.ProdRequest{}
    rsp := &services.ProdResponse{}
    err := cli.Invoke(context.Background(),
        "/ProdService/GetProdStock", req, rsp)
    if err != nil {log.Fatal(err)
    }
    fmt.Println(rsp.ProdStock)
}

执行go run client.go,于是有:

搞定!

本文由博客一文多发平台 OpenWrite 公布!

退出移动版