Upgrade to Pro — share decks privately, control downloads, hide ads and more …

HTTP for Great Good

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Matt Robenolt Matt Robenolt
September 05, 2013

HTTP for Great Good

Scaling Django with HTTP

DjangoCon US 2013

http://www.youtube.com/watch?v=HAjOQ09I1UY

Avatar for Matt Robenolt

Matt Robenolt

September 05, 2013
Tweet

More Decks by Matt Robenolt

Other Decks in Programming

Transcript

  1. > GET / HTTP/1.1 > User-Agent: curl/7.24.0 > Host: disqus.com

    > Accept: */* > < HTTP/1.1 200 OK < Server: nginx < Date: Fri, 30 Aug 2013 06:38:37 GMT < Content-Type: text/html; charset=utf-8 < Content-Length: 10453 < Last-Modified: Fri, 30 Aug 2013 00:32:14 GMT < Vary: Accept-Encoding < Expires: Fri, 30 Aug 2013 06:38:36 GMT < Cache-Control: no-cache, must-revalidate
  2. > GET / HTTP/1.1 > User-Agent: curl/7.24.0 > Host: disqus.com

    > Accept: */* > < HTTP/1.1 200 OK < Server: nginx < Date: Fri, 30 Aug 2013 06:38:37 GMT < Content-Type: text/html; charset=utf-8 < Content-Length: 10453 < Last-Modified: Fri, 30 Aug 2013 00:32:14 GMT < Vary: Accept-Encoding < Expires: Fri, 30 Aug 2013 06:38:36 GMT < Cache-Control: no-cache, must-revalidate Request
  3. > GET / HTTP/1.1 > User-Agent: curl/7.24.0 > Host: disqus.com

    > Accept: */* > < HTTP/1.1 200 OK < Server: nginx < Date: Fri, 30 Aug 2013 06:38:37 GMT < Content-Type: text/html; charset=utf-8 < Content-Length: 10453 < Last-Modified: Fri, 30 Aug 2013 00:32:14 GMT < Vary: Accept-Encoding < Expires: Fri, 30 Aug 2013 06:38:36 GMT < Cache-Control: no-cache, must-revalidate Method
  4. > GET / HTTP/1.1 > User-Agent: curl/7.24.0 > Host: disqus.com

    > Accept: */* > < HTTP/1.1 200 OK < Server: nginx < Date: Fri, 30 Aug 2013 06:38:37 GMT < Content-Type: text/html; charset=utf-8 < Content-Length: 10453 < Last-Modified: Fri, 30 Aug 2013 00:32:14 GMT < Vary: Accept-Encoding < Expires: Fri, 30 Aug 2013 06:38:36 GMT < Cache-Control: no-cache, must-revalidate Path
  5. > GET / HTTP/1.1 > User-Agent: curl/7.24.0 > Host: disqus.com

    > Accept: */* > < HTTP/1.1 200 OK < Server: nginx < Date: Fri, 30 Aug 2013 06:38:37 GMT < Content-Type: text/html; charset=utf-8 < Content-Length: 10453 < Last-Modified: Fri, 30 Aug 2013 00:32:14 GMT < Vary: Accept-Encoding < Expires: Fri, 30 Aug 2013 06:38:36 GMT < Cache-Control: no-cache, must-revalidate Version
  6. > GET / HTTP/1.1 > User-Agent: curl/7.24.0 > Host: disqus.com

    > Accept: */* > < HTTP/1.1 200 OK < Server: nginx < Date: Fri, 30 Aug 2013 06:38:37 GMT < Content-Type: text/html; charset=utf-8 < Content-Length: 10453 < Last-Modified: Fri, 30 Aug 2013 00:32:14 GMT < Vary: Accept-Encoding < Expires: Fri, 30 Aug 2013 06:38:36 GMT < Cache-Control: no-cache, must-revalidate Headers
  7. > GET / HTTP/1.1 > User-Agent: curl/7.24.0 > Host: disqus.com

    > Accept: */* > < HTTP/1.1 200 OK < Server: nginx < Date: Fri, 30 Aug 2013 06:38:37 GMT < Content-Type: text/html; charset=utf-8 < Content-Length: 10453 < Last-Modified: Fri, 30 Aug 2013 00:32:14 GMT < Vary: Accept-Encoding < Expires: Fri, 30 Aug 2013 06:38:36 GMT < Cache-Control: no-cache, must-revalidate Response
  8. > GET / HTTP/1.1 > User-Agent: curl/7.24.0 > Host: disqus.com

    > Accept: */* > < HTTP/1.1 200 OK < Server: nginx < Date: Fri, 30 Aug 2013 06:38:37 GMT < Content-Type: text/html; charset=utf-8 < Content-Length: 10453 < Last-Modified: Fri, 30 Aug 2013 00:32:14 GMT < Vary: Accept-Encoding < Expires: Fri, 30 Aug 2013 06:38:36 GMT < Cache-Control: no-cache, must-revalidate Status
  9. > GET / HTTP/1.1 > User-Agent: curl/7.24.0 > Host: disqus.com

    > Accept: */* > < HTTP/1.1 200 OK < Server: nginx < Date: Fri, 30 Aug 2013 06:38:37 GMT < Content-Type: text/html; charset=utf-8 < Content-Length: 10453 < Last-Modified: Fri, 30 Aug 2013 00:32:14 GMT < Vary: Accept-Encoding < Expires: Fri, 30 Aug 2013 06:38:36 GMT < Cache-Control: no-cache, must-revalidate Headers
  10. > GET / HTTP/1.1 > User-Agent: curl/7.24.0 > Host: disqus.com

    > Accept: */* > < HTTP/1.1 200 OK < Server: nginx < Date: Fri, 30 Aug 2013 06:38:37 GMT < Content-Type: text/html; charset=utf-8 < Content-Length: 10453 < Last-Modified: Fri, 30 Aug 2013 00:32:14 GMT < Vary: Accept-Encoding < Expires: Fri, 30 Aug 2013 06:38:36 GMT < Cache-Control: no-cache, must-revalidate Hmm. What can we do with this information?
  11. > GET / HTTP/1.1 > User-Agent: curl/7.24.0 > Host: disqus.com

    > Accept: */* > If-Modified-Since: Fri, 30 Aug 2013 00:32:14 GMT > < HTTP/1.1 304 Not Modified < Server: nginx < Date: Fri, 30 Aug 2013 18:05:38 GMT < Last-Modified: Fri, 30 Aug 2013 00:32:14 GMT < Vary: Accept-Encoding < Expires: Fri, 30 Aug 2013 18:05:37 GMT < Cache-Control: no-cache, must-revalidate
  12. $ curl -v a.disquscdn.com/dotcom/d-6203c8f/css/ disqus-web/pages/home.css < HTTP/1.1 200 OK <

    Server: nginx < Content-Type: text/css; charset=utf-8 < Last-Modified: Fri, 16 Aug 2013 20:31:05 GMT < Expires: Sun, 15 Sep 2013 20:34:21 GMT < Cache-Control: max-age=2592000 < Content-Length: 30749 < Date: Sun, 18 Aug 2013 03:23:37 GMT < Via: 1.1 varnish < Age: 110956 < Connection: keep-alive < Vary: Accept-Encoding
  13. $ curl -v a.disquscdn.com/dotcom/d-6203c8f/css/ disqus-web/pages/home.css < HTTP/1.1 200 OK <

    Server: nginx < Content-Type: text/css; charset=utf-8 < Last-Modified: Fri, 16 Aug 2013 20:31:05 GMT < Expires: Sun, 15 Sep 2013 20:34:21 GMT < Cache-Control: max-age=2592000 < Content-Length: 30749 < Date: Sun, 18 Aug 2013 03:23:37 GMT < Via: 1.1 varnish < Age: 110956 < Connection: keep-alive < Vary: Accept-Encoding 30 days in the future.
  14. Last-Modified def lol(request): response = render(request, 'lol.html') response['Last-Modified'] = \

    'Fri, 16 Aug 2013 20:31:05 GMT' return response * don’t do this.
  15. Last-Modified from django.views.decorators.http import \ last_modified def post_last_modified(request, slug): return

    Post.objects.get(slug=slug).modified @last_modified(post_last_modified) def blog_post_detail(request, slug): # Your view
  16. tl;dr Its sole purpose in life is to be a

    cache, so it’s really fast. Internet
  17. $ httperf --server 127.0.0.1 --port 8000 -- uri /hello/ --rate

    150 --num-conn 10 --num-call 500 --hog Request rate: 369.6 req/s (2.7 ms/req) Django + gunicorn * on my MacBook Air
  18. $ httperf --server 127.0.0.1 --port 8888 -- uri /hello/ --rate

    150 --num-conn 10 --num-call 10000 --hog Request rate: 15633.4 req/s (0.1 ms/req) Varnish * on my MacBook Air
  19. $ curl -vd "username=foo&password=bar" https:// disqus.com/profile/login/ > POST /profile/login/ HTTP/1.1

    > User-Agent: curl/7.24.0 > Host: disqus.com > < HTTP/1.1 302 FOUND < Server: nginx < Date: Fri, 30 Aug 2013 21:34:36 GMT < Vary: Cookie < Set-Cookie: sessionid=f7aa9598-11bb-11e3-9eb1-003048d9a288; Domain=.disqus.com; expires=Sun, 29-Sep-2013 21:34:36 GMT; httponly; Max-Age=2592000; Path=/
  20. $ curl -vd "username=foo&password=bar" https:// disqus.com/profile/login/ > POST /profile/login/ HTTP/1.1

    > User-Agent: curl/7.24.0 > Host: disqus.com > < HTTP/1.1 302 FOUND < Server: nginx < Date: Fri, 30 Aug 2013 21:34:36 GMT < Vary: Cookie < Set-Cookie: sessionid=f7aa9598-11bb-11e3-9eb1-003048d9a288; Domain=.disqus.com; expires=Sun, 29-Sep-2013 21:34:36 GMT; httponly; Max-Age=2592000; Path=/ Set-Cookie
  21. $ curl -vd "username=foo&password=bar" https:// disqus.com/profile/login/ > POST /profile/login/ HTTP/1.1

    > User-Agent: curl/7.24.0 > Host: disqus.com > < HTTP/1.1 302 FOUND < Server: nginx < Date: Fri, 30 Aug 2013 21:34:36 GMT < Vary: Cookie < Set-Cookie: sessionid=f7aa9598-11bb-11e3-9eb1-003048d9a288; Domain=.disqus.com; expires=Sun, 29-Sep-2013 21:34:36 GMT; httponly; Max-Age=2592000; Path=/ Session Id
  22. sub vcl_recv { // These urls can be stripped of

    all // cookies since they serve the same // data for anon and auth'd user if ( req.url == "/" || req.url ~ "^/embed/comments/" ) { unset req.http.Cookie; } }