Service Oriented Flask - Randall Degges

Service Oriented Flask - Randall Degges

Building service oriented web apps is a great way to separate concerns, parallelize development, and scale high traffic apps. One of the downsides of service oriented web applications, however, is managing the high overhead of communication between services, and handling the additional complexities that come along with service driven development.

In this presentation, Randall Degges, Stormpath Developer Evangelist and OpenCNAM co-founder, will share all of the best practices he learned while building OpenCNAM, supporting billions of API requests.


PyGotham 2014

August 17, 2014


  1. Service Oriented Flask Building awesome software that scales. @rdegges

  2. Yo, I’m Randall! “I’m just a happy programmer that likes

    to hack stuff.” Developer Evangelist, Stormpath
  3. (I also founded / built an API company that handles

    billions of API requests.)
  4. I <333 python.

  5. “Uh, why did I attend this talk again?”

  6. (And there are lots of ways to do it.) Scaling

    software is hard.
  7. How to write awesome software that scales using SOA.

  8. • What SOA is, exactly. • Why SOA is awesome.

    • The most import rule. • How to build reliable services. • How to make faster services. • How to scale Flask services. • The biggest SOA issue. • How to have more fun. What I’ll Cover
  9. 0x00 What is SOA?

  10. Big App Small Apps Website / API billing users api

  11. Users Service GET /users Returns a list of all user

    accounts. GET /users/<uid> Returns the user identified by uid. POST /users Create a new user. POST /users/authenticate Authenticate a user. PUT /users/<uid> Update a user account identified by uid. PATCH /users/<uid> Update a user account identified by uid. DELETE /users/<uid> Delete a user identified by uid.
  12. Isolated

  13. Database(s) Cache(s) Web Server(s) Load Balancer (s) Worker(s) Queue(s)

  14. 0x01 Why SOA?

  15. Less scope, less problems.

  16. Easily distribute work. billing users frontend api

  17. Easier to scale. Database(s) Database(s)

  18. Easier to test.

  19. 0x02 The Most Important Rule

  20. “Keep it simple.”


  22. Write your docs -- first.

  23. You may not need an API client.

  24. 0x03 How to Build Reliable Services

  25. integration tests > unit tests

  26. import urllib2 from flask import Flask from flask.ext.testing import LiveServerTestCase

    class MyTest(LiveServerTestCase): def create_app(self): app = Flask(__name__) app.config['TESTING'] = True app.config['LIVESERVER_PORT'] = 8943 return app def test_server_is_up_and_running(self): response = urllib2.urlopen(self.get_server_url()) self.assertEqual(response.code, 200)
  27. Foreman / Docker Make Testing with SOA Easier web: gunicorn

    myproject:app -k gevent -b$PORT servicea: cd ~/servicea && gunicorn myproject:app -k gevent -b$PORT serviceb: cd ~/serviceb && gunicorn myproject:app -k gevent -b$PORT $ foreman start 16:39:22 web.1 | started with pid 82834 16:39:22 worker.1 | started with pid 82835 16:39:22 blah.1 | started with pid 82836
  28. “Keep development, staging and production as similar as possible.” Development

  29. (postgression can help) $ curl -v postgres://user:password@host/db Tests postgres

  30. AUTO- DEPLOY YOUR CODE (or else)

  31. Travis!

  32. None
  33. Plan for downtime. Service B Service A

  34. Monitor your stuff.

  35. New Relic!

  36. 0x04 SOA Rules

  37. Always use HTTPS! Free certs from StartSSL!

  38. from flask import Flask from flask_sslify import SSLify app =

    Flask(__name__) sslify = SSLify(app) Flask-SSLify
  39. Flask-BasicAuth from flask import Flask from flask.ext.basicauth import BasicAuth app

    = Flask(__name__) app.config['BASIC_AUTH_USERNAME'] = 'john' app.config['BASIC_AUTH_PASSWORD'] = 'matrix' app.config['BASIC_AUTH_FORCE'] = True basic_auth = BasicAuth(app)
  40. There is only one serialization format: JSON.

  41. Keep deployment simple. $ git push heroku master

  42. 0x05 Speeding Things Up

  43. Your webserver isn’t slow.

  44. Use caching layers.

  45. Service A Code Cache CDN Clients

  46. from flask import Flask from flask.ext.cache import Cache app =

    Flask(__name__) cache = Cache(app, config={'CACHE_TYPE': 'simple'}) Flask-Cache
  47. 0x06 Scaling Services

  48. What’s your bottleneck? • CPU? • IO? • Memory?

  49. Scale vertically first, then horizontally.

  50. Web ? Web Vertical Scaling

  51. Web ? Web Web Web Horizontal Scaling

  52. Put your data in the right place.

  53. Dynamo Postgres Web Server 1ms 25ms

  54. Queue Everything Service A Code Cache Queue Service B Code

    Cache Queue
  55. from flask import Flask form flask.ext.rq import RQ, job app

    = Flask(__name__) RQ(app) @job def process(i): pass process.delay(3) Flask-RQ
  56. Outsource what you can. • Stormpath • Twilio • Loggly

    • Sendgrid • NewRelic • Ducksboard Less code, less *.
  57. billing users api frontend My Site logs stripe stormpath api

    frontend loggly
  58. 0x07 The Biggest SOA Problem

  59. Users! billing users api frontend logs

  60. frontend users username password submit ? Hmm.

  61. Flask-Security • Works with SQLAlchemy. • Configurable. • Password reset.

    • Basic Authentication (with email / password). • Token authentication. • Self hosted. • You have to build the API around it yourself.
  62. frontend users Flask-Security username password submit Flow Flask-Login

  63. from flask.ext.stormpath import StormpathManager app = Flask(__name__) stormpath_manager = StormpathManager(app)

  64. 0x09 Having MORE Fun

  65. Let’s Be Real Programming can be boringggg.

  66. Own your code.

  67. Release code.

  68. Tell people about it.

  69. Thank You 818-217-9229