django's role – in the polyglot web – a brief history



django's role – in the polyglot web – a brief history

0 0


djangocon-eu-2015

Django's role in the polyglot web - DjangoCon EU 2015

On Github dgouldin / djangocon-eu-2015

django's role

in the polyglot web

by David Gouldin / @dgouldin

django-polyglot.herokuapp.com

a brief history

  • Let's start by talking a bit about django's roots.

django's 10th birthday

  • django was open sourced in 2005, 10 years ago
  • it's aged remarkably well

django is not a cms

(but it was built for one)

  • django was conceived as a CMS for Lawrence Journal-World
  • eventually they decided to split the codebase in 2, license the CMS bits, and open source the more generic web framework underneath.
  • So django has its roots deep in journalism
  • contrib belies those roots (admin, content types, localflavor)

"perfectionists with deadlines"

  • Django's slogan is "perfectionists with deadlines"
  • This gives us an idea of the the purpose of Django, the motivation for the project that has dictated its trajectory
  • most of django's strengths and weaknesses can be summed up in this one phrase

the web

2005-2015

  • While Django's core architecture has remained the same, the web is a very different place than it was 10 years ago.

we've moved from this

  • Remember the days when you could describe your stack with an acronym?
  • 1 data store, usually relational
  • request/response cycle ecapsulated all business logic
  • server-side views responsible for all content rendering
  • this is the web django was born out of, the web whose problems it was intended to solve
  • so we've moved from this ...

to this

er, this

  • A single service is potentially comprised of many processes
  • Services (mostly) talk HTTP to each other
  • Pubsub (usually via redis) allows efficient 1:many communication between services
  • MOST IMPORTANTLY: the web client is now just another service, a consumer of public services published by the server

expectations

web "site" 🆚 "app"

  • over the past decade, expectations have changed dramatically
  • If your site looks like an application, users expect it to act like one
  • Fallacies of distributed computing mean nothing to users.
  • responsiveness is now an expectation, and sever-side mvc doesn't cut it

django's

strengths

  • As I said, Django has aged well, and it still brings a lot to the table for developing modern web apps

python

  • python is probably django's biggest strength
  • libraries are the lifeblood of a language, and the python community has a tremendous bredth and depth of libraries
  • plus, we all have a fondness for the language, otherwise we wouldn't be here

"perfectionists with deadlines"

  • I mentioned that most of Django's strengths and weaknesses stem from this one phrase
  • decisions made with this in mind mean django is still an awesome tool for getting stuff done

orm & migrations

  • Some people bash django's orm as not complete or expressive enough, but it's still my favorite
  • Now that migrations are built in, it's a tremendous battery included that sets the foundation for other productive tools

from django.contrib import admin
  • yesterday morning Ola gave an entire talk about how powerful the admin is for getting stuff done
  • nobody wants to spend their time writing an admin from scratch, so it's exactly the kind of feature that makes django valuable

django rest framework

  • super quick to get up and running with basic CRUD actions for resources based on orm models

celery

  • every non-trivial web application needs an asynchronous work queue
  • celery is a best in class tool, a huge advantage to putting core business logic in python

django's

weaknesses

  • but for all those strengths, django is of course not without its weaknesses

c10k

  • The c10k problem has plagued django for years
  • (c10k shorthand for 10,000 concurrent connections)
  • most evident in long-polling and websocket apps
  • python, at least python 2, wasn't built to be good at massive concurrency
  • solutions do exist, but either at the expense of library support or by monkeypatching, which can have some weird and subtle edge case behavior
  • Python, at least python + django, is just not the right tool for this job
  • node.js and go were built with concurrency in mind

js client integration

  • As we move toward richer js clients for our web apps, we've developed a suite of tools to help
  • But Most of those tools also exist within the js community, js being the de facto language in the browser
  • We don't get the full benefit of these tools without js on the server

example problems

  • let's look at a few example problems and how we might solve them using a multi-platform web architecture

push to web clients

  • Lots of applications want to be able to push data to web clients. Django still doesn't have a great solution.

django solution

  • Long-polling. Ties up web workers, will DDOS busy sites.
  • Some gevent monstrosity. Please, just don't.

polyglot solution

  • unix pipes: websocketd
  • pure go: built-in websocket package
  • js: socket.io

async task results

  • Let's say your client calls an API endpoint which launches an async task, but the client needs to know the result of the task before it can reasonably continue.
  • These problems commonly surface in a "waiting" UI state. (Think travel search engines like Hipmunk.)
  • How do you solve this problem?

django solution

  • Include task ids in endpoints which launch async tasks
  • Expose an API endpoint which takes a task id and responds with the task state and result
  • setInterval in the client to poll for the task result

polyglot solution

  • Include task ids in endpoints which launch async tasks
  • Client opens a websocket to a server which acts as a bridge to redis pubsub
  • Allow clients to subscribe to tasks using task id as a pubsub channel name

server side js rendering

  • It's becoming increasingly common for javascript libraries to support server side rendering of initial state in order to minimize time to usable page.
  • This cannot happen without js on the sever.

django solution

¯\_(ツ)_/¯

subprocess.call(['node', 'render.js'])

  • Subprocess to node?
  • Straw man: slow, still running node
  • I think Eric Florenzano actually tried doing this at some point and gave up because it was so slow

polyglot solution

React.renderToString(BaseElement)

  • Depending on how you handle setting element state, there's a bit more to it than this, but that's the gist
  • Use CORS to serve your client app from a different domain than your django api.
  • Alternatively, have node proxy api calls back to django

shared authentication

  • As soon as you have clients accessing more than 1 service directly, you need a shared authentication mechanism
  • On web clients, there are 2 stateful mechanisms: local storage and cookies

django.contrib.auth

  • If you use django.contrib.auth, make sure you issue the cookie on a domain that will be sent with requests to each public service
  • One benefit if you use the admin, you won't have to log into it separately

access token

  • The alternative is to store a 2-legged oauth token in local storage and append it to requests to public services from the client
  • It's worth noting that in both of these scenarios, django will need to serve an auth page (either to provide a session cookie or an access token)
  • You can also use local storage, but then there's no way to take advantage of server side rendering

authentication service

  • If you don't like the idea of delegating auth to a public service, you can create a dedicated private authentication service and delegate to it from all public services

conclusions

say no to full stack python

  • I know this was a popular sentiment a few years ago. I think it shows a lack of appreciation for the bredth of tools available to us as web developers.
  • Right tool for the job means there are some jobs python is just not the right tool for

http is your friend

(when it's not, pubsub is)

  • All of the web services you build know how to speak and listen in http. Take advantage of that.
  • When 1:1 communication between services won't do, pubsub is a great tool.

web browsers are service consumers

  • When you embrace the web browser as nothing more than a consumer of your public services, then you're free to think of much more appropriate application architectures for moden web apps.

Heroku is hiring

and we have employees all over the world

heroku.com/careers

Questions?