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
pull/32299/head
Xuan Wang 2 years ago committed by GitHub
parent 1f960697c5
commit a190831789
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 21
      examples/python/Makefile
  2. 56
      examples/python/health_checking/greeter_client.py
  3. 74
      examples/python/health_checking/greeter_server.py
  4. 30
      examples/python/health_checking/helloworld_pb2.py
  5. 17
      examples/python/health_checking/helloworld_pb2.pyi
  6. 70
      examples/python/health_checking/helloworld_pb2_grpc.py
  7. 46
      examples/python/helloworld/greeter_client_reflection.py
  8. 67
      examples/python/keep_alive/greeter_client.py
  9. 74
      examples/python/keep_alive/greeter_server.py
  10. 30
      examples/python/keep_alive/helloworld_pb2.py
  11. 17
      examples/python/keep_alive/helloworld_pb2.pyi
  12. 70
      examples/python/keep_alive/helloworld_pb2_grpc.py
  13. 45
      examples/python/timeout/greeter_client.py
  14. 46
      examples/python/timeout/greeter_server.py
  15. 30
      examples/python/timeout/helloworld_pb2.py
  16. 17
      examples/python/timeout/helloworld_pb2.pyi
  17. 70
      examples/python/timeout/helloworld_pb2_grpc.py

@ -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…
Cancel
Save