您好,登錄后才能下訂單哦!
What's gRPC?
gRPC is a modern open source high performance RPC framework that can run in any environment. It can efficiently connect services in and across data centers with pluggable support for load balancing, tracing, health checking and authentication. It is also applicable in last mile of distributed computing to connect devices, mobile applications and browsers to backend services.(gRPC是可以在任何環境中運行的現代的開源高性能RPC框架。它可以通過可插拔的支持來有效地連接數據中心內和跨數據中心的服務,以實現負載平衡,跟蹤,運行狀況檢查和身份驗證。它也適用于分布式計算的最后一英里,以將設備,移動應用程序和瀏覽器連接到后端服務。)
我們可以用一句話來概括:A high-performance, open-source universal RPC framework
RPC(remote procedure call 遠程過程調用)框架實際是提供了一套機制,使得應用程序之間可以進行通信,而且也遵從server/client模型。使用的時候客戶端調用server端提供的接口就像是調用本地的函數一樣。
so
在什么情況下需要使用gRPC呢?
需要對接口進行嚴格約束的情況,比如我們提供了一個公共的服務,很多人,甚至公司外部的人也可以訪問這個服務,這時對于接口我們希望有更加嚴格的約束,我們不希望客戶端給我們傳遞任意的數據,尤其是考慮到安全性的因素,我們通常需要對接口進行更加嚴格的約束。這時gRPC就可以通過protobuf來提供嚴格的接口約束。
對于性能有更高的要求時。有時我們的服務需要傳遞大量的數據,而又希望不影響我們的性能,這個時候也可以考慮gRPC服務,因為通過protobuf我們可以將數據壓縮編碼轉化為二進制格式,通常傳遞的數據量要小得多,而且通過http2我們可以實現異步的請求,從而大大提高了通信效率。
但是,通常我們不會去單獨使用gRPC,而是將gRPC作為一個部件進行使用,這是因為在生產環境,我們面對大并發的情況下,需要使用分布式系統來去處理,而gRPC并沒有提供分布式系統相關的一些必要組件。而且,真正的線上服務還需要提供包括負載均衡,限流熔斷,監控報jing,服務注冊和發現等等必要的組件。
接下來開始gRPC的Hello World測試
gRPC的使用通常包括如下幾個步驟:
1、通過protobuf來定義接口和數據類型
2、編寫gRPC server端代碼
3、編寫gRPC client端代碼
我實在mac中使用的python,mac中自帶python2,因為需要,自己安裝了python3。
首先pip3 安裝grpc和protobuf
(lxc) liuxuchong:untitled liuxuchong$ pip3 install grpcio
Collecting grpcio
Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ReadTimeoutError("HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Read timed out. (read timeout=15)")': /packages/0d/27/0413a5dffd7ddca4ea43cffd22f46ec2b26a5ed18c974e4448763e758a9b/grpcio-1.25.0-cp37-cp37m-macosx_10_9_x86_64.whl
Downloading https://files.pythonhosted.org/packages/0d/27/0413a5dffd7ddca4ea43cffd22f46ec2b26a5ed18c974e4448763e758a9b/grpcio-1.25.0-cp37-cp37m-macosx_10_9_x86_64.whl (2.3MB)
100% |████████████████████████████████| 2.3MB 8.1kB/s
Collecting six>=1.5.2 (from grpcio)
Using cached https://files.pythonhosted.org/packages/65/26/32b8464df2a97e6dd1b656ed26b2c194606c16fe163c695a992b36c11cdf/six-1.13.0-py2.py3-none-any.whl
Installing collected packages: six, grpcio
Successfully installed grpcio-1.25.0 six-1.13.0
(lxc) liuxuchong:untitled liuxuchong$ pip3 install protobuf
Collecting protobuf
Downloading https://files.pythonhosted.org/packages/a5/c6/a8b6a74ab1e165f0aaa673a46f5c895af8780976880c98934ae82060356d/protobuf-3.10.0-cp37-cp37m-macosx_10_9_intel.whl (1.4MB)
100% |████████████████████████████████| 1.4MB 83kB/s
Requirement already satisfied: setuptools in ./venv/lxc/lib/python3.7/site-packages/setuptools-40.8.0-py3.7.egg (from protobuf) (40.8.0)
Requirement already satisfied: six>=1.9 in ./venv/lxc/lib/python3.7/site-packages (from protobuf) (1.13.0)
Installing collected packages: protobuf
Successfully installed protobuf-3.10.0
定義protobuf
下面定義一個簡單的protobuf文件,在其中聲明一個grpc服務。
創建一個proto目錄,并在其中創建grpchello.proto文件,如下內容。
syntax = "proto3";
package grpcDemo;
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
service gRPC {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
編譯protobuf
使用protobuf的編譯器,為我們生成python版本的Message定義和服務的架手腳。
lxc) liuxuchong:untitled liuxuchong$ python -m grpc-tools.protoc -I./proto --python_out=. --grpc_python_out=. grpchello.proto
/Users/liuxuchong/PycharmProjects/untitled/venv/lxc/bin/python: Error while finding module specification for 'grpc-tools.protoc' (ModuleNotFoundError: No module named 'grpc-tools')
提示我們沒有安裝grpc-tools,用pip安裝一下
python3 -m pip install --user grpcio-tools
然后在運行上面的命令
在當前目錄下,生成2個文件:
查看第一個文件,消息定義文件:
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: grpchello.proto
import sys
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor(
name='grpchello.proto',
package='grpcDemo',
syntax='proto3',
serialized_options=None,
serialized_pb=_b('\n\x0fgrpchello.proto\x12\x08grpcDemo\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2B\n\x04gRPC\x12:\n\x08SayHello\x12\x16.grpcDemo.HelloRequest\x1a\x14.grpcDemo.HelloReply\"\x00\x62\x06proto3')
)
_HELLOREQUEST = _descriptor.Descriptor(
name='HelloRequest',
full_name='grpcDemo.HelloRequest',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='name', full_name='grpcDemo.HelloRequest.name', index=0,
number=1, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=29,
serialized_end=57,
)
然后看下grpc服務定義:
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor(
name='grpchello.proto',
package='grpcDemo',
syntax='proto3',
serialized_options=None,
serialized_pb=_b('\n\x0fgrpchello.proto\x12\x08grpcDemo\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2B\n\x04gRPC\x12:\n\x08SayHello\x12\x16.grpcDemo.HelloRequest\x1a\x14.grpcDemo.HelloReply\"\x00\x62\x06proto3')
)
_HELLOREQUEST = _descriptor.Descriptor(
name='HelloRequest',
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor(
name='grpchello.proto',
package='grpcDemo',
syntax='proto3',
serialized_options=None,
serialized_pb=_b('\n\x0fgrpchello.proto\x12\x08grpcDemo\"\x1c\n\x0cHelloRequest\\
x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x011
\x01(\t2B\n\x04gRPC\x12:\n\x08SayHello\x12\x16.grpcDemo.HelloRequest\x1a\x14.grpcc
Demo.HelloReply\"\x00\x62\x06proto3')
)
_HELLOREQUEST = _descriptor.Descriptor(
name='HelloRequest',
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
import grpc
import grpchello_pb2 as grpchello__pb2
class gRPCStub(object):
# missing associated documentation comment in .proto file
pass
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.SayHello = channel.unary_unary(
'/grpcDemo.gRPC/SayHello',
request_serializer=grpchello__pb2.HelloRequest.SerializeToString,
response_deserializer=grpchello__pb2.HelloReply.FromString,
)
class gRPCServicer(object):
# missing associated documentation comment in .proto file
pass
def SayHello(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_gRPCServicer_to_server(servicer, server):
rpc_method_handlers = {
'SayHello': grpc.unary_unary_rpc_method_handler(
servicer.SayHello,
request_deserializer=grpchello__pb2.HelloRequest.FromString,
response_serializer=grpchello__pb2.HelloReply.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'grpcDemo.gRPC', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
這里使用的幾個主要方法(類):
實現服務
在我們的實現服務的類中,使用服務方法,并在網絡中暴露出來。
# -*- coding: utf-8 -*-
import grpc
import time
from concurrent import futures
import grpchello_pb2, grpchello_pb2_grpc
_HOST = 'localhost'
_PORT = '8188'
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
class gRPCServicerImpl(grpchello_pb2_grpc.gRPCServicer):
def SayHello(self, request, context):
print ("called with " + request.name)
return grpchello_pb2.HelloReply(message='Hello, %s!' % request.name)
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
grpchello_pb2_grpc.add_gRPCServicer_to_server(gRPCServicerImpl(), server)
server.add_insecure_port('[::]:'+_PORT)
server.start()
try:
while True:
time.sleep(_ONE_DAY_IN_SECONDS)
except KeyboardInterrupt:
server.stop(0)
if __name__ == '__main__':
serve()
這里包括2個實現:
使用客戶端client
在客戶端,調用grpc的服務API。
# -*- coding: utf-8 -*-
"""The Python implementation of the gRPC client."""
from __future__ import print_function
import grpc
from grpchello_pb2 import * ## or import grpchello_pb2
from grpchello_pb2_grpc import *
## No grpcDemo! from grpcDemo import grpchello_pb2, grpchello_pb2_grpc #error!
_PORT = '8188'
def run():
conn = grpc.insecure_channel(_HOST + ':' + _PORT)
client = gRPCStub(channel=conn)
response = client.SayHello(HelloRequest(name='lxc'))
print("received: " + response.message)
##
if __name__ == '__main__':
if len(sys.argv)== 2:
print (sys.argv[1])
_HOST = sys.argv[1]
else:
_HOST = 'localhost'
#
run()
說明:
測試
分別啟動服務,然后再啟動客戶端,可以看到調用結果。
也可以啟動java、c#版本的grpc服務端、客戶端,都能調用成功。
然后運行
(lxc) liuxuchong:untitled liuxuchong$ python3 grpchello_pb2.py
Traceback (most recent call last):
File "grpchello_pb2.py", line 7, in <module>
from google.protobuf import descriptor as _descriptor
ModuleNotFoundError: No module named 'google'
提示沒有google模版
網上查了一下解決方法如下
pip3 install google
pip3 install protobuf
然后運行另一個py文件
python3 grpchello_pb2_grpc.py
Traceback (most recent call last):
File "grpchello_pb2_grpc.py", line 2, in <module>
import grpc
奇怪,剛才明明裝了,還提示沒有模版,又裝了一次
pip3 install grpcio
Collecting grpcio
Using cached https://files.pythonhosted.org/packages/0d/27/0413a5dffd7ddca4ea43cffd22f46ec2b26a5ed18c974e4448763e758a9b/grpcio-1.25.0-cp37-cp37m-macosx_10_9_x86_64.whl
Requirement already satisfied: six>=1.5.2 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from grpcio) (1.13.0)
Installing collected packages: grpcio
Successfully installed grpcio-1.25.0
果然剛才裝的丟了。。。
然后運行python3 get_service.py
打開一個新的窗口運行
python3 client.py
在原來的窗口可以看到called with lxc
參考資料:
https://www.jianshu.co×××c947d98e192
https://blog.csdn.net/whereismatrix/article/details/78595550
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。