-
Notifications
You must be signed in to change notification settings - Fork 6.7k
Endpoints GRPC Python Sample #852
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
6c76b63
af5f9a4
b758290
3915587
23c6d58
e7ad7cc
729c008
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| # The Google Cloud Platform Python runtime is based on Debian Jessie | ||
| # You can read more about the runtime at: | ||
| # https://github.com/GoogleCloudPlatform/python-runtime | ||
| FROM gcr.io/google_appengine/python | ||
|
|
||
| # Create a virtualenv for dependencies. This isolates these packages from | ||
| # system-level packages. | ||
| RUN virtualenv /env | ||
|
|
||
| # Setting these environment variables are the same as running | ||
| # source /env/bin/activate. | ||
| ENV VIRTUAL_ENV -p python3.5 /env | ||
| ENV PATH /env/bin:$PATH | ||
|
|
||
| ADD . /hello/ | ||
|
|
||
| WORKDIR /hello | ||
|
|
||
| RUN pip install -r requirements.txt | ||
|
|
||
| EXPOSE 8000 | ||
|
|
||
| # Copy Server | ||
| COPY . /hello/ | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In general, dont use see: https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#add-or-copy
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
| ENTRYPOINT [] | ||
|
|
||
| CMD ["python", "helloworld/greeter_server.py"] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,168 @@ | ||
| # Endpoints Getting Started with gRPC & Python Quickstart | ||
|
|
||
| It is assumed that you have a working Python environment and a Google | ||
| Cloud account and [SDK](https://cloud.google.com/sdk/) configured. | ||
|
|
||
| 1. Install dependencies using virtualenv: | ||
|
|
||
| ```bash | ||
| virtualenv -p python3 env | ||
| source env/bin/activate | ||
| pip install -r requirements.txt | ||
| ``` | ||
|
|
||
| 1. Test running the code, optional: | ||
|
|
||
| ```bash | ||
| # Run the server: | ||
| python helloworld/greeter_server.py | ||
|
|
||
| # Open another command line tab and enter the virtual environment: | ||
| source env/bin/activate | ||
|
|
||
| # In the new command line tab, run the client: | ||
| python helloworld/greeter_client.py | ||
| ``` | ||
|
|
||
| 1. The gRPC Services have already been generated in `helloworld/`. If you | ||
| change the proto, or just wish to regenerate these files, run: | ||
|
|
||
| ```bash | ||
| python -m grpc_tools.protoc -I protos --python_out=helloworld --grpc_python_out=helloworld protos/helloworld.proto | ||
| ``` | ||
|
|
||
| 1. Generate the `out.pb` from the proto file. | ||
|
|
||
| ```bash | ||
| python -m grpc_tools.protoc --include_imports --include_source_info -I protos protos/helloworld.proto --descriptor_set_out out.pb | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jeffmendoza is
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jonparrott out.pb is what is used in the Java canonical sample (https://github.com/GoogleCloudPlatform/java-docs-samples/tree/master/endpoints/getting-started-grpc0). do you wanna change it to something else?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's fine, I was just questioning Jeff, but he's on leave now so it's whatever. :) |
||
| ``` | ||
|
|
||
| 1. Edit, `api_config.yaml`. Replace `MY_PROJECT_ID` with your project id. | ||
|
|
||
| 1. Deploy your service config to Service Management: | ||
|
|
||
| ```bash | ||
| gcloud service-management deploy out.pb api_config.yaml | ||
| # The Config ID should be printed out, looks like: 2017-02-01r0, remember this | ||
|
|
||
| # set your project to make commands easier | ||
| GCLOUD_PROJECT=<Your Project ID> | ||
|
|
||
| # Print out your Config ID again, in case you missed it | ||
| gcloud service-management configs list --service hellogrpc.endpoints.${GCLOUD_PROJECT}.cloud.goog | ||
| ``` | ||
|
|
||
| 1. Also get an API key from the Console's API Manager for use in the | ||
| client later. (https://console.cloud.google.com/apis/credentials) | ||
|
|
||
| 1. Enable the Cloud Build API: | ||
|
|
||
| ```bash | ||
| gcloud service-management enable cloudbuild.googleapis.com | ||
| ``` | ||
|
|
||
| 1. Build a docker image for your gRPC server, store in your Registry | ||
|
|
||
| ```bash | ||
| gcloud container builds submit --tag gcr.io/${GCLOUD_PROJECT}/python-grpc-hello:1.0 . | ||
| ``` | ||
|
|
||
| 1. Either deploy to GCE (below) or GKE (further down) | ||
|
|
||
| ### GCE | ||
|
|
||
| 1. Enable the Compute Engine API. | ||
|
|
||
| ```bash | ||
| gcloud service-management enable compute-component.googleapis.com | ||
| ``` | ||
|
|
||
| 1. Create your instance and ssh in. | ||
|
|
||
| ```bash | ||
| gcloud compute instances create grpc-host --image-family gci-stable --image-project google-containers --tags=http-server | ||
| gcloud compute ssh grpc-host | ||
| ``` | ||
|
|
||
| 1. Set some variables to make commands easier | ||
|
|
||
| ```bash | ||
| GCLOUD_PROJECT=$(curl -s "http://metadata.google.internal/computeMetadata/v1/project/project-id" -H "Metadata-Flavor: Google") | ||
| SERVICE_NAME=hellogrpc.endpoints.${GCLOUD_PROJECT}.cloud.goog | ||
| SERVICE_CONFIG_ID=<Your Config ID> | ||
| ``` | ||
|
|
||
| 1. Pull your credentials to access Container Registry, and run your | ||
| gRPC server container | ||
|
|
||
| ```bash | ||
| /usr/share/google/dockercfg_update.sh | ||
| docker run -d --name=grpc-hello gcr.io/${GCLOUD_PROJECT}/python-grpc-hello:1.0 | ||
| ``` | ||
|
|
||
| 1. Run the Endpoints proxy | ||
|
|
||
| ```bash | ||
| docker run --detach --name=esp \ | ||
| -p 80:9000 \ | ||
| --link=grpc-hello:grpc-hello \ | ||
| gcr.io/endpoints-release/endpoints-runtime:1 \ | ||
| -s ${SERVICE_NAME} \ | ||
| -v ${SERVICE_CONFIG_ID} \ | ||
| -P 9000 \ | ||
| -a grpc://grpc-hello:50051 | ||
| ``` | ||
|
|
||
| 1. Back on your local machine, get the external IP of your GCE instance. | ||
|
|
||
| ```bash | ||
| gcloud compute instances list | ||
| ``` | ||
|
|
||
| 1. Run the client | ||
|
|
||
| ```bash | ||
| python helloworld/greeter_client.py --host=<IP of GCE Instance>:80 --api_key=<API Key from Console> | ||
| ``` | ||
|
|
||
| 1. Cleanup | ||
|
|
||
| ```bash | ||
| gcloud compute instances delete grpc-host | ||
| ``` | ||
|
|
||
| ### GKE | ||
|
|
||
| 1. Create a cluster. You can specify a different zone than us-central1-a if you | ||
| want. | ||
|
|
||
| ```bash | ||
| gcloud container clusters create my-cluster --zone=us-central1-a | ||
| ``` | ||
|
|
||
| 1. Edit `container-engine.yaml`. Replace `SERVICE_NAME`, | ||
| `SERVICE_CONFIG_ID`, and `GCLOUD_PROJECT` with your values. | ||
|
|
||
| 1. Deploy to GKE | ||
|
|
||
| ```bash | ||
| kubectl create -f ./container-engine.yaml | ||
| ``` | ||
|
|
||
| 1. Get IP of load balancer, run until you see an External IP. | ||
|
|
||
| ```bash | ||
| kubectl get svc grpc-hello | ||
| ``` | ||
|
|
||
| 1. Run the client | ||
|
|
||
| ```bash | ||
| python helloworld/greeter_client.py <IP of GKE LoadBalancer>:80 <API Key from Console> | ||
| ``` | ||
|
|
||
| 1. Cleanup | ||
|
|
||
| ```bash | ||
| gcloud container clusters delete my-cluster --zone=us-central1-a | ||
| ``` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| # Copyright 2017 Google Inc. | ||
| # | ||
| # 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. | ||
|
|
||
| # | ||
| # An example API configuration. | ||
| # | ||
| # Below, replace MY_PROJECT_ID with your Google Cloud Project ID. | ||
| # | ||
|
|
||
| # The configuration schema is defined by service.proto file | ||
| # https://github.com/googleapis/googleapis/blob/master/google/api/service.proto | ||
| type: google.api.Service | ||
| config_version: 3 | ||
|
|
||
| # | ||
| # Name of the service configuration. | ||
| # | ||
| name: hellogrpc.endpoints.MY_PROJECT_ID.cloud.goog | ||
|
|
||
| # | ||
| # API title to appear in the user interface (Google Cloud Console). | ||
| # | ||
| title: Hello gRPC API | ||
| apis: | ||
| - name: helloworld.Greeter |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| # Copyright 2017 Google Inc. | ||
| # | ||
| # 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. | ||
|
|
||
| apiVersion: v1 | ||
| kind: Service | ||
| metadata: | ||
| name: grpc-hello | ||
| spec: | ||
| ports: | ||
| - port: 80 | ||
| targetPort: 9000 | ||
| protocol: TCP | ||
| name: http | ||
| selector: | ||
| app: grpc-hello | ||
| type: LoadBalancer | ||
| --- | ||
| apiVersion: extensions/v1beta1 | ||
| kind: Deployment | ||
| metadata: | ||
| name: grpc-hello | ||
| spec: | ||
| replicas: 1 | ||
| template: | ||
| metadata: | ||
| labels: | ||
| app: grpc-hello | ||
| spec: | ||
| containers: | ||
| - name: esp | ||
| image: gcr.io/endpoints-release/endpoints-runtime:1 | ||
| args: [ | ||
| "-P", "9000", | ||
| "-a", "grpc://127.0.0.1:50051", | ||
| "-s", "SERVICE_NAME", | ||
| "-v", "SERVICE_CONFIG_ID", | ||
| ] | ||
| ports: | ||
| - containerPort: 9000 | ||
| - name: python-grpc-hello | ||
| image: gcr.io/GCLOUD_PROJECT/python-grpc-hello:1.0 | ||
| ports: | ||
| - containerPort: 50051 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| *.pyc |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| [This code's documentation lives on the grpc.io site.](http://www.grpc.io/docs/quickstart/python.html) | ||
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| # Copyright 2015, Google Inc. | ||
| # All rights reserved. | ||
| # | ||
| # Redistribution and use in source and binary forms, with or without | ||
| # modification, are permitted provided that the following conditions are | ||
| # met: | ||
| # | ||
| # * Redistributions of source code must retain the above copyright | ||
| # notice, this list of conditions and the following disclaimer. | ||
| # * Redistributions in binary form must reproduce the above | ||
| # copyright notice, this list of conditions and the following disclaimer | ||
| # in the documentation and/or other materials provided with the | ||
| # distribution. | ||
| # * Neither the name of Google Inc. nor the names of its | ||
| # contributors may be used to endorse or promote products derived from | ||
| # this software without specific prior written permission. | ||
| # | ||
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
|
|
||
| """The Python implementation of the GRPC helloworld.Greeter client.""" | ||
|
|
||
| from __future__ import print_function | ||
|
|
||
| import argparse | ||
|
|
||
| import grpc | ||
|
|
||
| import helloworld_pb2 | ||
| import helloworld_pb2_grpc | ||
|
|
||
|
|
||
| def run(host, api_key): | ||
| channel = grpc.insecure_channel(host) | ||
| stub = helloworld_pb2_grpc.GreeterStub(channel) | ||
| metadata = [] | ||
| if api_key: | ||
| metadata.append(('x-api-key', api_key)) | ||
| response = stub.SayHello( | ||
| helloworld_pb2.HelloRequest(name='you'), metadata=metadata) | ||
| print("Greeter client received: " + response.message) | ||
| response = stub.SayHelloAgain( | ||
| helloworld_pb2.HelloRequest(name='you'), metadata=metadata) | ||
| print("Greeter client received: " + response.message) | ||
|
|
||
|
|
||
| if __name__ == '__main__': | ||
| parser = argparse.ArgumentParser( | ||
| description=__doc__, | ||
| formatter_class=argparse.RawDescriptionHelpFormatter) | ||
| parser.add_argument( | ||
| '--host', default='localhost:50051', help='The server host.') | ||
| parser.add_argument( | ||
| '--api_key', default=None, help='The API key to use for the call.') | ||
| args = parser.parse_args() | ||
| run(args.host, args.api_key) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this container is exposing 50051, but listing it is not necessary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done