|Brian McCallister on 27 Jul 2006 17:31:54 -0000|
On Jul 26, 2006, at 9:51 PM, Aaron Blohowiak wrote:
Can you tell us more about the http keepalive bit?
# A design decision was made to force the client to not pipeline requests. HTTP/1.1
# pipelining really kills the performance due to how it has to be handled and how
# unclear the standard is. To fix this the HttpResponse gives a "Connection: close"
# header which forces the client to close right away. The bonus for this is that it
# gives a pretty nice speed boost to most clients since they can close their connection
Interestingly, the whole HTTP status line and first couple headers are a constant, frozen, string -- short of patching mongrel or using your own TCP connection handling in your Handler, it *will* close the connection a la HTTP 1.0.
I think Zed is an amazing (really, really amazing) programmer. I presume something in the design of Mongrel makes it tough to implement keep-alives. Saying that they are poorly specced, or hurt performance for the protocol or client is, umh, wrong, however. I have a hunch that the reason comes back to the choice to actually build an HTTP grammar with the ragel FSM compiler and making the FSM clean across requests on a single connection has proven difficult.
If you think of mongrel as being designed to run fairly big sites with one dynamic element and mostly static elements, and then this decision works. Basically you have mongrel serve the dynamic page (possibly from rails) and go ahead and close the connection because you *know* the same server isn't going to receive a followup resource request immediately, those are handled by servers optimized for that, or by a content distribution network. In this case the Connection:close on the initial request makes sense, the browser is going to be opening additional connections to a different host (or hosts for a CDN, or round-robined static setup) which will pipeline requests for resources.
Yahoo! is a good example of this, we see the initial response headers for the front page, made against www.yahoo.com, return the "Connection: close" header:
HTTP/1.x 200 OK Date: Thu, 27 Jul 2006 16:53:56 GMT P3P: policyref="http://p3p.yahoo.com/w3c/p3p.xml", ... Vary: User-Agent Cache-Control: private Set-Cookie: FPB=3r0o6jmqh12chrt4; expires=Thu, 01 .... Set-Cookie: D=_ylh=X3oDMTFmdWZsNGY1BF9TAzI ... Connection: close Transfer-Encoding: chunked Content-Type: text/html Content-Encoding: gzip
but subsequent image loads are made against their CDN, with hosts such as us.i1.yimg.com, and do pipeline:
HTTP/1.x 200 OK Last-Modified: Thu, 11 May 2006 20:46:13 GMT Accept-Ranges: bytes Content-Length: 7857 Content-Type: image/png Cache-Control: max-age=2345779 Date: Thu, 27 Jul 2006 16:53:56 GMT Connection: keep-alive Expires: Thu, 12 May 2016 20:29:52 GMT
HTTP/1.x 200 OK Last-Modified: Wed, 27 Jul 2005 00:18:07 GMT Etag: "29990d3-122-42e6d2bf" Accept-Ranges: bytes Content-Length: 290 Content-Type: image/gif Cache-Control: max-age=979924 Date: Thu, 27 Jul 2006 16:53:56 GMT Connection: keep-alive Expires: Sat, 01 Aug 2015 00:46:23 GMT
This works great for people who need it and have the expertise to use it, but doesn't scale down as well for folks that don't have or need an array of specialized web servers and configs -- which would be most folks. You can use a vanilla mod_proxy configuration and at least put apache in front to help, but then you still need to have pretty good apache config know-how to keep it to only one or two handshakes for the initial request and resource requests and not a get a big performance hit when used over the internet which won't be apparent when doing local, or even same-lan based development and testing.
Mongrel rocks as a highly specialized tool, but the choice to flat out disable pipelining requires understanding HTTP reasonably well in order to not shoot yourself in the foot when it goes to production instead of a local network.
Anyway, sorry I got up on the soap box, hopefully ya'll don't mind too much :-)
ps: If I recall, Zed wrote the SCGI rails runner, not mod_scgi which, I think, Neil Schemenauer wrote for python of all things.