Skip to content

Commit e6a5ff4

Browse files
ryanmatsJon Wayne Parrott
authored andcommitted
Endpoints GRPC Python Sample (GoogleCloudPlatform#852)
1 parent 003c30c commit e6a5ff4

File tree

11 files changed

+798
-1
lines changed

11 files changed

+798
-1
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# The Google Cloud Platform Python runtime is based on Debian Jessie
2+
# You can read more about the runtime at:
3+
# https://github.com/GoogleCloudPlatform/python-runtime
4+
FROM gcr.io/google_appengine/python
5+
6+
# Create a virtualenv for dependencies. This isolates these packages from
7+
# system-level packages.
8+
RUN virtualenv /env
9+
10+
# Setting these environment variables are the same as running
11+
# source /env/bin/activate.
12+
ENV VIRTUAL_ENV -p python3.5 /env
13+
ENV PATH /env/bin:$PATH
14+
15+
COPY requirements.txt /app/
16+
RUN pip install --requirement /app/requirements.txt
17+
COPY . /app/
18+
19+
ENTRYPOINT []
20+
21+
CMD ["python", "/app/greeter_server.py"]
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
# Endpoints Getting Started with gRPC & Python Quickstart
2+
3+
It is assumed that you have a working Python environment and a Google
4+
Cloud account and [SDK](https://cloud.google.com/sdk/) configured.
5+
6+
1. Install dependencies using virtualenv:
7+
8+
```bash
9+
virtualenv -p python3 env
10+
source env/bin/activate
11+
pip install -r requirements.txt
12+
```
13+
14+
1. Test running the code, optional:
15+
16+
```bash
17+
# Run the server:
18+
python greeter_server.py
19+
20+
# Open another command line tab and enter the virtual environment:
21+
source env/bin/activate
22+
23+
# In the new command line tab, run the client:
24+
python greeter_client.py
25+
```
26+
27+
1. The gRPC Services have already been generated. If you change the proto, or
28+
just wish to regenerate these files, run:
29+
30+
```bash
31+
python -m grpc_tools.protoc -I protos --python_out=. --grpc_python_out=. protos/helloworld.proto
32+
```
33+
34+
1. Generate the `out.pb` from the proto file:
35+
36+
```bash
37+
python -m grpc_tools.protoc --include_imports --include_source_info -I protos protos/helloworld.proto --descriptor_set_out out.pb
38+
```
39+
40+
1. Edit, `api_config.yaml`. Replace `MY_PROJECT_ID` with your project id.
41+
42+
1. Deploy your service config to Service Management:
43+
44+
```bash
45+
gcloud service-management deploy out.pb api_config.yaml
46+
# The Config ID should be printed out, looks like: 2017-02-01r0, remember this
47+
48+
# Set your project ID as a variable to make commands easier:
49+
GCLOUD_PROJECT=<Your Project ID>
50+
51+
# Print out your Config ID again, in case you missed it:
52+
gcloud service-management configs list --service hellogrpc.endpoints.${GCLOUD_PROJECT}.cloud.goog
53+
```
54+
55+
1. Also get an API key from the Console's API Manager for use in the
56+
client later. (https://console.cloud.google.com/apis/credentials)
57+
58+
1. Enable the Cloud Build API:
59+
60+
```bash
61+
gcloud service-management enable cloudbuild.googleapis.com
62+
```
63+
64+
1. Build a docker image for your gRPC server, and store it in your Registry:
65+
66+
```bash
67+
gcloud container builds submit --tag gcr.io/${GCLOUD_PROJECT}/python-grpc-hello:1.0 .
68+
```
69+
70+
1. Either deploy to GCE (below) or GKE (further down).
71+
72+
### GCE
73+
74+
1. Enable the Compute Engine API:
75+
76+
```bash
77+
gcloud service-management enable compute-component.googleapis.com
78+
```
79+
80+
1. Create your instance and ssh in:
81+
82+
```bash
83+
gcloud compute instances create grpc-host --image-family gci-stable --image-project google-containers --tags=http-server
84+
gcloud compute ssh grpc-host
85+
```
86+
87+
1. Set some variables to make commands easier:
88+
89+
```bash
90+
GCLOUD_PROJECT=$(curl -s "http://metadata.google.internal/computeMetadata/v1/project/project-id" -H "Metadata-Flavor: Google")
91+
SERVICE_NAME=hellogrpc.endpoints.${GCLOUD_PROJECT}.cloud.goog
92+
SERVICE_CONFIG_ID=<Your Config ID>
93+
```
94+
95+
1. Pull your credentials to access Container Registry, and run your gRPC server
96+
container:
97+
98+
```bash
99+
/usr/share/google/dockercfg_update.sh
100+
docker run -d --name=grpc-hello gcr.io/${GCLOUD_PROJECT}/python-grpc-hello:1.0
101+
```
102+
103+
1. Run the Endpoints proxy:
104+
105+
```bash
106+
docker run --detach --name=esp \
107+
-p 80:9000 \
108+
--link=grpc-hello:grpc-hello \
109+
gcr.io/endpoints-release/endpoints-runtime:1 \
110+
-s ${SERVICE_NAME} \
111+
-v ${SERVICE_CONFIG_ID} \
112+
-P 9000 \
113+
-a grpc://grpc-hello:50051
114+
```
115+
116+
1. Back on your local machine, get the external IP of your GCE instance:
117+
118+
```bash
119+
gcloud compute instances list
120+
```
121+
122+
1. Run the client:
123+
124+
```bash
125+
python greeter_client.py --host=<IP of GCE Instance>:80 --api_key=<API Key from Console>
126+
```
127+
128+
1. Cleanup:
129+
130+
```bash
131+
gcloud compute instances delete grpc-host
132+
```
133+
134+
### GKE
135+
136+
1. Create a cluster. You can specify a different zone than us-central1-a if you
137+
want:
138+
139+
```bash
140+
gcloud container clusters create my-cluster --zone=us-central1-a
141+
```
142+
143+
1. Edit `container-engine.yaml`. Replace `SERVICE_NAME`, `SERVICE_CONFIG_ID`,
144+
and `GCLOUD_PROJECT` with your values:
145+
146+
`SERVICE_NAME` is equal to hellogrpc.endpoints.GCLOUD_PROJECT.cloud.goog,
147+
replacing GCLOUD_PROJECT with your project ID.
148+
149+
`SERVICE_CONFIG_ID` can be found by running the following command, replacing
150+
GCLOUD_PROJECT with your project ID.
151+
152+
```bash
153+
gcloud service-management configs list --service hellogrpc.endpoints.GCLOUD_PROJECT.cloud.goog
154+
```
155+
156+
1. Deploy to GKE:
157+
158+
```bash
159+
kubectl create -f ./container-engine.yaml
160+
```
161+
162+
1. Get IP of load balancer, run until you see an External IP:
163+
164+
```bash
165+
kubectl get svc grpc-hello
166+
```
167+
168+
1. Run the client:
169+
170+
```bash
171+
python greeter_client.py --host=<IP of GKE LoadBalancer>:80 --api_key=<API Key from Console>
172+
```
173+
174+
1. Cleanup:
175+
176+
```bash
177+
gcloud container clusters delete my-cluster --zone=us-central1-a
178+
```
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Copyright 2017 Google Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
#
16+
# An example API configuration.
17+
#
18+
# Below, replace MY_PROJECT_ID with your Google Cloud Project ID.
19+
#
20+
21+
# The configuration schema is defined by service.proto file
22+
# https://github.com/googleapis/googleapis/blob/master/google/api/service.proto
23+
type: google.api.Service
24+
config_version: 3
25+
26+
#
27+
# Name of the service configuration.
28+
#
29+
name: hellogrpc.endpoints.MY_PROJECT_ID.cloud.goog
30+
31+
#
32+
# API title to appear in the user interface (Google Cloud Console).
33+
#
34+
title: Hello gRPC API
35+
apis:
36+
- name: helloworld.Greeter
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Copyright 2017 Google Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
apiVersion: v1
16+
kind: Service
17+
metadata:
18+
name: grpc-hello
19+
spec:
20+
ports:
21+
- port: 80
22+
targetPort: 9000
23+
protocol: TCP
24+
name: http
25+
selector:
26+
app: grpc-hello
27+
type: LoadBalancer
28+
---
29+
apiVersion: extensions/v1beta1
30+
kind: Deployment
31+
metadata:
32+
name: grpc-hello
33+
spec:
34+
replicas: 1
35+
template:
36+
metadata:
37+
labels:
38+
app: grpc-hello
39+
spec:
40+
containers:
41+
- name: esp
42+
image: gcr.io/endpoints-release/endpoints-runtime:1
43+
args: [
44+
"-P", "9000",
45+
"-a", "grpc://127.0.0.1:50051",
46+
"-s", "SERVICE_NAME",
47+
"-v", "SERVICE_CONFIG_ID",
48+
]
49+
ports:
50+
- containerPort: 9000
51+
- name: python-grpc-hello
52+
image: gcr.io/GCLOUD_PROJECT/python-grpc-hello:1.0
53+
ports:
54+
- containerPort: 50051
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Copyright 2015, Google Inc.
2+
# All rights reserved.
3+
#
4+
# Redistribution and use in source and binary forms, with or without
5+
# modification, are permitted provided that the following conditions are
6+
# met:
7+
#
8+
# * Redistributions of source code must retain the above copyright
9+
# notice, this list of conditions and the following disclaimer.
10+
# * Redistributions in binary form must reproduce the above
11+
# copyright notice, this list of conditions and the following disclaimer
12+
# in the documentation and/or other materials provided with the
13+
# distribution.
14+
# * Neither the name of Google Inc. nor the names of its
15+
# contributors may be used to endorse or promote products derived from
16+
# this software without specific prior written permission.
17+
#
18+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21+
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22+
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26+
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
30+
"""The Python implementation of the GRPC helloworld.Greeter client."""
31+
32+
import argparse
33+
34+
import grpc
35+
36+
import helloworld_pb2
37+
import helloworld_pb2_grpc
38+
39+
40+
def run(host, api_key):
41+
channel = grpc.insecure_channel(host)
42+
stub = helloworld_pb2_grpc.GreeterStub(channel)
43+
metadata = []
44+
if api_key:
45+
metadata.append(('x-api-key', api_key))
46+
response = stub.SayHello(
47+
helloworld_pb2.HelloRequest(name='you'), metadata=metadata)
48+
print('Greeter client received: ' + response.message)
49+
response = stub.SayHelloAgain(
50+
helloworld_pb2.HelloRequest(name='you'), metadata=metadata)
51+
print('Greeter client received: ' + response.message)
52+
53+
54+
if __name__ == '__main__':
55+
parser = argparse.ArgumentParser(
56+
description=__doc__,
57+
formatter_class=argparse.RawDescriptionHelpFormatter)
58+
parser.add_argument(
59+
'--host', default='localhost:50051', help='The server host.')
60+
parser.add_argument(
61+
'--api_key', default=None, help='The API key to use for the call.')
62+
args = parser.parse_args()
63+
run(args.host, args.api_key)

0 commit comments

Comments
 (0)