Go-gRPC的簡單使用
阿新 • • 發佈:2020-08-17
RPC簡介
Remote Procedure Call,縮寫為 RPC)是一個計算機通訊協議。RPC是一種伺服器-客戶端(Client/Server)模式,經典實現是一個通過傳送請求-接受迴應
進行資訊互動的系統
gRPC開發步驟
- 編寫
.proto
檔案,生成指定語言原始碼 - 編寫服務端程式碼
- 編寫客戶端程式碼
安裝
建立專案
mkdir grpc_demo
cd grpc_demo
go mod init grpc_demo
安裝gRPC
go get -u google.golang.org/grpc
安裝Protocol Buffers v3
安裝用於生成gRPC服務程式碼的協議編譯器。軟體地址
- 解壓下載好的檔案
- 把
protoc
二進位制檔案的路徑加到環境變數中 - 安裝protoc的Go外掛
go get -u github.com/golang/protobuf/protoc-gen-go
- 編譯外掛
protoc-gen-go
將會安裝到$GOBIN
,預設是$GOPATH/bin
,它必須在你的$PATH
中以便協議編譯器protoc
能夠找到它。
- 編譯外掛
C:\Users\Albin>d: D:\>cd D:\Practice\Scripts\go\src\gitee.com\bliub\stdgo D:\Practice\Scripts\go\src\gitee.com\bliub\stdgo>mkdir grpc_demo D:\Practice\Scripts\go\src\gitee.com\bliub\stdgo>cd grpc_demo D:\Practice\Scripts\go\src\gitee.com\bliub\stdgo\grpc_demo>go mod init grpc_demo go: creating new go.mod: module grpc_demo D:\Practice\Scripts\go\src\gitee.com\bliub\stdgo\grpc_demo>go get -u google.golang.org/grpc go: downloading golang.org/x/net v0.0.0-20190311183353-d8887717615a go: extracting golang.org/x/net v0.0.0-20190311183353-d8887717615a go: downloading golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a go: extracting golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a go: finding golang.org/x/sys latest go: finding google.golang.org/genproto latest go: finding golang.org/x/net latest D:\Practice\Scripts\go\src\gitee.com\bliub\stdgo\grpc_demo>go get -u github.com/golang/protobuf/protoc-gen-go
示例
建立專案程式碼目錄結構
mkdir helloworld\pb
mkdir helloworld\server
mkdir helloworld\client
D:\Practice\Scripts\go\src\gitee.com\bliub\stdgo\grpc_demo>tree
資料夾 PATH 列表
卷序列號為 A021-AE06
D:.
└─helloworld
├─client
├─pb
└─server
編寫proto程式碼
gRPC是基於Protocol Buffers。
Protocol Buffers
是一種與語言無關,平臺無關的可擴充套件機制,用於序列化結構化資料。使用Protocol Buffers
編寫檔案
vi helloworld/pb/helloworld.proto
syntax = "proto3"; // 版本宣告,使用Protocol Buffers v3版本
package pb; // 包名
// 定義一個打招呼服務
service Greeter {
// SayHello 方法
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// 包含人名的一個請求訊息
message HelloRequest {
string name = 1;
}
// 包含問候語的響應訊息
message HelloReply {
string message = 1;
}
生成go語言原始碼
protoc -I helloworld/ helloworld/pb/helloworld.proto --go_out=plugins=grpc:helloworld
在gRPC_demo/helloworld/pb
目錄下會生成helloworld.pb.go
檔案。
編寫server端go程式碼
vi grpc_demo/helloworld/server/server.go
package main
import (
"fmt"
"net"
pb "grpc_demo/helloworld/pb"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
)
type server struct{}
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{Message: "hello " + in.Name}, nil
}
func main() {
// 監聽本地的8972埠
lsnr, err := net.Listen("tcp", ":8972")
if err != nil {
fmt.Printf("failed to listen: %v", err)
return
}
s := grpc.NewServer() // 建立gRPC伺服器
pb.RegisterGreeterServer(s, &server{}) // 在gRPC服務端註冊服務
reflection.Register(s) // 在給定的gRPC伺服器上註冊伺服器反射服務
// Serve方法在lsnr上接受傳入連線,為每個連線建立一個ServerTransport和server的goroutine。
// 該goroutine讀取gRPC請求,然後呼叫已註冊的處理程式來響應它們。
err = s.Serve(lsnr)
if err != nil {
fmt.Printf("failed to serve: %v", err)
return
}
}
編譯並執行
cd helloworld/server
go build
./server
編寫客戶端go程式碼
package main
import (
"context"
"fmt"
pb "grpc_demo/helloworld/pb"
"google.golang.org/grpc"
)
func main() {
// 連線伺服器
conn, err := grpc.Dial(":8972", grpc.WithInsecure())
if err != nil {
fmt.Printf("faild to connect: %v", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)
// 呼叫服務端的SayHello
r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: "biao"})
if err != nil {
fmt.Printf("could not greet: %v", err)
}
fmt.Printf("Greeting: %s !\n", r.Message)
}
執行
gRPC跨語言呼叫
使用Python
語言編寫Client
,然後向上面使用go
語言編寫的server
傳送RPC請求
安裝相關python模組
pip3 install grpcio
pip3 install grpcio-tools
pip3 install protobuf
生成python程式碼
在gRPC_demo
目錄執行命令
python -m grpc_tools.protoc -I helloworld/pb/ --python_out=helloworld/client/ --grpc_python_out=helloworld/client/ helloworld/pb/helloworld.proto
上面命令執行完成後,在grpc_demo/helloworld/client/
目錄生成如下兩個python檔案
編寫python版client程式碼
#!/usr/bin/env python
# coding=utf-8
import logging
import grpc
import helloworld_pb2
import helloworld_pb2_grpc
def run():
# 注意(gRPC Python Team): .close()方法在channel上是可用的。
# 並且應該在with語句不符合程式碼需求的情況下使用。
with grpc.insecure_channel('localhost:8972') as channel:
stub = helloworld_pb2_grpc.GreeterStub(channel)
response = stub.SayHello(helloworld_pb2.HelloRequest(name='標'))
print("Greeter client received: {}!".format(response.message))
if __name__ == '__main__':
logging.basicConfig()
run()