微服務系列(二)GRPC的介紹與安裝
1.GPRC簡介
GRPC是Google公司基於Protobuf開發的跨語言的開源RPC框架。GRPC基於HTTP/2協議設計,可以基於一個HTTP/2連結提供多個服務,對於移動裝置更加友好。目前提供 C、Java 和 Go 語言版本,分別是:grpc, grpc-java, grpc-go. 其中 C 版本支援 C, C++, Node.js, Python, Ruby, Objective-C, PHP 和 C# 支援.
在 gRPC裡客戶端應用可以像呼叫本地物件一樣直接呼叫另一臺不同的機器上服務端應用的方法,使得您能夠更容易地建立分散式應用和服務。與許多 RPC系統類似, gRPC也是基於以下理念:
-
定義一個服務,指定其能夠被遠端呼叫的方法(包含引數和返回型別)。
-
在服務端實現這個介面,並執行一個 gRPC伺服器來處理客戶端呼叫。
在客戶端擁有一個存根能夠像服務端一樣的方法。 gRPC客戶端和服務端可以在多種環境中執行和互動 -從 google內部的伺服器到你自己的筆記本,並且可以用任何 gRPC支援的語言 來編寫。
所以,你可以很容易地用 Java建立一個 gRPC服務端,用 Go、 Python、Ruby來建立客戶端。此外, Google最新 API將有 gRPC版本的介面,使你很容易地將 Google的功能整合到你的應用裡。
參考資料
gRPC 官方文件中文版:http://doc.oschina.net/grpc?t=60133
gRPC官網:https://grpc.io
再詳細瞭解使用GRPC之前先來了解一下上面定義中的一些關鍵詞。
首先我們來看一下HTTP/2是什麼內容?
其實本質上就是http2.0版本,http目前為止主要有四個版本,分別為http1.0、http1.1、http2.0、https。
http1.0是最原始的版本,不支援持久連線,效率也比較低
http1.1針對http1.0版本做了優化,可以連線一次,多次使用,效率比http1.0高
http2.0實現了多路複用,對http1.1再次進行了優化。http2.0也被稱為下一代http協議,是在2013年8月進行首次測試,所以現在用的不是很廣。
https其實是在http協議上多加了一層SSL協議,具體如下圖:
所以本質上,http1.0、http1.1、http2.0都可以新增SSL協議。
2. grpc環境安裝
-
官方推薦安裝方法:
go get -u -v google.golang.org/grpc
但是由於牆原因,不能直接訪問google官網,所以只能曲線救國了
-
通過github下載各種依賴庫,然後配置。
git clone https://github.com/grpc/grpc-go.git $GOPATH/src/google.golang.org/grpc git clone https://github.com/golang/net.git $GOPATH/src/golang.org/x/net git clone https://github.com/golang/text.git $GOPATH/src/golang.org/x/text git clone https://github.com/google/go-genproto.git $GOPATH/src/google.golang.org/genproto cd $GOPATH/src/ go install google.golang.org/grpc
網路暢通可以用上述方法,但如果網速較慢,我們也可以選擇離線安裝方法。
-
用
x.zip
和google.golang.org.zip
兩個離線包來安裝。#將x.zip 解壓到 $GOPATH/src/golang.org/x 目錄下 $ unzip x.zip -d $GOPATH/src/golang.org/x #將google.golang.org.zip 解壓到 $GOPATH/src/google.golang.org 目錄下 $ unzip google.golang.org.zip -d $GOPATH/src/google.golang.org #然後進入到$GOPATH/src/google.golang.org/grpc下面執行go install $ go install
點選此處獲取兩個離線壓縮包
3.GRPC使用
如果從Protobuf的角度看,GRPC只不過是一個針對service介面生成程式碼的生成器。接著我們來學習一下GRPC的用法。這裡我們建立一個簡單的proto檔案,定義一個HelloService介面:
檔名稱為person.proto
syntax = "proto3";
package pb; // 後期生成go的檔案包名
option go_package = "../pb"; // go 1.14後需要指定匯出的路徑
// 訊息體 -- 一個package中,不允許定義同名的訊息體
message Teacher {
int32 age = 1;
string name = 2;
}
// 定義服務
service SayName {
rpc SayHello(Teacher) returns (Teacher);
}
對proto檔案進行編譯:
protoc --go_out=plugins=grpc:./ person.proto
編譯後生成person.pb.go
檔案
GRPC外掛會為服務端和客戶端生成不同的介面:
//客戶端介面
type SayNameClient interface {
SayHello(ctx context.Context, in *Teacher, opts ...grpc.CallOption) (*Teacher, error)
}
//伺服器介面
type SayNameServer interface {
SayHello(context.Context, *Teacher) (*Teacher, error)
}
我們接著可以基於他們給的服務端介面重新實現SayHello服務:
// 定義一個結構體 不一定非得是Teacher
type Children struct {
}
// 介面去繫結類方法
func (c *Children) SayHello(ctx context.Context,t *pb.Teacher) (*pb.Teacher, error) {
t.Name += "is teaching"
return t,nil
}
GRPC的啟動流程和RPC的啟動流程類似,程式碼如下:
func main(){
// 1. 初始一個grpc物件
grpcServer := grpc.NewServer()
// 2.註冊服務
pb.RegisterSayNameServer(grpcServer,new(Children))
// 3.設定監聽並建立連線,指定IP port
listener ,err := net.Listen("tcp","127.0.0.1:8080")
if err!=nil{
fmt.Printf("監聽失敗:%v",err)
return
}
defer listener.Close()
fmt.Println("正在監聽127.0.0.1:8080 ...")
// 4.啟動服務 ... Serve()
grpcServer.Serve(listener)
}
然後我們就可以通過客戶端來連線GRPC服務了:
func main(){
// 1.連線grpc服務
grpcConn,err := grpc.Dial("127.0.0.1:8080",grpc.WithInsecure()) // 第二個引數以一個安全的形式進行編譯
if err!=nil{
fmt.Printf("連線撥號失敗:%v",err)
return
}
defer grpcConn.Close()
// 2.初始化grpc客戶端
grpcClient := pb.NewSayNameClient(grpcConn) // 傳入Dail函式的返回值
// 建立並初始化Teacher物件
var teacher pb.Teacher
teacher.Name = "小寶"
teacher.Age = 24
// 3.呼叫遠端服務
t,err := grpcClient.SayHello(context.TODO(),&teacher) /*context.TODO()表示空物件,可以簡單理解我們不清楚要使用哪個上下文、或者還沒有可用的上下文時的佔位符*/
if err!=nil{
fmt.Printf("呼叫遠端服務失敗:%v",err)
return
}
fmt.Println(t)
}