Deploy a gRPC Service
Python gRPC Hello World Service
The complete example can be found at Python gRPC Helloworld - Truefoundry Examples
In this example, we will deploy a simple service with a Hello world RPC. This example was adapted from the official python gRPC quickstart: https://grpc.io/docs/languages/python/quickstart/
Project structure
Our final project structure will look like this
.
├── deploy.py
├── greeter_client_with_options.py
├── greeter_server_with_reflection.py
├── helloworld.proto
├── helloworld_pb2.py
├── helloworld_pb2.pyi
├── helloworld_pb2_grpc.py
└── requirements.txt
Step 1: Install grpcio
and grpc-tools
grpcio
and grpc-tools
pip install grpcio==1.51.3 grpcio-reflection==1.51.3 grpcio-tools==1.51.3
Let's also create a requirements.txt
and add dependencies which will be useful later.
requirements.txt
requirements.txt
grpcio==1.51.3
grpcio-reflection==1.51.3
grpcio-tools==1.51.3
protobuf==4.22.0
Step 2: Declare message
and rpc
message
and rpc
Create a helloworld.proto
with the following contents
helloworld.proto
helloworld.proto
syntax = "proto3";
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
Step 3: Next generate Python definitions
python -m grpc_tools.protoc -I. --python_out=. --pyi_out=. --grpc_python_out=. helloworld.proto
This will write helloworld_pb2.py
, helloworld_pb2.pyi
and helloworld_pb2_grpc.py
to your project directory.
Step 4: Implement the rpc
and gRPC Server
rpc
and gRPC ServerNext, we implement the SayHello
rpc and write code to start the gRPC Server on port 50051
greeter_server_with_reflection.py
greeter_server_with_reflection.py
from concurrent import futures
import logging
import grpc
from grpc_reflection.v1alpha import reflection
import helloworld_pb2
import helloworld_pb2_grpc
class Greeter(helloworld_pb2_grpc.GreeterServicer):
def SayHello(self, request, context):
logging.info('Now greeting %s' % request.name)
return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
SERVICE_NAMES = (
helloworld_pb2.DESCRIPTOR.services_by_name['Greeter'].full_name,
reflection.SERVICE_NAME,
)
reflection.enable_server_reflection(SERVICE_NAMES, server)
server.add_insecure_port('[::]:50051')
server.start()
logging.info('Server started!')
server.wait_for_termination()
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO, format=logging.BASIC_FORMAT)
serve()
Step 5: Deploy it using Truefoundry
We can now deploy our service using Python SDK or YAML spec. Make sure you have servicefoundry
installed and setup
Via Python SDK
Create a deploy.py
deploy.py
deploy.py
import argparse
import logging
from servicefoundry import Service, Build, PythonBuild, Resources, Port, AppProtocol
logging.basicConfig(level=logging.INFO, format=logging.BASIC_FORMAT)
parser = argparse.ArgumentParser()
parser.add_argument("--workspace_fqn", type=str, required=True,
help="FQN of the workspace to deploy to")
args = parser.parse_args()
service = Service(
name="grpc-py-helloworld",
image=Build(
build_spec=PythonBuild(
python_version="3.9",
requirements_path="requirements.txt",
command="python greeter_server_with_reflection.py"
)
),
resources=Resources(
cpu_request=0.2,
cpu_limit=0.5,
memory_request=500,
memory_limit=500,
),
ports=[
Port(
port=50051,
app_protocol=AppProtocol.grpc,
host="<Provide a host value based on your configured domain>"
# Note: Your cluster should allow subdomain based routing (*.yoursite.com) for gRPC to work correctly via public internet.
# A host matching the wildcard base domain for the cluster can be explicitly configured by passing in `host`
),
],
)
service.deploy(workspace_fqn=args.workspace_fqn)
Now we can deploy by simply running this file with Workspace FQN
python deploy.py --workspace_fqn <YOUR WORKSPACE FQN HERE>
Via YAML Spec
Create a deploy.yaml
with the following spec:
deploy.yaml
deploy.yaml
name: grpc-py-helloworld
type: service
image:
type: build
build_spec:
type: tfy-python-buildpack
command: python greeter_server_with_reflection.py
python_version: '3.9'
requirements_path: requirements.txt
build_context_path: ./
build_source:
type: local
ports:
- port: 50051
expose: true
protocol: TCP
app_protocol: grpc
host: <Provide a host value based on your configured domain>
replicas: 1
resources:
cpu_limit: 0.5
cpu_request: 0.2
memory_limit: 500
memory_request: 500
Now we can deploy by simply calling sfy deploy
with Workspace FQN
sfy deploy --file deploy.yaml --workspace-fqn <YOUR WORKSPACE FQN HERE>
Step 6: Get the Endpoint URL
Once deployed, we can find the Service in the Deployments section of the platform and get the Endpoint
Step 7: Interacting with our Service
We can now interact with our service by passing the Endpoint from Step 6.
Create a client python file as follows:
greeter_client_with_options.py
greeter_client_with_options.py
from __future__ import print_function
import argparse
import logging
import grpc
import helloworld_pb2
import helloworld_pb2_grpc
parser = argparse.ArgumentParser()
parser.add_argument(
"--host",
type=str,
required=True,
help="Host of the deployed service",
)
parser.add_argument(
"--name",
type=str,
required=False,
default="Truefoundry User",
help="Input name",
)
args = parser.parse_args()
def run():
with grpc.secure_channel(
target=args.host,
credentials=grpc.ssl_channel_credentials(),
) as channel:
stub = helloworld_pb2_grpc.GreeterStub(channel)
response = stub.SayHello(helloworld_pb2.HelloRequest(name=args.name), timeout=10)
print("Greeter client received: " + response.message)
if __name__ == '__main__':
logging.basicConfig()
run()
We can invoke our rpc by running the file
python greeter_client_with_options.py --host <YOUR ENDPOINT HERE> --name User
E.g. if Endpoint were https://grpc-py-helloworld-tfy-demo-50051.abc.xyz.example.com
python greeter_client_with_options.py --host grpc-py-helloworld-tfy-demo-50051.abc.xyz.example.com --name User
Note: Do not pass
https://
in the--host
option
This should get us output like
Greeter client received: Hello, User!
Updated 5 months ago