Add examples for timeout, kepp_alive, reflection and health_checking (#32243)
* Add timeout example * Add pb2 file to example * Remove .proto file * Add keep_alive example * Add refelction client * fixes * Add example for health_check * Changes based on comments * Fix pylint
This commit is contained in:
parent
1f960697c5
commit
a190831789
|
|
@ -20,6 +20,18 @@ ARTIFACTS += helloworld/helloworld_pb2.py
|
|||
ARTIFACTS += helloworld/helloworld_pb2_grpc.py
|
||||
ARTIFACTS += helloworld/helloworld_pb2.pyi
|
||||
|
||||
ARTIFACTS += timeout/helloworld_pb2.py
|
||||
ARTIFACTS += timeout/helloworld_pb2_grpc.py
|
||||
ARTIFACTS += timeout/helloworld_pb2.pyi
|
||||
|
||||
ARTIFACTS += keep_alive/helloworld_pb2.py
|
||||
ARTIFACTS += keep_alive/helloworld_pb2_grpc.py
|
||||
ARTIFACTS += keep_alive/helloworld_pb2.pyi
|
||||
|
||||
ARTIFACTS += health_checking/helloworld_pb2.py
|
||||
ARTIFACTS += health_checking/helloworld_pb2_grpc.py
|
||||
ARTIFACTS += health_checking/helloworld_pb2.pyi
|
||||
|
||||
ARTIFACTS += async_streaming/phone_pb2.py
|
||||
ARTIFACTS += async_streaming/phone_pb2_grpc.py
|
||||
ARTIFACTS += async_streaming/phone_pb2.pyi
|
||||
|
|
@ -74,6 +86,15 @@ all: ${ARTIFACTS}
|
|||
helloworld/helloworld_pb2.py helloworld/helloworld_pb2_grpc.py helloworld/helloworld_pb2.pyi: ../protos/helloworld.proto
|
||||
python3 -m grpc_tools.protoc --python_out=helloworld --grpc_python_out=helloworld --pyi_out=helloworld -I ../protos ../protos/helloworld.proto
|
||||
|
||||
timeout/helloworld_pb2.py timeout/helloworld_pb2_grpc.py timeout/helloworld_pb2.pyi: ../protos/helloworld.proto
|
||||
python3 -m grpc_tools.protoc --python_out=timeout --grpc_python_out=timeout --pyi_out=timeout -I ../protos ../protos/helloworld.proto
|
||||
|
||||
keep_alive/helloworld_pb2.py keep_alive/helloworld_pb2_grpc.py keep_alive/helloworld_pb2.pyi: ../protos/helloworld.proto
|
||||
python3 -m grpc_tools.protoc --python_out=keep_alive --grpc_python_out=keep_alive --pyi_out=keep_alive -I ../protos ../protos/helloworld.proto
|
||||
|
||||
health_checking/helloworld_pb2.py health_checking/helloworld_pb2_grpc.py health_checking/helloworld_pb2.pyi: ../protos/helloworld.proto
|
||||
python3 -m grpc_tools.protoc --python_out=health_checking --grpc_python_out=health_checking --pyi_out=health_checking -I ../protos ../protos/helloworld.proto
|
||||
|
||||
async_streaming/phone_pb2.py async_streaming/phone_pb2_grpc.py async_streaming/phone_pb2.pyi: async_streaming/phone.proto
|
||||
python3 -m grpc_tools.protoc --python_out=async_streaming --grpc_python_out=async_streaming --pyi_out=async_streaming -I async_streaming async_streaming/phone.proto
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
# Copyright 2023 gRPC authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""gRPC Python helloworld.Greeter client with health checking."""
|
||||
|
||||
import logging
|
||||
from time import sleep
|
||||
|
||||
import grpc
|
||||
from grpc_health.v1 import health_pb2
|
||||
from grpc_health.v1 import health_pb2_grpc
|
||||
import helloworld_pb2
|
||||
import helloworld_pb2_grpc
|
||||
|
||||
|
||||
def unary_call(stub: helloworld_pb2_grpc.GreeterStub, message: str):
|
||||
response = stub.SayHello(helloworld_pb2.HelloRequest(name=message),
|
||||
timeout=3)
|
||||
print(f"Greeter client received: {response.message}")
|
||||
|
||||
|
||||
def health_check_call(stub: health_pb2_grpc.HealthStub):
|
||||
request = health_pb2.HealthCheckRequest(service="helloworld.Greeter")
|
||||
resp = stub.Check(request)
|
||||
if resp.status == health_pb2.HealthCheckResponse.SERVING:
|
||||
print("server is serving")
|
||||
elif resp.status == health_pb2.HealthCheckResponse.NOT_SERVING:
|
||||
print("server stopped serving")
|
||||
|
||||
|
||||
def run():
|
||||
with grpc.insecure_channel('localhost:50051') as channel:
|
||||
stub = helloworld_pb2_grpc.GreeterStub(channel)
|
||||
health_stub = health_pb2_grpc.HealthStub(channel)
|
||||
# Should succeed
|
||||
unary_call(stub, 'you')
|
||||
|
||||
# Check health status every 1 second for 30 seconds
|
||||
for _ in range(30):
|
||||
health_check_call(health_stub)
|
||||
sleep(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig()
|
||||
run()
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
# Copyright 2023 gRPC authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""The Python implementation of the GRPC helloworld.Greeter server with health checking."""
|
||||
|
||||
from concurrent import futures
|
||||
import logging
|
||||
import threading
|
||||
from time import sleep
|
||||
|
||||
import grpc
|
||||
from grpc_health.v1 import health
|
||||
from grpc_health.v1 import health_pb2
|
||||
from grpc_health.v1 import health_pb2_grpc
|
||||
import helloworld_pb2
|
||||
import helloworld_pb2_grpc
|
||||
|
||||
|
||||
class Greeter(helloworld_pb2_grpc.GreeterServicer):
|
||||
|
||||
def SayHello(self, request, context):
|
||||
return helloworld_pb2.HelloReply(message=request.name)
|
||||
|
||||
|
||||
def _toggle_health(health_servicer: health.HealthServicer, service: str):
|
||||
next_status = health_pb2.HealthCheckResponse.SERVING
|
||||
while True:
|
||||
if next_status == health_pb2.HealthCheckResponse.SERVING:
|
||||
next_status = health_pb2.HealthCheckResponse.NOT_SERVING
|
||||
else:
|
||||
next_status = health_pb2.HealthCheckResponse.SERVING
|
||||
|
||||
health_servicer.set(service, next_status)
|
||||
sleep(5)
|
||||
|
||||
|
||||
def _configure_health_server(server: grpc.Server):
|
||||
health_servicer = health.HealthServicer(
|
||||
experimental_non_blocking=True,
|
||||
experimental_thread_pool=futures.ThreadPoolExecutor(max_workers=10))
|
||||
health_pb2_grpc.add_HealthServicer_to_server(health_servicer, server)
|
||||
|
||||
# Use a daemon thread to toggle health status
|
||||
toggle_health_status_thread = threading.Thread(target=_toggle_health,
|
||||
args=(health_servicer,
|
||||
"helloworld.Greeter"),
|
||||
daemon=True)
|
||||
toggle_health_status_thread.start()
|
||||
|
||||
|
||||
def serve():
|
||||
port = '50051'
|
||||
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
|
||||
helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
|
||||
server.add_insecure_port('[::]:' + port)
|
||||
_configure_health_server(server)
|
||||
server.start()
|
||||
print("Server started, listening on " + port)
|
||||
server.wait_for_termination()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig()
|
||||
serve()
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: helloworld.proto
|
||||
"""Generated protocol buffer code."""
|
||||
from google.protobuf.internal import builder as _builder
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import descriptor_pool as _descriptor_pool
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x36\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\xa2\x02\x03HLWb\x06proto3')
|
||||
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
|
||||
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'helloworld_pb2', globals())
|
||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||
|
||||
DESCRIPTOR._options = None
|
||||
DESCRIPTOR._serialized_options = b'\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW'
|
||||
_HELLOREQUEST._serialized_start=32
|
||||
_HELLOREQUEST._serialized_end=60
|
||||
_HELLOREPLY._serialized_start=62
|
||||
_HELLOREPLY._serialized_end=91
|
||||
_GREETER._serialized_start=93
|
||||
_GREETER._serialized_end=166
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import message as _message
|
||||
from typing import ClassVar as _ClassVar, Optional as _Optional
|
||||
|
||||
DESCRIPTOR: _descriptor.FileDescriptor
|
||||
|
||||
class HelloReply(_message.Message):
|
||||
__slots__ = ["message"]
|
||||
MESSAGE_FIELD_NUMBER: _ClassVar[int]
|
||||
message: str
|
||||
def __init__(self, message: _Optional[str] = ...) -> None: ...
|
||||
|
||||
class HelloRequest(_message.Message):
|
||||
__slots__ = ["name"]
|
||||
NAME_FIELD_NUMBER: _ClassVar[int]
|
||||
name: str
|
||||
def __init__(self, name: _Optional[str] = ...) -> None: ...
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
||||
"""Client and server classes corresponding to protobuf-defined services."""
|
||||
import grpc
|
||||
|
||||
import helloworld_pb2 as helloworld__pb2
|
||||
|
||||
|
||||
class GreeterStub(object):
|
||||
"""The greeting service definition.
|
||||
"""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.SayHello = channel.unary_unary(
|
||||
'/helloworld.Greeter/SayHello',
|
||||
request_serializer=helloworld__pb2.HelloRequest.SerializeToString,
|
||||
response_deserializer=helloworld__pb2.HelloReply.FromString,
|
||||
)
|
||||
|
||||
|
||||
class GreeterServicer(object):
|
||||
"""The greeting service definition.
|
||||
"""
|
||||
|
||||
def SayHello(self, request, context):
|
||||
"""Sends a greeting
|
||||
"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
|
||||
def add_GreeterServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
'SayHello': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.SayHello,
|
||||
request_deserializer=helloworld__pb2.HelloRequest.FromString,
|
||||
response_serializer=helloworld__pb2.HelloReply.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'helloworld.Greeter', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
class Greeter(object):
|
||||
"""The greeting service definition.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def SayHello(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/helloworld.Greeter/SayHello',
|
||||
helloworld__pb2.HelloRequest.SerializeToString,
|
||||
helloworld__pb2.HelloReply.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
# Copyright 2023 gRPC authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""The Python implementation of the GRPC helloworld.Greeter client with reflection."""
|
||||
|
||||
import logging
|
||||
|
||||
from google.protobuf.descriptor_pool import DescriptorPool
|
||||
import grpc
|
||||
from grpc_reflection.v1alpha.proto_reflection_descriptor_database import \
|
||||
ProtoReflectionDescriptorDatabase
|
||||
|
||||
|
||||
def run():
|
||||
print("Will try to greet world ...")
|
||||
with grpc.insecure_channel('localhost:50051') as channel:
|
||||
reflection_db = ProtoReflectionDescriptorDatabase(channel)
|
||||
services = reflection_db.get_services()
|
||||
print(f"found services: {services}")
|
||||
|
||||
desc_pool = DescriptorPool(reflection_db)
|
||||
service_desc = desc_pool.FindServiceByName("helloworld.Greeter")
|
||||
print(f"found Greeter service with name: {service_desc.full_name}")
|
||||
for methods in service_desc.methods:
|
||||
print(f"found method name: {methods.full_name}")
|
||||
input_type = methods.input_type
|
||||
print(f"input type for this method: {input_type.full_name}")
|
||||
|
||||
request_desc = desc_pool.FindMessageTypeByName(
|
||||
"helloworld.HelloRequest")
|
||||
print(f"found request name: {request_desc.full_name}")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig()
|
||||
run()
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
# Copyright 2023 gRPC authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""gRPC Python helloworld.Greeter client with keepAlive channel options."""
|
||||
|
||||
import logging
|
||||
from time import sleep
|
||||
|
||||
import grpc
|
||||
import helloworld_pb2
|
||||
import helloworld_pb2_grpc
|
||||
|
||||
|
||||
def unary_call(stub: helloworld_pb2_grpc.GreeterStub, request_id: int,
|
||||
message: str):
|
||||
print("call:", request_id)
|
||||
try:
|
||||
response = stub.SayHello(helloworld_pb2.HelloRequest(name=message))
|
||||
print(f"Greeter client received: {response.message}")
|
||||
except grpc.RpcError as rpc_error:
|
||||
print('Call failed with code: ', rpc_error.code())
|
||||
|
||||
|
||||
def run():
|
||||
"""
|
||||
grpc.keepalive_time_ms: The period (in milliseconds) after which a keepalive ping is
|
||||
sent on the transport.
|
||||
grpc.keepalive_timeout_ms: The amount of time (in milliseconds) the sender of the keepalive
|
||||
ping waits for an acknowledgement. If it does not receive an acknowledgment within this
|
||||
time, it will close the connection.
|
||||
grpc.keepalive_permit_without_calls: If set to 1 (0 : false; 1 : true), allows keepalive
|
||||
pings to be sent even if there are no calls in flight.
|
||||
grpc.http2.max_pings_without_data: How many pings can the client send before needing to
|
||||
send a data/header frame.
|
||||
For more details, check: https://github.com/grpc/grpc/blob/master/doc/keepalive.md
|
||||
"""
|
||||
channel_options = [('grpc.keepalive_time_ms', 8000),
|
||||
('grpc.keepalive_timeout_ms', 5000),
|
||||
('grpc.http2.max_pings_without_data', 5),
|
||||
('grpc.keepalive_permit_without_calls', 1)]
|
||||
|
||||
with grpc.insecure_channel(target='localhost:50051',
|
||||
options=channel_options) as channel:
|
||||
stub = helloworld_pb2_grpc.GreeterStub(channel)
|
||||
# Should succeed
|
||||
unary_call(stub, 1, 'you')
|
||||
|
||||
# Run 30s, run this with GRPC_VERBOSITY=DEBUG GRPC_TRACE=http_keepalive to observe logs.
|
||||
# Client will be closed after receveing GOAWAY from server.
|
||||
for i in range(30):
|
||||
print(f"{i} seconds paased.")
|
||||
sleep(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig()
|
||||
run()
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
# Copyright 2023 gRPC authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""The Python implementation of the GRPC helloworld.Greeter server with keepAlive options."""
|
||||
|
||||
from concurrent import futures
|
||||
import logging
|
||||
from time import sleep
|
||||
|
||||
import grpc
|
||||
import helloworld_pb2
|
||||
import helloworld_pb2_grpc
|
||||
|
||||
|
||||
class Greeter(helloworld_pb2_grpc.GreeterServicer):
|
||||
|
||||
def SayHello(self, request, context):
|
||||
message = request.name
|
||||
if message.startswith("[delay]"):
|
||||
sleep(5)
|
||||
return helloworld_pb2.HelloReply(message=message)
|
||||
|
||||
|
||||
def serve():
|
||||
"""
|
||||
grpc.keepalive_time_ms: The period (in milliseconds) after which a keepalive ping is
|
||||
sent on the transport.
|
||||
grpc.keepalive_timeout_ms: The amount of time (in milliseconds) the sender of the keepalive
|
||||
ping waits for an acknowledgement. If it does not receive an acknowledgment within
|
||||
this time, it will close the connection.
|
||||
grpc.http2.min_ping_interval_without_data_ms: Minimum allowed time (in milliseconds)
|
||||
between a server receiving successive ping frames without sending any data/header frame.
|
||||
grpc.max_connection_idle_ms: Maximum time (in milliseconds) that a channel may have no
|
||||
outstanding rpcs, after which the server will close the connection.
|
||||
grpc.max_connection_age_ms: Maximum time (in milliseconds) that a channel may exist.
|
||||
grpc.max_connection_age_grace_ms: Grace period (in milliseconds) after the channel
|
||||
reaches its max age.
|
||||
grpc.http2.max_pings_without_data: How many pings can the client send before needing to
|
||||
send a data/header frame.
|
||||
grpc.keepalive_permit_without_calls: If set to 1 (0 : false; 1 : true), allows keepalive
|
||||
pings to be sent even if there are no calls in flight.
|
||||
For more details, check: https://github.com/grpc/grpc/blob/master/doc/keepalive.md
|
||||
"""
|
||||
server_options = [('grpc.keepalive_time_ms', 20000),
|
||||
('grpc.keepalive_timeout_ms', 10000),
|
||||
('grpc.http2.min_ping_interval_without_data_ms', 5000),
|
||||
('grpc.max_connection_idle_ms', 10000),
|
||||
('grpc.max_connection_age_ms', 30000),
|
||||
('grpc.max_connection_age_grace_ms', 5000),
|
||||
('grpc.http2.max_pings_without_data', 5),
|
||||
('grpc.keepalive_permit_without_calls', 1)]
|
||||
port = '50051'
|
||||
server = grpc.server(thread_pool=futures.ThreadPoolExecutor(max_workers=10),
|
||||
options=server_options)
|
||||
helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
|
||||
server.add_insecure_port('[::]:' + port)
|
||||
server.start()
|
||||
print("Server started, listening on " + port)
|
||||
server.wait_for_termination()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig()
|
||||
serve()
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: helloworld.proto
|
||||
"""Generated protocol buffer code."""
|
||||
from google.protobuf.internal import builder as _builder
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import descriptor_pool as _descriptor_pool
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x36\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\xa2\x02\x03HLWb\x06proto3')
|
||||
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
|
||||
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'helloworld_pb2', globals())
|
||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||
|
||||
DESCRIPTOR._options = None
|
||||
DESCRIPTOR._serialized_options = b'\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW'
|
||||
_HELLOREQUEST._serialized_start=32
|
||||
_HELLOREQUEST._serialized_end=60
|
||||
_HELLOREPLY._serialized_start=62
|
||||
_HELLOREPLY._serialized_end=91
|
||||
_GREETER._serialized_start=93
|
||||
_GREETER._serialized_end=166
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import message as _message
|
||||
from typing import ClassVar as _ClassVar, Optional as _Optional
|
||||
|
||||
DESCRIPTOR: _descriptor.FileDescriptor
|
||||
|
||||
class HelloReply(_message.Message):
|
||||
__slots__ = ["message"]
|
||||
MESSAGE_FIELD_NUMBER: _ClassVar[int]
|
||||
message: str
|
||||
def __init__(self, message: _Optional[str] = ...) -> None: ...
|
||||
|
||||
class HelloRequest(_message.Message):
|
||||
__slots__ = ["name"]
|
||||
NAME_FIELD_NUMBER: _ClassVar[int]
|
||||
name: str
|
||||
def __init__(self, name: _Optional[str] = ...) -> None: ...
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
||||
"""Client and server classes corresponding to protobuf-defined services."""
|
||||
import grpc
|
||||
|
||||
import helloworld_pb2 as helloworld__pb2
|
||||
|
||||
|
||||
class GreeterStub(object):
|
||||
"""The greeting service definition.
|
||||
"""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.SayHello = channel.unary_unary(
|
||||
'/helloworld.Greeter/SayHello',
|
||||
request_serializer=helloworld__pb2.HelloRequest.SerializeToString,
|
||||
response_deserializer=helloworld__pb2.HelloReply.FromString,
|
||||
)
|
||||
|
||||
|
||||
class GreeterServicer(object):
|
||||
"""The greeting service definition.
|
||||
"""
|
||||
|
||||
def SayHello(self, request, context):
|
||||
"""Sends a greeting
|
||||
"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
|
||||
def add_GreeterServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
'SayHello': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.SayHello,
|
||||
request_deserializer=helloworld__pb2.HelloRequest.FromString,
|
||||
response_serializer=helloworld__pb2.HelloReply.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'helloworld.Greeter', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
class Greeter(object):
|
||||
"""The greeting service definition.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def SayHello(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/helloworld.Greeter/SayHello',
|
||||
helloworld__pb2.HelloRequest.SerializeToString,
|
||||
helloworld__pb2.HelloReply.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
# Copyright 2023 gRPC authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""gRPC Python helloworld.Greeter client with call timeout parameters."""
|
||||
|
||||
import logging
|
||||
|
||||
import grpc
|
||||
import helloworld_pb2
|
||||
import helloworld_pb2_grpc
|
||||
|
||||
|
||||
def unary_call(stub: helloworld_pb2_grpc.GreeterStub, request_id: int,
|
||||
message: str):
|
||||
print("call:", request_id)
|
||||
try:
|
||||
response = stub.SayHello(helloworld_pb2.HelloRequest(name=message),
|
||||
timeout=3)
|
||||
print(f"Greeter client received: {response.message}")
|
||||
except grpc.RpcError as rpc_error:
|
||||
print(f"Call failed with code: {rpc_error.code()}")
|
||||
|
||||
|
||||
def run():
|
||||
with grpc.insecure_channel('localhost:50051') as channel:
|
||||
stub = helloworld_pb2_grpc.GreeterStub(channel)
|
||||
# Should success
|
||||
unary_call(stub, 1, 'you')
|
||||
# Should fail with DEADLINE_EXCEEDED
|
||||
unary_call(stub, 2, '[delay] you')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig()
|
||||
run()
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
# Copyright 2023 gRPC authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""The Python implementation of the GRPC helloworld.Greeter server."""
|
||||
|
||||
from concurrent import futures
|
||||
import logging
|
||||
from time import sleep
|
||||
|
||||
import grpc
|
||||
import helloworld_pb2
|
||||
import helloworld_pb2_grpc
|
||||
|
||||
|
||||
class Greeter(helloworld_pb2_grpc.GreeterServicer):
|
||||
|
||||
def SayHello(self, request, context):
|
||||
message = request.name
|
||||
if message.startswith("[delay]"):
|
||||
sleep(5)
|
||||
return helloworld_pb2.HelloReply(message=message)
|
||||
|
||||
|
||||
def serve():
|
||||
port = '50051'
|
||||
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
|
||||
helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
|
||||
server.add_insecure_port('[::]:' + port)
|
||||
server.start()
|
||||
print("Server started, listening on " + port)
|
||||
server.wait_for_termination()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig()
|
||||
serve()
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: helloworld.proto
|
||||
"""Generated protocol buffer code."""
|
||||
from google.protobuf.internal import builder as _builder
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import descriptor_pool as _descriptor_pool
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x36\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\xa2\x02\x03HLWb\x06proto3')
|
||||
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
|
||||
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'helloworld_pb2', globals())
|
||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||
|
||||
DESCRIPTOR._options = None
|
||||
DESCRIPTOR._serialized_options = b'\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW'
|
||||
_HELLOREQUEST._serialized_start=32
|
||||
_HELLOREQUEST._serialized_end=60
|
||||
_HELLOREPLY._serialized_start=62
|
||||
_HELLOREPLY._serialized_end=91
|
||||
_GREETER._serialized_start=93
|
||||
_GREETER._serialized_end=166
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import message as _message
|
||||
from typing import ClassVar as _ClassVar, Optional as _Optional
|
||||
|
||||
DESCRIPTOR: _descriptor.FileDescriptor
|
||||
|
||||
class HelloReply(_message.Message):
|
||||
__slots__ = ["message"]
|
||||
MESSAGE_FIELD_NUMBER: _ClassVar[int]
|
||||
message: str
|
||||
def __init__(self, message: _Optional[str] = ...) -> None: ...
|
||||
|
||||
class HelloRequest(_message.Message):
|
||||
__slots__ = ["name"]
|
||||
NAME_FIELD_NUMBER: _ClassVar[int]
|
||||
name: str
|
||||
def __init__(self, name: _Optional[str] = ...) -> None: ...
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
||||
"""Client and server classes corresponding to protobuf-defined services."""
|
||||
import grpc
|
||||
|
||||
import helloworld_pb2 as helloworld__pb2
|
||||
|
||||
|
||||
class GreeterStub(object):
|
||||
"""The greeting service definition.
|
||||
"""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.SayHello = channel.unary_unary(
|
||||
'/helloworld.Greeter/SayHello',
|
||||
request_serializer=helloworld__pb2.HelloRequest.SerializeToString,
|
||||
response_deserializer=helloworld__pb2.HelloReply.FromString,
|
||||
)
|
||||
|
||||
|
||||
class GreeterServicer(object):
|
||||
"""The greeting service definition.
|
||||
"""
|
||||
|
||||
def SayHello(self, request, context):
|
||||
"""Sends a greeting
|
||||
"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
|
||||
def add_GreeterServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
'SayHello': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.SayHello,
|
||||
request_deserializer=helloworld__pb2.HelloRequest.FromString,
|
||||
response_serializer=helloworld__pb2.HelloReply.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'helloworld.Greeter', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
class Greeter(object):
|
||||
"""The greeting service definition.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def SayHello(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/helloworld.Greeter/SayHello',
|
||||
helloworld__pb2.HelloRequest.SerializeToString,
|
||||
helloworld__pb2.HelloReply.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
Loading…
Reference in New Issue