RPC简单介绍
简单流程:
- 客户端发送数据(以字节流的方式)
- 服务端接受数据,并解析,根据约定知道要执行什么,然后把结果返回给客户端。
RPC就是:
- 将上述流程封装一下,使其操作更加优化
- 使用一些大家都认可的协议使其规范化
- 做成一些框架,直接或间接产生利益
安装
1、安装protobuf
2、检查安装结果
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 上面去下载下来,复制到
目录下,分别进入到 protobuf/proto 和 protobuf/protoc-gen-go/ 目录下执行
命令
4、运用,在文件目录里运行
1 2
| protoc --go_out=plugins=grpc:. user.proto 1
|
生成了新文件,成功
使用gRPC的流程
- 写好 .proto 描述文件定义 RPC 的接口,
- 然后用 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
| 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)) lis, _ := net.Listen("tcp", ":8081") rpcServer.Serve(lis) 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: ×tamp.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); }
|