為什么使用grpc
1.protocl buffer一種高效的序列化結構。
2.支持http 2.0標準化協議。
http/2
1.http/2對每個源只需創建一個持久連接,在這一個連接內,可以并行的處理多個請求和響應,而且做到不相互影響。
2.允許客戶端和服務端實現自己的數據流和連接流控制,這對我們傳輸大數據非常有幫助。
安裝 grpc 與 protobuf 解釋器
這里我們需要使用 protobuf 解釋器 將 protobuf 語法的代碼轉化成對應語言的代碼,以及使用 grpc 實現跨越性,所以我們需要先安裝它們。
本教程中只會用到 python3 以及 golang ,所以我們只安裝這兩個語言的解釋器就足夠了
python3 安裝 grpc 與 protobuf
安裝 grpc 庫
pip3 install grpcio
安裝 grpc 工具 以及 protobuf 解釋器
pip3 install grpcio-tools googleapis-common-protos
go 安裝 grcp 與 protobuf
安裝 grpc 庫:
go get -u -v google.golang.org/grpc
然后從 https://github.com/protocolbuffers/protobuf/releases 下載 與你操作系統對應的 protobuf 解釋器,這里選擇的 linux64 進行下載
首先新建一個目錄用來容納下載安裝包解壓后的文件,并進入目錄
mkdir protobuf && cd protobuf
下載 protobuf 解釋器
wget https://github.com/protocolbuffers/protobuf/releases/download/v3.6.1/protoc-3.6.1-linux-x86_64.zip
解壓縮下載的文件
unzip protoc*.zip
刪除剛才下載好的壓縮包
rm protoc*.zip
移動 protobuf 目錄到 ~/.local
mv ~/protobuf/ ~/.local/
將 protobuf 的可執行文件添加進系統變量
echo "PATH=\"\$HOME/.local/protobuf/bin:\$PATH\"" >> ~/.profile
安裝 protobuf go 語言的插件
go get -u github.com/golang/protobuf/protoc-gen-go
將插件添加進系統變量
echo "PATH=\$PATH:\$GOPATH/bin" >> ~/.profile
然后使用 cd 命令回到用戶根目錄
cd
使用 grpc
創建本次使用的工程目錄
創建工程目錄并進入目錄
mkdir $GOPATH/src/demo && cd $GOPATH/src/demo
編寫 proto 文件
proto 文件為 protobuf 的擴展名,我們編寫這個文件用于生成 python 與 go 都支持的代碼。
這里我們再新建一個目錄用來容納 proto 文件以及 使用 protobuf 編譯器轉化過的代碼
創建目錄并進入目錄
mkdir hello && cd hello
接下來開始編寫 proto 文件,這里我們新建一個 名為 hello.proto 的文件并在里面寫入以下內容
syntax = "proto3"; //指定語法為 protobuf3 語法,如果不寫這句的話默認語法為 protobuf2
package hello; //指定包名,這句在本次演示中只對 go 生效,python 的 protobuf 解釋器會忽略它service Greeter { // 定義grpc 遠程調用的方法rpc SayHello (HelloRequest) returns (HelloReply) {} // 接受 HelloRequest 返回 HelloReply,SayHello 需要自己在服務端實現
}message HelloRequest { //定義一個消息類型string name = 1; //定義 name 字段為 string 類型 tag 為 1
}message HelloReply {string message = 1;
}
完成后保存并退出編輯
生成對應語言的代碼
編輯好 proto 文件后我們并不能直接使用它,還需要將它轉化成對應語言的代碼才能使用
生成 go 語言的代碼
protoc hello.proto --go_out=plugins=grpc:.
生成 python 的代碼
python3 -m grpc_tools.protoc -I . --python_out=. --grpc_python_out=. hello.proto
然后我們回到 demo 工程目錄,開始真正的 代碼編寫
cd ..
編寫服務端
服務端端這里我采用的 go 語言進行編寫
創建一個名為 server.go 的文件并寫入以下內容
package mainimport ("context""google.golang.org/grpc""google.golang.org/grpc/reflection""log""demo/hello""net"
)const (port = ":50051" // 監聽端口
)type server struct{}func (s *server) SayHello(ctx context.Context, in *hello.HelloRequest) (*hello.HelloReply, error) { // 服務端實現 proto 中定義的方法return &hello.HelloReply{Message: "Hello " + in.Name}, nil //拼接客戶端發送過來的消息,并返回給客戶端
}func main() {lis, err := net.Listen("tcp", port) // 啟動監聽if err != nil {log.Fatalf("failed to listen: %v", err) }s := grpc.NewServer()hello.RegisterGreeterServer(s, &server{})reflection.Register(s) // 在 grpc 上注冊服務if err := s.Serve(lis); err != nil { //啟動服務并處理錯誤log.Fatalf("failed to server: %v", err) }
}
編寫 客戶端
客戶端我采用的 python3 進行編寫
創建一個名為 client.py 的文件寫入以下內容
#! /usr/bin/env python3
# -*- coding: utf-8 -*-import grpc # 導入 grpc 模塊import sys
sys.path.append('hello') # 將 hello 目錄臨時添加進環境變量,不然接下來的導入會失敗import hello_pb2 #導入我們剛才從 helloWorld.proto 生成的 python 代碼
import hello_pb2_grpcdef run():with grpc.insecure_channel('localhost:50051') as channel: # 創建連接到服務端的通道stub = hello_pb2_grpc.GreeterStub(channel) #創建提供調用的存根response = stub.SayHello(hello_pb2.HelloRequest(name = 'niconiconi')) #調用 SayHello 方法 發送我們剛才在 proto 文件中定義的字段,返回我們在 proto 中定義的返回值print("Greeter client received: " + response.message) #打印返回值if __name__ == '__main__':run()
運行 grpc 服務端與客戶端
首先我們啟動服務端
go run server.go
使用 CTRL + z 將 正在運行的服務端掛起在后臺,然后使用 bg命令使掛起的 程序繼續運行。
接下來運行我們編寫的客戶端
python3 client.py
不出意外的話你的屏幕上應該會打印
Greeter client received: Hello niconiconi
到這里 演示就全部結束了。