App Engine Development Ron Reiter, 2012
App Engine DevelopmentRon Reiter, 2012
Agenda● What is Google App Engine● Advantages● Disadvantages● Creating your first webapp● Deployment● Features● Reducing Cost
What is GAE● Google App Engine is a Platform-as-a-
service server for web applications● Similar to Heroku, but writing atop it
requires using specific Google APIs● Supports Python, Java and Go
Advantages● Scales automatically● Bills by services used● Easy to deploy● Extremely high uptime of all services (web
server, database, cronjobs, mail delivery, etc)
● Free development tier
Disadvantages● Cannot use native libraries with Python● Cannot use different runtime
environments, such as PyPy (yet).● Constrained to Google because code is
Google specific● 30 second limit per request● No websockets for now● High price because of PaaS
Your first Web Application● Download the Google App Engine Python
SDK● Add a new application● Click "Run"● Go to
http://localhost:8080● And you're done!
Your first Web Application● The code example contains two important
files:○ main.py - the web server code example○ app.yaml - the web application configuration
● It also contains a favicon example and a file called index.yaml, which you don't need to touch right now.
app.yaml● The default app.yaml configuration is to
forward all requests to main.py● We will need to add a static files path, if we
want App Engine to serve some static files.
- url: /static
static_dir: static
Deployment● Go to http://appengine.google.com● If you haven't yet verified your account
using your mobile phone, please do so● Add a new application and find an
available identifier for it● Once you've created it, change your app.
yaml file to use the same identifier● Using your Google credentials, Use the
App Engine launcher to deploy
Deployment (cont.)● After deploying, use the GAE dashboard
for datastore access, logs, quota details, load, and more.
main.pyimport webapp2
class MainHandler(webapp2.RequestHandler):
def get(self):
self.response.write("Hello world!")
app = webapp2.WSGIApplication([
('/', MainHandler)
], debug=True)
Templatesfrom google.appengine.ext.webapp import templateimport webapp2
class MainHandler(webapp2.RequestHandler):
def get(self):
self.response.write(template.render("index.html", {
"message" : "Hello, World!"
})
app = webapp2.WSGIApplication([
('/', MainHandler)
], debug=True)
GET/POST Parametersfrom google.appengine.ext.webapp import templateimport webapp2
class MainHandler(webapp2.RequestHandler):
def get(self):
self.response.write(template.render("index.html", {
"message" : self.request.get("message")
})
app = webapp2.WSGIApplication([
('/', MainHandler)
], debug=True)
URL Parametersfrom google.appengine.ext.webapp import templateimport webapp2
class MainHandler(webapp2.RequestHandler):
def get(self, message):
self.response.write(template.render("index.html", {
"message" : message
})
app = webapp2.WSGIApplication([
('/(\w+)', MainHandler)
], debug=True)
● NoSQL Database (BigTable)● Supports an SQL-like syntax called GQL
○ GqlQuery("SELECT * FROM Song WHERE composer = :composer", composer="Lennon, John")
● Scales Automatically● Django-like ORM (db.Model)● Map Reduce API● Expando - schema-less objects
Datastore API
The Model Classfrom google.appengine.ext import db
class Post(db.Model):
name = db.StringProperty()
body = db.TextProperty()
created = db.DateTimeProperty(auto_now_add=True)
# create a new entry
post = Post(
name = "Ron Reiter", body = "This is a guestbook entry!")
# save it to the databasepost.put()
The Model Class (cont.)# get the post keypost_id = post.key().id()
# using the class method to fetch the object using the IDpost = Post.get_by_id(post_id)
# update the entrypost.body = "This is the updated body"post.put()
● An alternative to the Datastore API● Document oriented instead of column
oriented● Schema-less● Can run map reduce queries on structured
properties, like MongoDB
NDB API
class Address(ndb.Model):
type = ndb.StringProperty() # E.g., 'home', 'work'
street = ndb.StringProperty()
city = ndb.StringProperty()
class Contact(ndb.Model):
name = ndb.StringProperty()
addresses = ndb.StructuredProperty(Address, repeated=True)
guido = Contact(name='Guido',
addresses=[Address(type='home',
city='Amsterdam'),
Address(type='work',
street='Spear St',
city='SF')])
guido.put()
NDB API (cont.)
● Cloud Storage is similar to Amazon S3● Integrates very well with App Engine
with files.open('/gs/mybucket/myobject/', 'r') as f:
data = f.read(1)
while data != "":
print data
data = f.read(1)
print 'Done reading file!'
Cloud Storage API
Python Service APIs● BlobStore API - Allows saving and
retrieving binary data from the datastore● Channel API - Gives server push
capabilities using long polling● Memcache API - fast key/value store● LogService API - Convenient logging● Mail API - Simple email delivery● Inbound mail handler - Use request
handlers to handle emails sent to the app
Python Service APIs● Search API - Powerful datastore search● Task Queues API - Allows queueing
request handlers to process data in the background
● Cron jobs - Allows scheduling request handlers to be executed
● Image API - Simple image processing module, based on PIL
Python Service APIs● URLFetch API - Alternative to urllib, use it
instead, also with asynchronous bindings● Users API - Easy integration for user
authentication using Google accounts● And more...
Reducing Cost of GAE App● Use Go (compiled) instead of Python for
CPU intensive applications● Use Asynchronous APIs to prevent
spawning new handlers for no reason● Use memcache whenever possible● Reduce DataStore calls● Use cache headers
Questions?Thank You!