中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

gRPC HelloWorld測試

發布時間:2020-06-23 20:48:04 來源:網絡 閱讀:209637 作者:九月朦朧 欄目:編程語言

一、概述

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端代碼

1、通過protobuf來定義接口和數據類型

我實在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個文件:

  • grpchello_pb2.py
  • grpchello_pb2_grpc.py

查看第一個文件,消息定義文件:

# -*- 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,))
  • 在grpc服務架手腳定義中,定義了gRPCStub,這是給client端使用,調用grpc服務的。
  • 定義的服務類gRPCServicer,方法SayHello需要我們在子類中進行實現。定義的add_gRPCServicer_to_server方法,用于把實現的類和grpc API調用注冊起來。

這里使用的幾個主要方法(類):

  • grpc.server – Creates a Server with which RPCs can be serviced
  • grpc.method_handlers_generic_handler – Creates a GenericRpcHandler from RpcMethodHandlers.
  • grpc.unary_unary_rpc_method_handler – Creates an RpcMethodHandler for a unary-unary RPC method.

實現服務

在我們的實現服務的類中,使用服務方法,并在網絡中暴露出來。

# -*- 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個實現:

  • 1、在grpc的API的實現(服務實現類)gRPCServicerImpl中,實現SayHello方法。
  • 2、然后,定義網絡服務和端口,把grpc的API注冊到網絡服務的處理上。這里簡單利用了grpc.server類。

使用客戶端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()

說明:

  • 1、 def insecure_channel(target, options=None):
    – Creates an insecure Channel to a server.
  • 2、 客戶端使用服務的Stub,調用API。

測試

分別啟動服務,然后再啟動客戶端,可以看到調用結果。
也可以啟動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

gRPC HelloWorld測試
打開一個新的窗口運行
python3 client.py
gRPC HelloWorld測試

在原來的窗口可以看到called with lxc
gRPC HelloWorld測試

參考資料:
https://www.jianshu.co×××c947d98e192
https://blog.csdn.net/whereismatrix/article/details/78595550

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

衡东县| 青海省| 军事| 靖宇县| 镇远县| 元朗区| 淄博市| 岳池县| 吉水县| 广东省| 静海县| 桃源县| 论坛| 太仓市| 施甸县| 乌拉特后旗| 龙江县| 南木林县| 阜宁县| 全南县| 鄢陵县| 昌宁县| 金沙县| 祥云县| 兴业县| 博乐市| 霍林郭勒市| 浠水县| 扎囊县| 恩平市| 丹巴县| 南丰县| 华容县| 信宜市| 无棣县| 吉木萨尔县| 六枝特区| 连平县| 盘锦市| 乐都县| 宿迁市|