RPC 是一种跨语言的协议,它可以让我们在不同的语言之间进行通信。 远程过程调用(英语:Remote Procedure Call,缩写为 RPC)是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一个
地址空间(通常为一个开放网络的一台计算机)的子程序,而程序员就像调用本地程序一样,无需额外地为这个交互作用编程(无需关注细节)。
RPC是一种服务器-客户端(Client/Server)模式,经典实现是一个通过发送请求-接受回应进行信息交互的系统。
1
2
go install github.com/golang/protobuf/protoc-gen-go@v1.4.0
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1
不推荐使用 google.golang.org/protobuf/cmd/protoc-gen-go@v1.26
这个版本太高了,可能会遇到以下这个问题,
1
2
3
--go_out: protoc-gen-go: plugins are not supported; use 'protoc --go-grpc_out=...' to generate gRPC
See https://grpc.io/docs/languages/go/quickstart/#regenerate-grpc-code for more information.
参考解决方案记一次奇妙的go-protobuf包升级之旅
protoc 工具安装
下载地址 ,下载解压将 bin 目录添加到环境变量中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
syntax = "proto3" ; // 使用protobuf版本3
option go_package = "./protobuf" ; // 这个影响生成的目录及go的package命名
// 定义一个计算服务, 输入为CalcRequest, 输出为CalcResponse
service CalculatorService {
rpc calc ( CalcRequest ) returns ( CalcResponse ) {};
}
// 计算两个数某种运算(如加法)的参数
message CalcRequest {
double a = 1 ;
double b = 2 ;
string op = 3 ;
}
// 计算结果
message CalcResponse {
double r = 1 ;
}
1
protoc --go_out= plugins = grpc:. calculator.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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package main
import (
"context"
"fmt"
"net"
"go.src/grpc/calculator/protobuf"
"google.golang.org/grpc"
)
// 实现: CalculatorServiceServer接口, 在calculator.pb.go中定义
type server struct {}
func ( s server ) Calc ( ctx context . Context , req * protobuf . CalcRequest ) ( resp * protobuf . CalcResponse , err error ) {
a := req . GetA ()
b := req . GetB ()
op := req . GetOp ()
resp = & protobuf . CalcResponse {}
switch op {
case "+" :
resp . R = a + b
case "-" :
resp . R = a - b
case "*" :
resp . R = a * b
case "/" :
if b == 0 {
err = fmt . Errorf ( "divided by zero" )
return
}
resp . R = a / b
}
return
}
// 启动rpc server
func main () {
listener , err := net . Listen ( "tcp" , "localhost:3233" )
if err != nil {
panic ( err )
}
s := grpc . NewServer ()
protobuf . RegisterCalculatorServiceServer ( s , & server {})
fmt . Println ( "server start" )
err = s . Serve ( listener )
if err != nil {
panic ( err )
}
}
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
package main
import (
"context"
"fmt"
"log"
"go.src/grpc/calculator/protobuf"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func main () {
// 连上grpc server
//conn, err := grpc.Dial("localhost:3233", grpc.WithInsecure())
conn , err := grpc . Dial ( "localhost:3233" , grpc . WithTransportCredentials ( insecure . NewCredentials ()))
if err != nil {
log . Fatalf ( "did not connect: %v" , err )
}
defer conn . Close ()
c := protobuf . NewCalculatorServiceClient ( conn )
// 调用远程方法
resp , err := c . Calc ( context . Background (), & protobuf . CalcRequest {
A : 1 ,
B : 2 ,
Op : "+" ,
})
if err != nil {
fmt . Println ( "calc err: " , err . Error ())
return
}
fmt . Println ( "calc success,respR: " , resp . GetR ()) // 3
}
server
client
示例源码地址