> > I'm not even speaking about a specific implementation but about HTTP. > HTTP provides no way to announce that a keep-alive connection will close. > So in general it can close while you are sending a request over it. HTTP > says that when this happens, you just apply a classical back-off algorithm > and reconnect and push your request again. The problem here is that if the > connection closes just after the request reaches the server, then the server > may have started processing it, and will do it once again when the second > request arrives. If that's an idempotent request, no problem. If that's a > POST or a GET with side effects, then it's a different story. Many > applications are protected against undesired "reload" effects, because > users are humans an may very well do the mistake themselves. But not all > applications are designed that way, and if your browser still warns you > when you hit "reload" after a POST, it's precisely because of that. > > If you want to add such info to the doc, it's explained here in RFC2616, > paragraph 8.1.4 : > > A client, server, or proxy MAY close the transport connection at any > time. For example, a client might have started to send a new request > at the same time that the server has decided to close the "idle" > connection. From the server's point of view, the connection is being > closed while it was idle, but from the client's point of view, a > request is in progress. > > This means that clients, servers, and proxies MUST be able to recover > from asynchronous close events. Client software SHOULD reopen the > transport connection and retransmit the aborted sequence of requests > without user interaction so long as the request sequence is > idempotent (see section 9.1.2). Non-idempotent methods or sequences > MUST NOT be automatically retried, although user agents MAY offer a > human operator the choice of retrying the request(s). Confirmation by > user-agent software with semantic understanding of the application > MAY substitute for user confirmation. The automatic retry SHOULD NOT > be repeated if the second sequence of requests fails. > > As you can see, the rules are quite clear and strict on that matter. > However, I think that the last point may allow an intermediary with > a list of retryable URLs to retry the request once. After all, if the > site's admin configures a full list of the idempotent requests in the > load balancer, we might consider that the load balancer gets semantic > understanding of the application.
So you're specifically talking about the HTTP client retry issue? Where haproxy is now the "HTTP client" because it's rebroadcasting a client request? You'll probably flip out at this compromise, but it doesn't really make sense to pretend that the load balancer is now the client for all purposes; there's still a client at the other end of the load balancer issuing the initial request. Which means that, in perlbal, if a backend server does anything but return a 200 OK, we do a few things: - close the backend connection (not a valid keepalive connection, or can assume something is going wrong safely) - if the backend closes the connection without sending a proper response, IIRC we close drop the connection all the way through; backend to client. Then the client may decide if it wants to re-issue the request. Whether or not frontend/backend keepalives are enabled would make no difference in how the browser would've handled the situation otherwise. If haproxy didn't exist and the backend got closed, the client should open a new connection and retry, or bounce an error to the user. Dropping the connection from the LB front to back emulates this pretty effectively? However, we do special case in X-Reproxy-URL for perlbal :) It's another ugly extension, but we pass back a list of URLs which are tried in most cases. Due to mogilefs maintaining multiple copies of a file, we can always give the LB a prioritized list of ones to try, in case of overload, sudden failure, etc.

