gRPC + Python 入門到生產環境

來自專欄 xsren5 人贊了文章

所有的代碼在 https://github.com/xsren/learning_record/tree/master/grpc,歡迎star。

一、先了解幾個概念

RPC

RPC(Remote Procedure Call)—遠程過程調用,它是一種通過網路從遠程計算機程序上請求服務,而不需要了解底層網路技術的協議。

gRPC

gRPC是一個高性能、通用的開源RPC框架,其由Google主要由開發並基於HTTP/2協議標準而設計,基於ProtoBuf(Protocol Buffers)序列化協議開發,且支持眾多開發語言。

  • 基於HTTP/2協議提供了更好的強的應用性能(節省帶寬,減少TCP請求連接數)
  • 基於ProtoBuf定義服務,面向介面對服務進行頂層設計
  • 支持主流的編程語言,C++,Java,Python,Go,Ruby,Node.js,PHP等, 基於ProtoBuf生成相應的服務端和客戶端代碼。
  • 相比在使用Restful方式完成服務之間的相互訪問,GRPC能提供更好的性能,更低的延遲,並且生來適合與分散式系統。
  • 同時基於標準化的IDL(ProtoBuf)來生成伺服器端和客戶端代碼, ProtoBuf服務定義可以作為服務契約,因此可以更好的支持團隊與團隊之間的介面設計,開發,測試,協作等等。

protobuf

protocol buffers(簡稱protobuf)是google 的一種數據交換的格式,它獨立於語言,獨立於平台。

  • protobuf是google開發的一個數據傳輸格式,類似json
  • protobuf是二進位的、結構化的,所以比json的數據量更小,也更對象化
  • protobuf不是像json直接明文的,這個是定義對象結構,然後由protbuf庫去把對象自動轉換成二進位,用的時候再自動反解過來的。傳輸對我們是透明的!我們只管傳輸的對象就可以了

二、再學習protobuf

1、安裝protobuf

1)安裝 Protocol Compiler

參考:Protocol Compiler Installation https://github.com/google/protobuf

有兩種方式,一種是自己編譯,一種是下載然後把protoc放在/usr/bin即可。我選的後者,本地命令如下:

# 下載

github.com/google/proto 下載 protoc-3.5.1-osx-x86_64.zip# 解壓unzip protoc-3.5.1-osx-x86_64.zip -d protoc# 拷貝sudo cp protoc/bin/protoc /usr/bin/# 增加可執行的許可權sudo chmod +x /usr/bin/protoc

# 拷貝 include文件p

cp -rf include/google /usr/local/include

2)安裝 python package

sudo pip3 install protobuf

2、運行protobuf demo

參考:

  • Protocol Buffer Basics: Python https://developers.google.com/protocol-buffers/docs/pythontutorial
  • proto3和proto2的區別 https://superlc320.gitbooks.io/protocol-buffers-3-study-notes/content/proto3he_proto2_de_qu_bie.html

官方的demo實現了一個簡易通訊錄,可以將聯繫人寫入文件,並可以從文件中讀取聯繫人。

python版本3.6.0

protoc版本3.5.1cd protobuf_demo# 編譯生成addressbook_pb2.pyprotoc --python_out=. addressbook.proto# 添加聯繫人python3 add_person.py address.txt

# 讀取聯繫人

python3 list_people.py address.txt

運行結果

三、gRPC學習

1、安裝

參考:https://grpc.io/docs/quickstart/python.html

# Install gRPC

sudo pip3 install grpcio# Install gRPC tools sudo pip3 install grpcio-tools

2、運行

1) hello world

cd grpc_helloworld# 生成 helloworld_pb2.py 和 helloworld_pb2_grpc.pypython3 -m grpc_tools.protoc --proto_path=. --python_out=. --grpc_python_out=. helloworld.proto# 運行serverpython3 greeter_server.py# 運行clientpython3 greeter_client.py

2) route guide

一個和streaming相關的demo,支持:

  • A server-to-client streaming RPC.
  • A client-to-server streaming RPC.
  • A Bidirectional streaming RPC.

streaming 的應用場景主要是傳輸數據量比較多的情況。

cd grpc_helloworld

# 生成 route_guide_pb2.py 和 route_guide_pb2_grpc.pypython3 -m grpc_tools.protoc --proto_path=. --python_out=. --grpc_python_out=. route_guide.proto

# 運行server

python3 route_guide_server.py# 運行clientpython3 route_guide_client.py

四、生產環境

參考:

  • python API doc https://grpc.io/grpc/python/index.html
  • Exploring Security, Metrics, and Error-handling with gRPC in Python https://blog.codeship.com/exploring-security-metrics-and-error-handling-with-grpc-in-python/
  • gRPC Authentication https://grpc.io/docs/guides/auth.html#credential-types

生產環境的要求:

  • 性能
    • 使用多線程提高並發。
    • 使用負載均衡的方式進行擴展。
  • 安全
    • SSL/TLS
    • Token-based authentication with Google
    • 擴展使用其他認證方式
  • 錯誤處理
    • 超時
    • 錯誤
  • 攔截器(python版本的攔截器還不穩定)

cd grpc_product

# 生產私鑰openssl genrsa -out server.key 2048 # 生產公鑰openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650 # 生成 helloworld_pb2.py 和 helloworld_pb2_grpc.pypython3 -m grpc_tools.protoc --proto_path=. --python_out=. --grpc_python_out=. helloworld.proto

# 運行server

python3 greeter_server.py# 運行clientpython3 greeter_client.py

五、讓gRPC支持Restful

參考:

  • gRPC with REST and Open APIs https://grpc.io/blog/coreos
  • grpc-gateway https://github.com/grpc-ecosystem/grpc-gateway
  • gRPC helloworld service, RESTful JSON API gateway and swagger UI http://www.cnblogs.com/lienhua34/p/6285829.html

可以使用使用grpc-gateway生成一個反向代理,將接收的RESTful JSON API 轉化為 gRPC。

grpc_gateway.png

# 生成的python文件用到了google.api,搞了半天,我發現居然是包含在google-cloud-translate裡面的

sudo pip3 install google-cloud-translate# 安裝go依賴的包

go get -u github.com/grpc-ecosyst

go get -u github.com/grpc-ecosystgo get -u github.com/golang/proto# 修改proto文件 # 生成 gRPC golang stub 類sh gen_grpc_stub_go.sh# 需要注釋掉helloworld.pb.go第19行: import _ "github.com/grpc-ecosyst" # 生成 gRPC python stub 類sh gen_grpc_stub_python.sh# 生成網關代碼sh gen_grpc_gw.sh# 生成swagger代碼

sh gen_grpc_gw_swagger.sh

# 運行 serverpython3 server.py# 運行 clientpython3 client.py# 運行網關服務go run proxy.go# 命令行測試curl -X POST -k http://localhost:8080/v1/hello -d {"name": "world"} # 打開swagger測試http://localhost:8080/swagger-ui/

六、TODO:

  • 1、深入研究grpc-gateway的高級選項。

七、疑問解答:

Question1: gRPC client能使用代理嗎?

Answer:

官方的client API並沒有提供設置proxy的選項,可行的幾種方案:

  • 1、通過設置系統的代理$ echo $http_proxyhttp://httpproxy.mydomain:8080
  • 2、通過nginx、haproxy等設置一個反向代理

Question2: protobuf的默認值是?

Answer:以下只針對proto3參考https://developers.google.com/protocol-buffers/docs/proto3

For strings, the default value is the empty string. For bytes, the default value is empty bytes.

For bools, the default value is false.For numeric types, the default value is zero.For enums, the default value is the first defined enum value, which must be 0. For message fields, the field is not set. Its exact value is language-dependent. See the generated code guide for details.

Question3: gRPC如何認證和授權?

  • SSL/TLS
  • Token-based authentication with Google(包含了Oauth2和JWT的方式)
  • 自己擴展,官方提供API可以自行擴展認證方式(找到了go的實現方式)

Question4: gRPC的並發問題?

  • 多線程(不支持多進程)
  • 非同步,有一個熱心網友的實現
  • 負載均衡

推薦閱讀:

相关文章