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

本文介绍了在macOSBigSur环境下,使用golang1.18和protobuf3来构建RPC服务的基本步骤。首先解释了RPC的基本原理,然后详细讲述了protobuf的作用和功能。接着,文章提供了安装protobuf及相关插件的命令,并展示了如何创建.proto文件,生成Go代码,以及实现服务类。最后,文章给出了服务端和客户端的代码示例,完成了gRPC服务端的搭建和客户端测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

环境详情

  • 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

若报错

file

只需要在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,于是有:

file



搞定!

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

常鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值