Google App Engine                Writing a         Stack Overflow clone             on App Engine           in under an ho...
Agenda1. App Engine Introduction2. Demo: Building an app3. Demo: Deploying an app4. Demo: Writing App Overflow5. App Engin...
App Engineintroduction
Building web applications is hard
Thinking about scalabilityJust a few users....               ....the tools, platform and design               dont matter ...
Thinking about scalabilityLots and lots of users...               ....you must design for scalability
WhiteHouse.gov/openforquestions
Serving developers AND their customersGoogle App Engine                       Scalable                       High Performa...
The Components
1. Scalable Serving Architecture                   creative commons licensed photograph from cote
1. Scalable Serving Architecture                             Incoming Requests                App Engine      App Engine  ...
1. Scalable Serving Architecture                                    Incoming Requests                      App Engine     ...
2. Distributed DatastoreThe Datastore is...   Distributed   Transactional   Natively Partitioned   Hierarchial            ...
2. Distributed DatastoreThe Datastore is not...   A relational database   A SQL engine   Just Bigtable                    ...
Demo: Writing an app
App configurationapplication: appoverflowversion: 1runtime: pythonapi_version: 1handlers:- url: /.*  script: /request.py
Request handlingclass IndexHandler(webapp.RequestHandler): def render_template(self, name, values):   path = os.path.join(...
Demo: Deploying an app  In 30 seconds or less. Time me!
Demo: Writing App Overflow
Adding authenticationclass IndexHandler(webapp.RequestHandler): def __init__(self):   self.user = users.get_current_user()...
Adding authentication<html><head> <title>{%block title%}App Overflow{%endblock%}</title> {% block head %}{% endblock %}</h...
Storing datafrom google.appengine.ext import dbclass Question(db.Model): asker = db.UserProperty(required=True) title = db...
Storing dataclass NewQuestionHandler(BaseHandler): def get(self):   self.render_form(forms.QuestionForm()) def post(self):...
Fetching dataclass QuestionHandler(BaseHandler): def get_question(self, id):   question = models.Question.get_by_id(int(id...
Queriesclass IndexHandler(BaseHandler): def get_questions(self):   q = models.Question.all()   q.order(-asked_at)   return...
Precomputationclass Question(db.Model): asker = db.UserProperty(required=True) title = db.StringProperty(required=True, in...
Transactionsanswer = models.Answer(  parent=question,  answerer=self.user,  # ...)def save_answer(answer): def _tx():  que...
XMPPclass XmppHandler(xmpp_handlers.CommandHandler):  def ask_command(self, message=None):   question = models.Question(  ...
Additional services / APIs URL Fetch Memcache Mail - incoming and outgoing Images Google Accounts Cron support Task Queue
Questions?
Upcoming SlideShare
Loading in...5
×

Python Ireland Nov 2009 Talk - Appengine

617
-1

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
617
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
4
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Python Ireland Nov 2009 Talk - Appengine

  1. 1. Google App Engine Writing a Stack Overflow clone on App Engine in under an hour* http://blog.bitquabit.com/2009/07/01/one-which-i-call-out-hacker-news/
  2. 2. Agenda1. App Engine Introduction2. Demo: Building an app3. Demo: Deploying an app4. Demo: Writing App Overflow5. App Engines Services6. Questions If I say "Cloud" at any point, Boo!
  3. 3. App Engineintroduction
  4. 4. Building web applications is hard
  5. 5. Thinking about scalabilityJust a few users.... ....the tools, platform and design dont matter too much
  6. 6. Thinking about scalabilityLots and lots of users... ....you must design for scalability
  7. 7. WhiteHouse.gov/openforquestions
  8. 8. Serving developers AND their customersGoogle App Engine Scalable High Performance Standards Cost effective
  9. 9. The Components
  10. 10. 1. Scalable Serving Architecture creative commons licensed photograph from cote
  11. 11. 1. Scalable Serving Architecture Incoming Requests App Engine App Engine App Engine Front End Front End Front EndLoad Balancer AppServer AppServer AppServer
  12. 12. 1. Scalable Serving Architecture Incoming Requests App Engine App Engine App Engine Front End Front End Front EndLoad Balancer AppServer AppServer AppServer Other Google AppServer Infrastructure API Layer - Bigtable - Google Accounts App App App - Memcache - Image manipulation
  13. 13. 2. Distributed DatastoreThe Datastore is... Distributed Transactional Natively Partitioned Hierarchial Wow. That is one big table. Schemaless Based on Bigtable
  14. 14. 2. Distributed DatastoreThe Datastore is not... A relational database A SQL engine Just Bigtable Wow. That is one big table.
  15. 15. Demo: Writing an app
  16. 16. App configurationapplication: appoverflowversion: 1runtime: pythonapi_version: 1handlers:- url: /.* script: /request.py
  17. 17. Request handlingclass IndexHandler(webapp.RequestHandler): def render_template(self, name, values): path = os.path.join(os.path.dirname(__file__), templates, name) self.response.out.write(template.render(path, values)) def get(self): self.render_template(index.html, {})application = webapp.WSGIApplication([ (/, IndexHandler),], debug=True)def main(): run_wsgi_app(application)
  18. 18. Demo: Deploying an app In 30 seconds or less. Time me!
  19. 19. Demo: Writing App Overflow
  20. 20. Adding authenticationclass IndexHandler(webapp.RequestHandler): def __init__(self): self.user = users.get_current_user() def render_template(self, name, values): url = self.request.url template_values.update({ user: self.user, login_url:users.create_login_url(url), logout_url:users.create_logout_url(url), }) path = os.path.join(os.path.dirname(__file__), templates, template_name) self.response.out.write(template.render(path, template_values))
  21. 21. Adding authentication<html><head> <title>{%block title%}App Overflow{%endblock%}</title> {% block head %}{% endblock %}</head><body> <div class="login"> {% if user %} Logged in as {{user.nickname}} | <a href="{{logout_url}}">Log Out</a> {% else %} <a href="{{login_url}}">Log In</a> {% endif %} </div> {% block body %}{% endblock %}</body></html>
  22. 22. Storing datafrom google.appengine.ext import dbclass Question(db.Model): asker = db.UserProperty(required=True) title = db.StringProperty(required=True, indexed=False) body = db.TextProperty(required=True) asked_at = db.DateTimeProperty(auto_now_add=True)
  23. 23. Storing dataclass NewQuestionHandler(BaseHandler): def get(self): self.render_form(forms.QuestionForm()) def post(self): form = forms.QuestionForm(self.request.POST) if not form.is_valid(): self.render_form(form) return entity = models.Question( asker=self.user, **form.clean_data) entity.put() self.redirect(/questions/%d/ % (entity.key().id(),))
  24. 24. Fetching dataclass QuestionHandler(BaseHandler): def get_question(self, id): question = models.Question.get_by_id(int(id)) return question def render_page(self, question): template_values = { question: question, } self.render_template(question.html, template_values) def get(self, id): question = self.get_question(id) if question: self.render_page(question)
  25. 25. Queriesclass IndexHandler(BaseHandler): def get_questions(self): q = models.Question.all() q.order(-asked_at) return q.fetch(20) def render_page(self): template_values = { questions: self.get_questions(), } self.render_template(index.html, template_values) def get(self): self.render_page()
  26. 26. Precomputationclass Question(db.Model): asker = db.UserProperty(required=True) title = db.StringProperty(required=True, indexed=False) body = db.TextProperty(required=True) asked_at = db.DateTimeProperty(auto_now_add=True) answer_count = db.IntegerProperty(required=True, default=0)class Answer(db.Model): answerer = db.UserProperty(required=True) body = db.TextProperty(required=True) answered_at = db.DateTimeProperty(auto_now_add=True)
  27. 27. Transactionsanswer = models.Answer( parent=question, answerer=self.user, # ...)def save_answer(answer): def _tx(): question = db.get(answer.parent().key()) question.answer_count += 1 db.put([answer, question]) return answer.key() return db.run_in_transaction(_tx)
  28. 28. XMPPclass XmppHandler(xmpp_handlers.CommandHandler): def ask_command(self, message=None): question = models.Question( title=message.arg, body=message.arg, sender=message.sender) question.put() message.reply(Your question has been received. You will be pinged when an answeris submitted.)# Elsewhere...xmpp.send_message([question.sender], Answer: + answer.body)
  29. 29. Additional services / APIs URL Fetch Memcache Mail - incoming and outgoing Images Google Accounts Cron support Task Queue
  30. 30. Questions?
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×