RPC算是近些年比較火熱的概念了,隨著微服務架構的興起,RPC的應用越來越廣泛,本文介紹了RPC和gRPC的相關概念,并且通過詳細的代碼示例介紹了gRPC的基本使用,
RPC是什么
在分布式計算,遠程程序呼叫(英語:Remote Procedure Call,縮寫為 RPC)是一個計算機通信協議,該協議允許運行于一臺計算機的程式呼叫另一個地址空間(通常為一個開放網路的一臺計算機)的子程式,而程式員就像呼叫本地程式一樣,無需額外地為這個互動作用編程(無需關注細節),RPC是一種服務器-客戶端(Client/Server)模式,經典實作是一個通過發送請求-接受回應進行資訊互動的系統,
gRPC是什么
gRPC是一種現代化開源的高性能RPC框架,能夠運行于任意環境之中,最初由谷歌進行開發,它使用HTTP/2作為傳輸協議,
在gRPC里,客戶端可以像呼叫本地方法一樣直接呼叫其他機器上的服務端應用程式的方法,是你更容易創建分布式應用程式和服務,與許多RPC系統一樣,gRPC是基于定義一個服務,指定一個可以遠程呼叫的帶有引數和回傳型別的的方法,在服務端程式中實作這個介面并且運行gRPC服務處理客戶端呼叫,在客戶端,有一個stub提供和服務端相同的方法,
為什么要用gRPC
使用gRPC, 我們可以一次性的在一個.proto檔案中定義服務并使用任何支持它的語言去實作客戶端和服務端,反過來,它們可以應用在各種場景中,從Google的服務器到你自己的平板電腦—— gRPC幫你解決了不同語言及環境間通信的復雜性,使用protocol buffers還能獲得其他好處,包括高效的序列號,簡單的IDL以及容易進行介面更新,總之一句話,使用gRPC能讓我們更容易撰寫跨語言的分布式代碼,
安裝gRPC
安裝gRPC
go get -u google.golang.org/grpc
安裝Protocol Buffers v3
安裝用于生成gRPC服務代碼的協議編譯器,最簡單的方法是從下面的鏈接:https://github.com/google/protobuf/releases下載適合你平臺的預編譯好的二進制檔案(protoc-<version>-<platform>.zip),
下載完之后,執行下面的步驟:
- 解壓下載好的檔案
- 把
protoc二進制檔案的路徑加到環境變數中
接下來執行下面的命令安裝protoc的Go插件:
go get -u github.com/golang/protobuf/protoc-gen-go
編譯插件protoc-gen-go將會安裝到$GOBIN,默認是$GOPATH/bin,它必須在你的$PATH中以便協議編譯器protoc能夠找到它,
安裝指定
gRPC開發分三步
把大象放進冰箱分幾步?
- 把冰箱門打開,
- 把大象放進去,
- 把冰箱門帶上,
gRPC開發同樣分三步:
- 撰寫
.proto檔案,生成指定語言源代碼, - 撰寫服務端代碼
- 撰寫客戶端代碼
gRPC入門示例
撰寫proto代碼
gRPC是基于Protocol Buffers,
Protocol Buffers是一種與語言無關,平臺無關的可擴展機制,用于序列化結構化資料,使用Protocol Buffers可以一次定義結構化的資料,然后可以使用特殊生成的源代碼輕松地在各種資料流中使用各種語言撰寫和讀取結構化資料,
關于Protocol Buffers的教程可以自行在網上搜索,本文默認讀者熟悉Protocol Buffers,
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代碼
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埠
lis, 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方法在lis上接受傳入連接,為每個連接創建一個ServerTransport和server的goroutine,
// 該goroutine讀取gRPC請求,然后呼叫已注冊的處理程式來回應它們,
err = s.Serve(lis)
if err != nil {
fmt.Printf("failed to serve: %v", err)
return
}
}
將上面的代碼保存到gRPC_demo/helloworld/server/server.go檔案中,編譯并執行:
cd helloworld/server go build ./server
撰寫Client端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: "q1mi"})
if err != nil {
fmt.Printf("could not greet: %v", err)
}
fmt.Printf("Greeting: %s !\n", r.Message)
}
將上面的代碼保存到gRPC_demo/helloworld/client/client.go檔案中,編譯并執行:
cd helloworld/client/ go build ./client
得到輸出如下(注意要先啟動server端再啟動client端):
$ ./client Greeting: Hello q1mi!
此時我們的目錄結構如下:
./gRPC_demo
├── go.mod
├── go.sum
└── helloworld
├── client
│ ├── client
│ └── client.go
│ ├── client.py
├── pb
│ ├── helloworld.pb.go
│ └── helloworld.proto
└── server
├── server
└── server.go
gRPC跨語言呼叫
接下來,我們演示一下如何使用gRPC實作跨語言的RPC呼叫,
我們使用Python語言撰寫Client,然后向上面使用go語言撰寫的server發送RPC請求,
生成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檔案:
helloworld_pb2.py
helloworld_pb2_grpc.py
撰寫Python版Client
在`gRPC_demo/helloworld/client/目錄闖將client.py檔案,其內容如下:
# 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='q1mi'))
print("Greeter client received: {}!".format(response.message))
if __name__ == '__main__':
logging.basicConfig()
run()
將上面的代碼保存執行,得到輸出結果如下:
gRPC_demo $ python helloworld/client/client.py
Greeter client received: Hello q1mi!
這里我們就實作了,使用python代碼撰寫的client去呼叫Go語言版本的server了,
點擊右邊的鏈接查看完整代碼:gRPC_demo完整代碼
gRPC還有更多進階用法,未完待續…
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/45070.html
標籤:Go
上一篇:Go操作MySQL
下一篇:protobuf初識
