天天看點

學習gRPC - 2.如何建構一個流和序列化

建構流

gRPC 利用

HTTP/2

的雙向通信特性實作了

連續的消息交換

,實作了

雙向流

資料流是什麼?

流資料有各種各樣的場景用法

。一種是,

當事件發生時,有一種方法可以不斷發出描述事件的消息

。例如,當資料被添加到資料庫中時,資料庫希望将“資料添加”事件通知相關方。或者當股票價格發生變化時,證券交易所希望向訂閱“價格變化”事件的所有服務公布新價格。

另一個是

有一種以異步方式高效傳輸非常大的資料集的方法

。例如,假設您有一個傳回一百萬條記錄的查詢,其中每條記錄對調用者都有值。能夠在每條記錄以流的方式進入時檢查它,比等到所有100萬條記錄都收到後再批量處理它們要有效得多。或者,想象你有一個電視控制台,想要攝入一部電影5分鐘的時間來處理。通過流消費和處理5分鐘的片段意味着消費者可以在電影進入時持續觀看,而不必等到整部電影下載下傳後才能觀看。

環境準備

  • python 3.7
  • pip 最新版, 可以用下面的指令更新
python -m pip install --upgrade pip           

複制

安裝

gRPC

python -m pip install grpcio           

複制

這個還需要安裝一個

gRPC tools

, Python 的 gRPC 工具包括協定緩沖編譯器 protoc 和用于從 .proto服務定義。

python -m pip install grpcio-tools           

複制

為了學習,這個提供要給demo

git clone -b v1.33.1 https://github.com/grpc/grpc

# 國内可以通路這個
git clone [email protected]:chasays/grpc.git           

複制

clone 之前需要安裝 protoc 和 grpc_python_plugin

  • protoc 可以直接用

    brew install protoc

    , 如果是其他的類似,或者下載下傳protoc,然後解壓後放到環境裡面
  • grpc_python_plugin 這個在上面clone的工程裡面,編譯

    make grpc_python_plugin

    然後把編譯好的檔案copy到PATH裡面即可
(base) ➜  grpc git:(master) ✗ make grpc_python_plugin
[HOSTCXX] Compiling src/compiler/cpp_generator.cc
[HOSTCXX] Compiling src/compiler/csharp_generator.cc
[HOSTCXX] Compiling src/compiler/objective_c_generator.cc
[HOSTCXX] Compiling src/compiler/python_generator.cc
[HOSTCXX] Compiling src/compiler/ruby_generator.cc
[AR]      Creating /Users/admin/Documents/OpenSource/grpc/libs/opt/libgrpc_plugin_support.a
[HOSTCXX] Compiling src/compiler/python_plugin.cc
[HOSTLD]  Linking /Users/admin/Documents/OpenSource/grpc/bins/opt/grpc_python_plugin

(base) ➜  sudo cp bins/opt/grpc_python_plugin /usr/local/bin/           

複制

先來看一個最簡單的 helloworld

然後切換目錄到

cd grpc/examples/python/helloworld

執行

run_codegen.sh

,即可生成

helloworld_pb2.py

檔案。

然後依次執行

greeter_server.py

greeter_client.py

。 就可以看到輸出

python greeter_server.py
# 再開一個,shell程序執行
python greeter_client.py

# 需要注意執行client的時候一定要用python2, 用py3需要修改下檔案裡面print這句
(base) ➜  helloworld git:(master) ✗ python2 greeter_client.py
Greeter client received: Hello, you!           

複制

這個裡面有個

stub

,需要提一下, 網上看了下,這個解釋是不錯的。

寫碼的時候你會遇到一些外部依賴,比如在本機上寫代碼,可能會調用谷歌的API,來完成遠端調用。而我在做測試的時候并不想真的發出這個請求,(貴,得不到想要的結果),是以我選擇通過某種方式(Mockito)來進行模拟。Stub指的就是這種模拟,把服務端的依賴用本機來進行模拟

也可以用

Bloomrpc

導入 protoc檔案,然後直接執行。

注意用這個執行之前需要啟動 server

學習gRPC - 2.如何建構一個流和序列化

Streaming

要定義一個服務,你需要在你的. proto 檔案中指定一個命名的服務:

service RouteGuide {
   // (Method definitions not shown)
}           

複制

然後在服務定義中定義 rpc 方法,指定它們的請求和響應類型。讓你定義

四種

服務方法,所有這些都在 RouteGuide 服務中使用:

  1. 一個簡單的 RPC,其中用戶端使用存根向伺服器發送請求,并等待響應傳回,就像

    普通的函數調用一樣

// Obtains the feature at a given position.
rpc GetFeature(Point) returns (Feature) {}           

複制

  1. 一種

    響應流

    RPC,

    其中用戶端向伺服器發送請求,并獲得一個流來讀取一系列消息

    。用戶端從傳回的流中讀取,直到沒有更多的消息。正如您在示例中看到的,您通過将 stream 關鍵字放在 response 類型之前來指定 response-streaming 方法。
// Obtains the Features available within the given Rectangle.  Results are
// streamed rather than returned at once (e.g. in a response message with a
// repeated field), as the rectangle may cover a large area and contain a
// huge number of features.
rpc ListFeatures(Rectangle) returns (stream Feature) {}           

複制

  1. 一種

    請求流式

    RPC,其中客戶機寫入一

    系列消息并将它們發送到伺服器,同樣使用提供的流。一旦用戶端完成了消息的寫入

    ,它就會等待伺服器讀取所有消息并傳回響應。通過将 stream 關鍵字放在請求類型之前,可以指定請求流方法。
// Accepts a stream of Points on a route being traversed, returning a
// RouteSummary when traversal is completed.
rpc RecordRoute(stream Point) returns (RouteSummary) {}           

複制

  1. 一種

    雙向流式

    RPC,其中

    雙方使用讀寫流發送一系列消息。這兩個流獨立運作

    ,是以用戶端和伺服器可以按照自己喜歡的順序讀寫: 例如,伺服器可以等待接收所有用戶端消息後再寫響應,或者可以交替讀取消息然後寫入消息,或者其他讀寫組合。保留了每個流中消息的順序。通過将 stream 關鍵字放在請求和響應之前,可以指定這種類型的方法。
// Accepts a stream of RouteNotes sent while a route is being traversed,
// while receiving other RouteNotes (e.g. from other users).
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}           

複制

然後用 如下指令生成 python代碼。

$ python -m grpc_tools.protoc -I../../protos --python_out=. --grpc_python_out=. ../../protos/route_guide.proto           

複制

建構server和client的代碼略。
https://github.com/grpc/grpc/blob/v1.33.1/examples/python/route_guide/route_guide_server.py
https://github.com/grpc/grpc/blob/v1.33.1/examples/python/route_guide/route_guide_client.py           

複制

啟動server, 然後 push data,就可以在response看到對應的消息。

學習gRPC - 2.如何建構一個流和序列化

用protobuf 實作序列化和反序列化

用python來舉例吧,比如序列化就是request,用

SerializeToString

, 反序列化就用

FromString

request_serializers = {
    ('helloworld.Greeter', 'SayHello'): helloworld_pb2.HelloRequest.SerializeToString,
  }
response_deserializers = {
    ('helloworld.Greeter', 'SayHello'): helloworld_pb2.HelloReply.FromString,
  }           

複制