gRPC 簡介:
gRPC 是一款高性能、開源的 RPC 框架,產(chǎn)自 Google,基于 ProtoBuf 序列化協(xié)議進(jìn)行開發(fā),支持多種語言(Golang、Python、Java等),本篇只介紹 Golang 的 gRPC 使用。因?yàn)?gRPC 對(duì) HTTP/2 協(xié)議的支持使其在 Android、IOS 等客戶端后端服務(wù)的開發(fā)領(lǐng)域具有良好的前景。gRPC 提供了一種簡單的方法來定義服務(wù),同時(shí)客戶端可以充分利用 HTTP/2 stream 的特性,從而有助于節(jié)省帶寬、降低 TCP 的連接次數(shù)、節(jié)省CPU的使用等。
安裝:
- gRPC 的安裝:
$ go get -u google.golang.org/grpc
- 因?yàn)?gRPC 是基于 protobuf 實(shí)現(xiàn)的接口序列化,所以也要安裝 protobuf: 安裝及簡介教程。
實(shí)踐:
下面我們使用 gRPC 定義一個(gè)接口,該接口實(shí)現(xiàn)對(duì)傳入的數(shù)據(jù)進(jìn)行大寫的格式化處理。
-
創(chuàng)建項(xiàng)目 golang Demo 工程:
Paste_Image.png
- client目錄下的 main.go 實(shí)現(xiàn)了客戶端用于發(fā)送數(shù)據(jù)并打印接收到 server 端處理后的數(shù)據(jù)
server 目錄下的 main.go 實(shí)現(xiàn)了服務(wù)端用于接收客戶端發(fā)送的數(shù)據(jù),并對(duì)數(shù)據(jù)進(jìn)行大寫處理后返回給客戶端
example 包用于編寫 proto 文件并生成 data 接口
定義 gRPC 接口:
syntax = "proto3";
package example;
service FormatData {
rpc DoFormat(Data) returns (Data){}
}
message Data {
string text = 1;
}
- 編譯 protobuf:
$ protoc -I=. --go_out=plugins=grpc:. . // 在 example 目錄中執(zhí)行編譯,會(huì)生成:data.pb.go
- 實(shí)現(xiàn) server 端:
package main
import (
"Demo/example"
"net"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
"golang.org/x/net/context"
"strings"
"log"
)
// 定義監(jiān)聽地址
const (
HOST string = "localhost"
PORT string = "8080"
)
// 定義接口
type FormatData struct{}
func (fd *FormatData) DoFormat(ctx context.Context, in *example.Data) (out *example.Data, err error) {
str := in.Text
out = &example.Data{Text: strings.ToUpper(str)}
return out, nil
}
// 直接在 main 方法中注冊(cè)接口
func main() {
listener, err := net.Listen("tcp", HOST+":"+PORT)
if err != nil {
log.Fatalln("faile listen at: " + HOST + ":" + PORT)
} else {
log.Println("Demo server is listening at: " + HOST + ":" + PORT)
}
rpcServer := grpc.NewServer()
example.RegisterFormatDataServer(rpcServer, &FormatData{})
reflection.Register(rpcServer)
if err = rpcServer.Serve(listener); err != nil {
log.Fatalln("faile serve at: " + HOST + ":" + PORT)
}
}
- 實(shí)現(xiàn) client 端:
package main
import (
"google.golang.org/grpc"
"log"
"Demo/example"
"golang.org/x/net/context"
)
// 定義請(qǐng)求地址
const (
ADDRESS string = "localhost:8080"
)
// main 方法實(shí)現(xiàn)對(duì) gRPC 接口的請(qǐng)求
func main() {
conn, err := grpc.Dial(ADDRESS, grpc.WithInsecure())
if err != nil {
log.Fatalln("Can't connect: " + ADDRESS)
}
defer conn.Close()
client := example.NewFormatDataClient(conn)
resp,err := client.DoFormat(context.Background(), &example.Data{Text:"hello,world!"})
if err != nil {
log.Fatalln("Do Format error:" + err.Error())
}
log.Println(resp.Text)
}
- 執(zhí)行驗(yàn)證結(jié)果:
- 先啟動(dòng) server,之后再執(zhí)行 client
- client 側(cè)控制臺(tái)如果打印的結(jié)果為: HELLO,WORLD! ,證明 gRPC 接口定義成功