使用grpc开发RPC服务

grpc简介#

gRPC是谷歌开源的一款跨平台、高性能的RPC框架,目前主要使用它来进行后端微服务的开发。
可能会有的同学对RPC不太熟悉,其实在笔者看来,RPC和HTTP并无多大的区别都是一种调用方式,区别则是在于RPC会限制传输协议、传输的参数等,以此换取高效的传输流程,比如grpc就使用的是google开源的protobuf协议,使用TCP的方式进行传输,使得请求比起普通的JSON+HTPP更加快捷。关于更多protobuf的信息,可以查看这里

必要的准备#

  • 了解Golang及其生态
  • 安装gRPc及protobuf,教程
  • 安装golang
  • 安装protobuf编译器
一、首先我们需要定义好整个服务的protobuf文件user.proto
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
syntax = "proto3";  // 指定语法格式,注意 proto3 不再支持 proto2 的 required 和 optional
package  proto;      // 指定生成的 user.pb.go 的包名,防止命名冲突
 
// service 定义开放调用的服务,即 UserInfoService 微服务
service  UserInfoService {
// rpc 定义服务内的 GetUserInfo 远程调用
rpc  GetUserInfo (UserRequest) returns (UserResponse) {
}
}
 
// message 对应生成代码的 struct
 
// 定义客户端请求的数据格式
 
message  UserRequest {
 
// [修饰符] 类型 字段名 = 标识符;
 
string  name = 1;
 
}
 
// 定义服务端响应的数据格式
 
message  UserResponse {
 
int32  id = 1;
 
string  name = 2;
 
int32  age = 3;
 
repeated  string  title = 4;  // repeated 修饰符表示字段是可变数组,即 slice 类型
 
}

然后我们通过protoc命令编译proto文件,生成对应的go文件

1
protoc -I . --go_out=plugins=grpc:. ./user.proto 

二、我们来实现server.go

首先我们应该明确实现的步骤:
1、实现GetUserInfo接口
2、使用gRPC建立服务,监听端口
3、将我们实现的服务注册到gRPC中去
话不多说,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package  main
 
import (
"fmt"
"log"
"net"
// Import the generated protobuf code
pb "go_mirco_service/proto"
"golang.org/x/net/context"
"google.golang.org/grpc"
 
)
type  UserInfoService  struct{}
var  u  = UserInfoService{}
 
func (u *UserInfoService) GetUserInfo(ctx context.Context, req *pb.UserRequest) (resp *pb.UserResponse, err error) {
 
name  := req.Name
 
if name ==  "leoython" {
 
resp  =  &pb.UserResponse{
 
Id: 233,
 
            Name: name,
 
Age: 20,
 
            Title: []string{"Gopher"},
 
        }
 
    }
 
err  =  nil
 
return
 
}
 
   
 
func  main() {
 
port  :=  ":2333"
 
l, err  := net.Listen("tcp", port)
 
if err !=  nil {
 
        log.Fatalf("listen error: %v\n", err)
 
    }
 
    fmt.Printf("listen %s\n", port)
 
s  := grpc.NewServer()
 
   
 
// 将 UserInfoService 注册到 gRPC
 
// 注意第二个参数 UserInfoServiceServer 是接口类型的变量
 
// 需要取地址传参
 
    pb.RegisterUserInfoServiceServer(s, &u)
 
    s.Serve(l)
 
} 

到此我们就实现了利用gRPC实现了一个非常简单但是五脏俱全的RPC服务,但是却出现了一个问题,我们无法直接调用,所以我们还需要实现一个调用server的客户端,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package  main
 
   
 
import (
 
"fmt"
 
"log"
 
pb "go_mirco_service/proto"
 
"golang.org/x/net/context"
 
"google.golang.org/grpc"
 
)
 
 
func  main() {
 
conn, err  := grpc.Dial(":2333", grpc.WithInsecure())
 
if err !=  nil {
 
        log.Fatalf("dial error: %v\n", err)
 
    }
 
defer conn.Close()
 
   
 
// 实例化 UserInfoService 微服务的客户端
 
client  := pb.NewUserInfoServiceClient(conn)
 
   
 
// 调用服务
 
req  :=  new(pb.UserRequest)
 
req.Name  =  "leoython"
 
resp, err  := client.GetUserInfo(context.Background(), req)
 
if err !=  nil {
 
        log.Fatalf("resp error: %v\n", err)
 
    }
 
    fmt.Printf("Recevied: %v\n", resp)
 
} 

结语#

至此,我们已经学会使用gRPC进行开发,采用protobuf进行参数的定义,下一篇笔者将会使用grpc-gateway将RPC接口转换为rest接口供客户端调用,而不需要客户端实现RPC,这也是现在主流微服务的一种服务提供方式,对外使用REST,对内使用RPC

 

可参考https://blog.csdn.net/Wendy_LWZ/article/details/81330799

thrift跨语言通信实例    https://blog.csdn.net/koli6678/article/details/80740749

posted @   鲸鱼的海老大  阅读(13)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示
CONTENTS