mirror of https://github.com/grpc/grpc.git
[Python] Add an UDS example (#29592)
parent
972374347b
commit
3f2b3460a4
8 changed files with 394 additions and 0 deletions
@ -0,0 +1,2 @@ |
||||
*.pyc |
||||
helloworld.sock |
@ -0,0 +1,50 @@ |
||||
# Unix Domain Socket Example in gRPC Python |
||||
|
||||
## Check Our Guide First |
||||
|
||||
For knowing the basics of gRPC Python and the context around the helloworld example, please checkout our gRPC Python [Quick Start guide](https://grpc.io/docs/languages/python/quickstart). |
||||
|
||||
## Overview |
||||
|
||||
This example demonstrate how gRPC Python can utilize the gRPC Name Resolution mechanism to specify UDS address for clients and servers. The gRPC Name Resolution mechanism is documented at https://github.com/grpc/grpc/blob/master/doc/naming.md. |
||||
|
||||
Specifically, this example will bind the server to the following UDS addresses, and use clients to connect to them: |
||||
|
||||
* `unix:path`: setting the unix domain socket path relatively or absolutely |
||||
* `unix://absolute_path`: setting the absolute path of the unix domain socket |
||||
|
||||
## Prerequisite |
||||
|
||||
The Python interpreter should have `grpcio` and `protobuf` installed. |
||||
|
||||
## Running The Example |
||||
|
||||
Starting the server: |
||||
|
||||
``` |
||||
$ python3 greeter_server.py |
||||
INFO:root:Server listening on: unix:helloworld.sock |
||||
INFO:root:Server listening on: unix:///tmp/helloworld.sock |
||||
... |
||||
``` |
||||
|
||||
``` |
||||
$ python3 async_greeter_server.py |
||||
INFO:root:Server listening on: unix:helloworld.sock |
||||
INFO:root:Server listening on: unix:///tmp/helloworld.sock |
||||
... |
||||
``` |
||||
|
||||
Connecting with a client: |
||||
|
||||
``` |
||||
$ python3 greeter_client.py |
||||
INFO:root:Received: Hello to unix:helloworld.sock! |
||||
INFO:root:Received: Hello to unix:///tmp/helloworld.sock! |
||||
``` |
||||
|
||||
``` |
||||
$ python3 async_greeter_client.py |
||||
INFO:root:Received: Hello to unix:helloworld.sock! |
||||
INFO:root:Received: Hello to unix:///tmp/helloworld.sock! |
||||
``` |
@ -0,0 +1,36 @@ |
||||
# Copyright 2022 The 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 gRPC AsyncIO client for the UDS example.""" |
||||
|
||||
import asyncio |
||||
import logging |
||||
|
||||
import grpc |
||||
import helloworld_pb2 |
||||
import helloworld_pb2_grpc |
||||
|
||||
|
||||
async def run() -> None: |
||||
uds_addresses = ['unix:helloworld.sock', 'unix:///tmp/helloworld.sock'] |
||||
for uds_address in uds_addresses: |
||||
async with grpc.aio.insecure_channel(uds_address) as channel: |
||||
stub = helloworld_pb2_grpc.GreeterStub(channel) |
||||
response = await stub.SayHello( |
||||
helloworld_pb2.HelloRequest(name='you')) |
||||
logging.info('Received: %s', response.message) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
logging.basicConfig(level=logging.INFO) |
||||
asyncio.run(run()) |
@ -0,0 +1,46 @@ |
||||
# Copyright 2022 The 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 gRPC AsyncIO server for the UDS example.""" |
||||
|
||||
import asyncio |
||||
import logging |
||||
|
||||
import grpc |
||||
import helloworld_pb2 |
||||
import helloworld_pb2_grpc |
||||
|
||||
|
||||
class Greeter(helloworld_pb2_grpc.GreeterServicer): |
||||
|
||||
async def SayHello( |
||||
self, request: helloworld_pb2.HelloRequest, |
||||
context: grpc.aio.ServicerContext) -> helloworld_pb2.HelloReply: |
||||
del request |
||||
return helloworld_pb2.HelloReply(message=f'Hello to {context.peer()}!') |
||||
|
||||
|
||||
async def serve() -> None: |
||||
uds_addresses = ['unix:helloworld.sock', 'unix:///tmp/helloworld.sock'] |
||||
server = grpc.aio.server() |
||||
helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) |
||||
for uds_address in uds_addresses: |
||||
server.add_insecure_port(uds_address) |
||||
logging.info('Server listening on: %s', uds_address) |
||||
await server.start() |
||||
await server.wait_for_termination() |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
logging.basicConfig(level=logging.INFO) |
||||
asyncio.run(serve()) |
@ -0,0 +1,36 @@ |
||||
# Copyright 2022 The 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 gRPC Python client for the UDS example.""" |
||||
|
||||
from __future__ import print_function |
||||
|
||||
import logging |
||||
|
||||
import grpc |
||||
import helloworld_pb2 |
||||
import helloworld_pb2_grpc |
||||
|
||||
|
||||
def run(): |
||||
uds_addresses = ['unix:helloworld.sock', 'unix:///tmp/helloworld.sock'] |
||||
for uds_address in uds_addresses: |
||||
with grpc.insecure_channel(uds_address) as channel: |
||||
stub = helloworld_pb2_grpc.GreeterStub(channel) |
||||
response = stub.SayHello(helloworld_pb2.HelloRequest(name='you')) |
||||
logging.info('Received: %s', response.message) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
logging.basicConfig(level=logging.INFO) |
||||
run() |
@ -0,0 +1,44 @@ |
||||
# Copyright 2022 The 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 gRPC Python server for the UDS example.""" |
||||
|
||||
from concurrent import futures |
||||
import logging |
||||
|
||||
import grpc |
||||
import helloworld_pb2 |
||||
import helloworld_pb2_grpc |
||||
|
||||
|
||||
class Greeter(helloworld_pb2_grpc.GreeterServicer): |
||||
|
||||
def SayHello(self, request, context): |
||||
del request |
||||
return helloworld_pb2.HelloReply(message=f'Hello to {context.peer()}!') |
||||
|
||||
|
||||
def serve(): |
||||
uds_addresses = ['unix:helloworld.sock', 'unix:///tmp/helloworld.sock'] |
||||
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) |
||||
helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) |
||||
for uds_address in uds_addresses: |
||||
server.add_insecure_port(uds_address) |
||||
logging.info('Server listening on: %s', uds_address) |
||||
server.start() |
||||
server.wait_for_termination() |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
logging.basicConfig(level=logging.INFO) |
||||
serve() |
@ -0,0 +1,134 @@ |
||||
# Generated by the protocol buffer compiler. DO NOT EDIT! |
||||
# source: helloworld.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 |
||||
from google.protobuf import descriptor_pb2 |
||||
# @@protoc_insertion_point(imports) |
||||
|
||||
_sym_db = _symbol_database.Default() |
||||
|
||||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor.FileDescriptor( |
||||
name='helloworld.proto', |
||||
package='helloworld', |
||||
syntax='proto3', |
||||
serialized_pb=_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') |
||||
) |
||||
|
||||
|
||||
|
||||
|
||||
_HELLOREQUEST = _descriptor.Descriptor( |
||||
name='HelloRequest', |
||||
full_name='helloworld.HelloRequest', |
||||
filename=None, |
||||
file=DESCRIPTOR, |
||||
containing_type=None, |
||||
fields=[ |
||||
_descriptor.FieldDescriptor( |
||||
name='name', full_name='helloworld.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, |
||||
options=None), |
||||
], |
||||
extensions=[ |
||||
], |
||||
nested_types=[], |
||||
enum_types=[ |
||||
], |
||||
options=None, |
||||
is_extendable=False, |
||||
syntax='proto3', |
||||
extension_ranges=[], |
||||
oneofs=[ |
||||
], |
||||
serialized_start=32, |
||||
serialized_end=60, |
||||
) |
||||
|
||||
|
||||
_HELLOREPLY = _descriptor.Descriptor( |
||||
name='HelloReply', |
||||
full_name='helloworld.HelloReply', |
||||
filename=None, |
||||
file=DESCRIPTOR, |
||||
containing_type=None, |
||||
fields=[ |
||||
_descriptor.FieldDescriptor( |
||||
name='message', full_name='helloworld.HelloReply.message', 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, |
||||
options=None), |
||||
], |
||||
extensions=[ |
||||
], |
||||
nested_types=[], |
||||
enum_types=[ |
||||
], |
||||
options=None, |
||||
is_extendable=False, |
||||
syntax='proto3', |
||||
extension_ranges=[], |
||||
oneofs=[ |
||||
], |
||||
serialized_start=62, |
||||
serialized_end=91, |
||||
) |
||||
|
||||
DESCRIPTOR.message_types_by_name['HelloRequest'] = _HELLOREQUEST |
||||
DESCRIPTOR.message_types_by_name['HelloReply'] = _HELLOREPLY |
||||
_sym_db.RegisterFileDescriptor(DESCRIPTOR) |
||||
|
||||
HelloRequest = _reflection.GeneratedProtocolMessageType('HelloRequest', (_message.Message,), dict( |
||||
DESCRIPTOR = _HELLOREQUEST, |
||||
__module__ = 'helloworld_pb2' |
||||
# @@protoc_insertion_point(class_scope:helloworld.HelloRequest) |
||||
)) |
||||
_sym_db.RegisterMessage(HelloRequest) |
||||
|
||||
HelloReply = _reflection.GeneratedProtocolMessageType('HelloReply', (_message.Message,), dict( |
||||
DESCRIPTOR = _HELLOREPLY, |
||||
__module__ = 'helloworld_pb2' |
||||
# @@protoc_insertion_point(class_scope:helloworld.HelloReply) |
||||
)) |
||||
_sym_db.RegisterMessage(HelloReply) |
||||
|
||||
|
||||
DESCRIPTOR.has_options = True |
||||
DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW')) |
||||
|
||||
_GREETER = _descriptor.ServiceDescriptor( |
||||
name='Greeter', |
||||
full_name='helloworld.Greeter', |
||||
file=DESCRIPTOR, |
||||
index=0, |
||||
options=None, |
||||
serialized_start=93, |
||||
serialized_end=166, |
||||
methods=[ |
||||
_descriptor.MethodDescriptor( |
||||
name='SayHello', |
||||
full_name='helloworld.Greeter.SayHello', |
||||
index=0, |
||||
containing_service=None, |
||||
input_type=_HELLOREQUEST, |
||||
output_type=_HELLOREPLY, |
||||
options=None, |
||||
), |
||||
]) |
||||
_sym_db.RegisterServiceDescriptor(_GREETER) |
||||
|
||||
DESCRIPTOR.services_by_name['Greeter'] = _GREETER |
||||
|
||||
# @@protoc_insertion_point(module_scope) |
@ -0,0 +1,46 @@ |
||||
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! |
||||
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,)) |
Loading…
Reference in new issue