当前位置:网站首页>【Golang | gRPC】使用gRPC实现简单远程调用
【Golang | gRPC】使用gRPC实现简单远程调用
2022-07-02 15:56:00 【田土豆】
环境:
Golang: go1.18.2 windows/amd64
grpc: v1.47.0
protobuf: v1.28.0
完整代码:
https://github.com/WanshanTian/GolangLearning
cd GolangLearning/RPC/gRPC
1. 简介
gRPC
是一个基于C/S架构,使用protobuf
作为传输协议进行远程过程调用的高性能框架,前文【Golang | gRPC】protocol buffer compiler\protoc的安装,【Golang | gRPC】使用protoc编译.proto文件分别就protoc编译工具的安装和使用进行了详细的说明,下面通过一个demo具体说明gRPC的简单使用
2. 实践
现有下面一种场景:服务端保存着用户的年龄信息,客户端输入姓名,经RPC后获得对应的年龄
2.1 proto文件
2.1.1 新建gRPC文件夹,使用go mod init
初始化,创建pb文件夹,新建query.proto文件
syntax = "proto3";
package pb;
option go_package= ".;pb";
// 定义查询服务包含的方法
service Query {
rpc GetAge (userInfo) returns (ageInfo) {}
}
// 请求用的结构体,包含一个name字段
message userInfo {
string name = 1;
}
// 响应用的结构体,包含一个age字段
message ageInfo {
int32 age = 1;
}
服务端实现一个查询(Query)服务,包含一个方法GetAge
;从Golang层面理解,其实就是一个Query
接口,实现了一个GetAge
方法
2.1.2 在.\gRPC\pb
目录下使用protoc工具进行编译,在pb文件夹下直接生成.pb.go
和_grpc.pb.go
文件
protoc --go_out=./ --go-grpc_out=./ *.proto
2.2 pb.go和grpc.pb.go文件
2.2.1 查看query_grpc.pb.go
中生成的关于QueryServer
的定义
type QueryServer interface {
GetAge(context.Context, *UserInfo) (*AgeInfo, error)
mustEmbedUnimplementedQueryServer()
}
// UnimplementedQueryServer must be embedded to have forward compatible implementations.
type UnimplementedQueryServer struct {
}
func (UnimplementedQueryServer) GetAge(context.Context, *UserInfo) (*AgeInfo, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetAge not implemented")
}
func (UnimplementedQueryServer) mustEmbedUnimplementedQueryServer() {
}
QueryServer
就是根据proto文件中定义的service Query{}
生成的接口,GetAge
是我们定义的方法,mustEmbedUnimplementedQueryServer()
这个方法是protoc自行编译出的(https://github.com/grpc/grpc-go/issues/3669这里有详细的讨论,在通过protoc编译时,也可以加参数取消这个方法,protoc --go_out=./ --go-grpc_out=require_unimplemented_servers=false:./ *.proto
)
2.2.2 查看pb.go中关于UserInfo
和AgeInfo
的定义
type UserInfo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
}
func (x *UserInfo) GetName() string {
if x != nil {
return x.Name
}
return ""
}
type AgeInfo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Age int32 `protobuf:"varint,1,opt,name=age,proto3" json:"age,omitempty"`
}
func (x *AgeInfo) GetAge() int32 {
if x != nil {
return x.Age
}
return 0
}
UserInfo
和AgeInfo
结构体的前三个字段暂且用不到,通过方法Get...
可以得到自定义字段的值
2.3 服务端
在gRPC目录下新建Server文件夹,新建main.go文件
2.3.1 下面我们通过Query
这个结构体具体实现QueryServer
接口
var userinfo = map[string]int32{
"foo": 18,
"bar": 20,
}
// Query 实现了QueryServer接口
type Query struct {
pb.UnimplementedQueryServer // 通过结构体嵌套的方式默认实现mustEmbedUnimplementedQueryServer()这个方法,查看2.2.1
}
func (q *Query) GetAge(ctx context.Context, info *pb.UserInfo) (*pb.AgeInfo, error) {
age := userinfo[info.GetName()]
var res = new(pb.AgeInfo)
res.Age = age
return res, nil
}
2.3.2 服务注册并启动
func main() {
// 创建socket监听器
listener, err := net.Listen("tcp", ":1234")
if err != nil {
log.Panic(err)
}
// new一个gRPC服务器,用来注册服务
grpcserver := grpc.NewServer()
// 注册服务方法
pb.RegisterQueryServer(grpcserver, new(Query))
// 开启gRPC服务
err = grpcserver.Serve(listener)
if err != nil {
log.Panic(err)
}
}
使用RegisterQueryServer
这个方法向gRPC服务器里注册服务。这里有两个服务,很容易概念搞混,一个是gRPC服务(用来监听,完成一些网络、路由等工作),一个是业务层面的服务(这些服务可以理解为包含一定方法的接口,用来给客户端进行调用)
2.4 客户端
在gRPC目录下新建Client文件夹,新建main.go文件
2.4.1 先建立无认证的连接,生成Client,然后进行方法调用
package main
import (
"context"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"log"
"wanshantian/grpc/pb"
)
func main() {
//建立无认证的连接
conn, err := grpc.Dial(":1234", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Panic(err)
}
defer conn.Close()
client := pb.NewQueryClient(conn)
//RPC方法调用
age, _ := client.GetAge(context.Background(), &pb.UserInfo{
Name: "foo"})
fmt.Println(age)
}
注:
- 使用
grpc.WithTransportCredentials(insecure.NewCredentials())
建立无认证的连接 - 使用
client := pb.NewQueryClient(conn)
生成gRPC客户端
运行结果如下:
age:18
3 总结
- 先创建
proto
文件,定义message
和service
- 根据编译生成的
pb.go
和grpc.pb.go
文件具体实现接口 - 服务端注册服务并启动,客户端建立连接进行方法调用
边栏推荐
- Alibaba cloud sub account - Permission Policy - full control permission granted to an account and an OSS bucket
- Chapter 15 string localization and message Dictionary (1)
- 一日2篇Nature!中科大校友段镶锋团队纳米材料新成果,曾是贝尔比奖章第三位华人得主...
- What should we pay attention to in the development process of Yingguang single chip microcomputer?
- finally详解
- What are the green field and brown field models in software development - green field development and brown field development
- Longest non repeating subarray
- 应广单片机开发调试应注意的问题
- 每日一题——倒置字符串
- Modbus协议通信异常
猜你喜欢
[how is the network connected] Chapter 6 requests arrive at the server and respond to the client (end)
[非线性控制理论]8_三种鲁棒控制器的比较
蓝牙技术|物联网的可穿戴设备新工作模式,蓝牙BLE助力新工作模式
Platform management background and merchant menu resource management: merchant role management design
体验一下阿里云文字识别OCR
[how is the network connected] Chapter 4 explores access networks and network operators
应广单片机开发 工规 PMC131 带AD芯片检测电池电压单片机SOP8/14
chrome瀏覽器快速訪問stackoverflow
【网络是怎样连接的】第五章 探索服务器
win10 kms activator
随机推荐
Platform management background and business menu resource management: business permissions and menu resource management design
Alibaba cloud sub account - Permission Policy - full control permission granted to an account and an OSS bucket
Chrome browser quick access stackoverflow
Navigateur Chrome pour un accès rapide au stackoverflow
The bottom simulation implementation of vector
Daily question - inverted string
chrome瀏覽器快速訪問stackoverflow
Solution pour arrêter automatiquement les paquets Jar en cours d'exécution en éteignant le serveur de connexion xshell
应广PMC131 SOP16 16pin八位单片机
What is the experience of maintaining Wanxing open source vector database
Easyswoole3.2 restart failed
应广单片机PMS150/PMC150/PMS150C消费类单片机
一日2篇Nature!中科大校友段镶锋团队纳米材料新成果,曾是贝尔比奖章第三位华人得主...
辉芒微IO单片机FT60F010A-URT
Common SQL statements (complete example)
Asemi rectifier bridge umb10f parameters, umb10f specifications, umb10f package
松翰SN8P2511 SOP8单片机 可代烧录 提供单片机方案开发 单片机解密
[target tracking] | data set summary
finally详解
android之循环定时器实现,实现定Android时缓存清理