Re: The deep difference between request/response and fire-and-forget

Hello, 

I have some comments regarding a fire-and-forget implementation over
HTTP.

HTTP/1.1 as defined by RFC 2616 doesn't leave any doubt in my mind that
every valid HTTP transaction requires both a request and response.
Response entites can be zero length of course, but a minimal response
header must be produced. It seems inappropriate to me to create a higher
level MEP recommendation that encourages non-compliant use of a lower
layer protocol. 

>>>
>From 2616
1.4 Overall Operation

   The HTTP protocol is a request/response protocol. A client sends a
   request to the server in the form of a request method, URI, and
   protocol version, followed by a MIME-like message containing request
   modifiers, client information, and possible body content over a
   connection with a server. The server responds with a status line,
   including the message's protocol version and a success or error code,
   followed by a MIME-like message containing server information, entity
   metainformation, and possible entity-body content. 
>>>

Any HTTP server that does not produce a response is a non-compliant
server. Any HTTP client that does not consume the response will generate
a TCP RST packet back towards the server. This is an error condition at
the TCP level. Again, it seems inappropriate to me to create a higher
level MEP recommendation that encourages implementations that would
create TCP layer errors for the base "working" case.

It has been suggested to me that servers of this type won't create
responses and clients won't expect them - so you won't get the impedance
mismatch and the RST generated. However, what that scenario describes is
a fine application level protocol - but it isn't HTTP.

My sniff test for "is it HTTP?" is "does it run through an unmodified
HTTP Proxy?". That would seem to be one of the major advantages of
specing this over HTTP afterall. This scenario will definitely throw
errors in the proxy on the server-facing side (server hangup before
expected response) which will result in the proxy generating a 500 based
response on the client-facing side which will in turn generate a TCP RST
when it gets to the client. At this point system monitoring software
both on the proxy server and network levels is firing off alarms all
over the place. You might even get the client's address automatically
blocked if this is done repeatedly and systematically. yum!

Additionally, as has already been noted this "close after send" approach
means you can't use persistent connections. Do not underestimate the
relevance of this choice. The standardization of HTTP/1.1 was driven
largely by the need to introduce that single feature (which of course a
variant of got added defacto to HTTP/1.0 in parallel to the HTTP/1.1
process as that was going on because the standardization process was
long.). Making a recommendation in 2006 that ignores this lesson learned
in 1996 is like designing a transport protocol today without congestion
control - a poor decision. 

I think the appropriate HTTP FNF binding is to spec that the response is
ignored above the HTTP layer. The preferred implementation would be a
202 response code with a 0 length body or maybe a 204 response code
(which has no body by definition). This preserves the potential to use
HTTP proxies, pipelining, persistent connections, 'elephant-like' TCP
flows that have much better congestion control properties, etc.. etc..
There are lot of implied benefits to doing this.

As to the question of whether this qualifies as FNF - I think it is 97%
the same as the client-close-after-send model. If you think that model
is FNF, then this is basically just as good. Afterall, the client host
isn't really forgetting anything after the application says close() - it
still has a large amount of state stored in the TCP stack which it
slowly (at least in comparison to how fast the CPU could deal with them)
parcels out over time in response to acknowledgments coming back from
the server - perhaps even retransmitting ones it deems lost. That's
hardly pure fire and forget - and the system will scale as a stateful
one would scale - not as a true stateless fnf one would. I don't think
adding a touch more logic into the final state (reading the http
response) really changes the fundamentals of this. 

What really makes it FNF in my mind is that the server can generate that
response as soon as it has received the message. It doesn't need to wait
for processing/forwarding/whatever to wrapup the transport session. 

-Patrick

Received on Tuesday, 24 January 2006 17:11:31 UTC