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

HTTP for Great Good

Matt Robenolt
September 05, 2013

HTTP for Great Good

Scaling Django with HTTP

DjangoCon US 2013

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

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; } }