>
> 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.

Reply via email to