Skip to content

add microservices demo #509

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

Merged
merged 12 commits into from
Oct 11, 2016
Merged
15 changes: 12 additions & 3 deletions appengine/flexible/multiple_services/api_gateway/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ $ pip install -r requirements.txt
$ deactivate
```

4. To start server locally use the development flag `--development` or `-d`
4. To start server locally:
```Bash
$ python <filename>.py --development
$ python <filename>.py
```

## To Deploy to App Engine
Expand All @@ -48,5 +48,14 @@ The deployed url will be `https://<service name>-dot-<your project id>.appspot.c

### Deployment

To deploy a service cd into its directory and run: `gcloud app deploy app.yaml`
To deploy a service cd into its directory and run:
```Bash
$ gcloud app deploy app.yaml
```
and enter `Y` when prompted. Or to skip the check add `-q`.

To deploy multiple services simultaneously just add the path to each `app.yaml`
file as an argument to `gcloud app deploy `:
```Bash
$ gcloud app deploy gateway/app.yaml static/app.yaml
```
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
import os
import requests
import sys
import argparse
from flask import Flask
import services_config

app = Flask(__name__)
#create service map for production urls unless --development flag added
app.config['SERVICE_MAP'] = services_config.map_services('production')

#setup arg parser to handle development flag
parser = argparse.ArgumentParser()
parser.add_argument('-d', '--development', action='store_true')
app = services_config.make_app(__name__)

@app.route('/')
def root():
Expand All @@ -20,11 +12,12 @@ def root():

@app.route('/hello/<service>')
def say_hello(service):
'''Recieves requests from the buttons on the front end and resopnds
'''Recieves requests from buttons on the front end and resopnds
or sends request to the static file server'''
#if 'gateway' is specified return immediate
if service == 'gateway':
return 'Gateway says hello'
#otherwise send request to service indicated by URL param
responses = []
url = app.config['SERVICE_MAP'][service]
res = requests.get(url + '/hello')
Expand All @@ -33,13 +26,11 @@ def say_hello(service):

@app.route('/<path>')
def static_file(path):
'''Handles static file requests from index.html'''
'''Gets static files required by index.html to static file server'''
url = app.config['SERVICE_MAP']['static']
res = requests.get(url + '/' + path)
return res.content, 200, {'Content-Type': res.headers['Content-Type']}

if __name__ == '__main__':
args = parser.parse_args()
if args.development:
app.config['SERVICE_MAP'] = services_config.map_services('development')
app.run()
port = os.environ.get('PORT') or 8000
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

won't this error because PORT is a string?

app.run(port=port)
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import os
from flask import Flask

#to add services insert key value pair of the name of the service and
#the port you want it to run on when running locally
SERVICES = {
'default': 5000,
'default': 8000,
'static': 8001
}

def make_app(name):
app = Flask(name)
environment = 'production' if os.environ.get('GAE_LONG_APP_ID') else 'development'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the time being, I recommend using os.environ.get('GAE_INSTANCE', os.environ.get('GAE_MODULE_INSTANCE')).

app.config['SERVICE_MAP'] = map_services(environment)
return app

def map_services(environment):
'''Generates a map of services to correct urls for running locally
or when deployed'''
url_map = {}
for service, local_port in SERVICES.items():
if environment == 'production':
Expand All @@ -17,13 +26,14 @@ def map_services(environment):
return url_map

def production_url(service_name):
project_id = os.environ.get('GAE_LONG_APP_ID') or 'flask-algo'
project_url = project_id + '.appspot.com'
template = 'https://{}{}'
'''Generates url for a service when deployed to App Engine'''
project_id = os.environ.get('GAE_LONG_APP_ID')
project_url = '{}.appspot.com'.format(project_id)
if service_name == 'default':
return template.format('', project_url)
return 'https://{}'.format(project_url)
else:
return template.format(service_name + '-dot-', project_url)
return 'https://{}-dot-{}'.format(service_name, project_url)

def local_url(port):
return 'http://localhost:' + str(port)
'''Generates url for a service when running locally'''
return 'http://localhost:{}'.format(str(port))
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ entrypoint: gunicorn -b :$PORT static_server:app

runtime_config:
python_version: 3

manual_scaling:
instances: 1
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import sys
import os
from flask import Flask

app = Flask(__name__)

@app.route('/hello')
def say_hello():
'''responds to request from frontend via gateway'''
return 'Static File Server says hello!'

@app.route('/')
def root():
'''serves index.html'''
return app.send_static_file('index.html')

@app.route('/<path:path>')
def static_file(path):
'''serves static files required by index.html'''
mimetype = ''
if path.split('.')[1] == 'css':
mimetype = 'text/css'
Expand All @@ -21,7 +24,5 @@ def static_file(path):
return app.send_static_file(path), 200, {'Content-Type': mimetype}

if __name__ == "__main__":
if len(sys.argv) > 1 and sys.argv[1] == '--development':
app.run(port=int(8001))
else:
app.run()
port = os.environ.get('PORT') or 8001
app.run(port=port)