RPC简单介绍

简单流程:

  1. 客户端发送数据(以字节流的方式)
  2. 服务端接受数据,并解析,根据约定知道要执行什么,然后把结果返回给客户端。

RPC就是:

  1. 将上述流程封装一下,使其操作更加优化
  2. 使用一些大家都认可的协议使其规范化
  3. 做成一些框架,直接或间接产生利益

安装

1、安装protobuf

1
brew install protobuf

2、检查安装结果

1
protoc  --version

3、安装golang for protobuf插件

1
2
go get github.com/golang/protobuf/protoc-gen-go
go get -u -v github.com/golang/protobuf/protoc-gen-go

go get = git clone + go install
这里会慢的要死
所以我这里采取的是先直接在github 上面去下载下来,复制到

1
/src/github.com/golang/

目录下,分别进入到 protobuf/proto 和 protobuf/protoc-gen-go/ 目录下执行

1
2
go build
go install

命令

4、运用,在文件目录里运行

1
2
protoc --go_out=plugins=grpc:. user.proto
1

生成了新文件,成功

使用gRPC的流程

  1. 写好 .proto 描述文件定义 RPC 的接口,
  2. 然后用 protoc(带 gRPC 插件)基于 .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
// Prod.proto
syntax="proto3";
package services;
import "google/protobuf/timestamp.proto"

enum ProAreas {
A=110;
B=120;
C=130;
}

message ProdRequest {
int32 prod_id=1;
ProAreas prod_areas=2;
google.protobuf.Timestamp order_time=3;
}

message ProdResponse {
int32 prod_stock=1;
}

message QuerySize {
int32 size=1;
}

message ProdResponseList {
repeated ProdResponse prores=1;
}

service ProdService {
rpc GetProdStock(ProdRequest) returns (ProdResponse){};
rpc GetProdStocks(QuerySize) returns (ProdResponseList){};
}

执行protoc -go_out=grpc:./ Prod.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
import (
"context"
"google.golang.org/grpc"
)

type ProdService struct {}

func (this *ProdService) GetProdStock(ctx context.Context, in *ProdRequest) (*ProdResponse, error) {
var stock int32 =0;
if in.ProdArea== ProdArea_A{
stock=20
}
return &ProdResponse(ProStock:stock),nil
}

func (this *ProdService) GetProdStocks(ctx context.Context, in *QuerySize) (*ProdResponseList, error) {
prodres := []*ProdResponse {
&ProdResponse(ProdStock:28),
&ProdResponse(ProdStock:29),
&ProdResponse(ProdStock:30),
}
return &ProdResponseList{
Prodres:prodres
},nil
}

服务端

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
package main

import (
"google.golang.org/grpc"
"XXX/services"
"net"
)

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

// 提供grpc服务
lis, _ := net.Listen("tcp", ":8081")
rpcServer.Serve(lis)

// 提供http服务
mux := http.NewServeMux()
mux.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
rpcServer.ServerHTTP(writer.request)
})
httpServer := &http.Server {
Addr:":8081",
Handler:mux,
}
httpServer.ListenAndServer()
}

客户端

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
package main

import (
"google.golang.org/grpc"
"github.com/golang/protobuf/ptypes/timestamp"
"XXX/services"
"net"
)

func main() {
conn, err := grpc.Dial(":8081", grpc.WithInsecure())
if err != nil {
log.Fatal(err)
}
defer conn.Close()

ProdClient := services.NewProdServiceClient(conn)
Prodresponse, err := ProdClient.GetProdStock(
context.Backgroud(),
&services.ProdRequest(
ProdId:12,
ProAreas:ProAreas_A,
order_time: &timestamp.Timestamp(Seconds:time.Now().Unix())
)
)
if err != nil {
log.Fatal(err)
}
fmt.Println(ProdResponse.ProdStock)
}

插件本身要做负载均衡

一个插件要开多份,各自拥有不同的workspace

network有socket、

工厂方法

示例

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
syntax="proto3";
package v1;
import "google/protobuf/timestamp.proto"

message ToDO {
int64 id=1;
string title=2;
string description=3;
google.protobuf.TimeStamp.reminder=4;
}

message CreateRequest {
string api=1;
ToDo toDO=2;
}

message CreateResponse {
string api=1;
int64 id=2;
}

message ReadRequest {
string api=1;
int64 id=2;
}

message ReadResponse {
string api=1;
ToDo toDo=2;
}

message UpdateRequest {
string api=1;
ToDo toDo=2;
}

message UpdateResponse {
string api=1;
int update=2;
}

message DeleteRequest {
string api=1;
int64 id=2;
}

message DeleteResponse {
string api=1;
int64 deleted=2;
}

message ReadAllRequest {
string api=1;
}

message ReadAllResponse {
string api=1;
repeated ToDo toDos=2;
}

service ToDoService {
rpc Create(CreateRequest) returns (CreateResponse);
rpc Read(ReadRequest) returns (ReadResponse);
rpc Update(UpdateRequest) returns (UpdateResponse);
rpc Delete(DeleteRequest) returns (DeleteResponse);
rpc ReadAll(ReadAllRequest) returns (ReadAllResponse);
}