Is it a good practice to cancel a HTTP request with another request? - http-request

Consider we have an HTTP server and there are many concurrent clients making HTTP requests to this server.
The responses are adequately big to be considered.
User may send requests on the trot, with different request bodies. Once a new request has been made, former requests made by same user become obsolete.
In this type of situation, looking from client aspect, that may not be an issue. However, in server-side, it will make considerable amount of CPU time steal. If there is no way to do further processing relied upon former requests that came from same users, what to do? Here are some workarounds I thought:
to make a new HTTP request from client in order to cancel the process in server-side (via different port)
checking client if incoming request is a further request (over IPv4 or MAC address, is there a popular way to conduct this?)
That being said, please let the task being done by server upon HTTP requests is nonatomic (otherwise I think it would be a maze, because as I know a block-closure passed to some dispatch authority will be executed, ultimately).
This was actually a request-response pattern question because it is not limited to use HTTP. Sadly, there was no tag named request-response.
Thank you.

Related

Can I do something similar to pipelining on HTTP 2?

Pipelining is a technique in HTTP/1.1 where multiple requests are sent at once without waiting for a response, on a keepalive connection. The responses are then returned in order by the server, without waiting for a round-trip-time between a response being sent and the next request being received.
HTTP/2 adds a feature called multiplexing, which similarly allows the client to send off multiple requests at once. In this case however, the server can send responses all at once.
Without control of the server, Can I achieve something similar to pipelining (i.e. receiving responses in order one-at-a-time without latency between responses) when using HTTP/2?
This would be useful when downloading many large files, without much available memory to buffer several partially-completed responses.
Without control of the server, Can I achieve something similar to pipelining (i.e. receiving responses in order one-at-a-time without latency between responses) when using HTTP/2?
No you cannot, unless the server cooperates (for example the server can be configured to handle requests sequentially or something similar).
As a side note, while request pipelining was allowed in HTTP/1.1, it has always been considered a bad idea and as such made irrelevant by all major implementations (i.e. browsers don't do it, servers don't really support it, etc.).
The main problem is error handling and buggy proxy servers.
HTTP/2 allows a client to set priorities on requests so that requests are processed in priority order.
However, this feature is optional and servers may not implement it, so again you need to carefully choose/configure the server in order to get the behavior you want.
If you can control a little the server side, for both HTTP/1.1 and HTTP/2, a better solution would be to ask the server for all the files in a single request, and have the server reply with a multipart response.

Are HTTP responses to the same resource returned in sequence?

Say I want to request some resource on a given domain, e.g. example.com/image.jpg.
If I do two requests to this particular resource, can I expect the first response I get back to be mappable to the first response I sent, and so on (or does this depend on client/server implementation)?
I'm asking because if I want to debug request-response pair, I necessarily need to know exactly which response belongs to which request (for timing purposes etc.). So, are there any sure-fire ways to achieve this mapping?
I'm assuming that you are talking about HTTP/1.x using persistent connections (i.e. HTTP keep-alive) when sending a new request without having the response for the previous one yet, i.e. using HTTP pipelining. In this case the order of the responses matches the order of the requests.
If you are instead talking about HTTP/2 then the situation is different because multiple requests can receive the responses in parallel inside the same TCP connection and this also means that a later requests might have received a response before earlier requests. And in which order requests to the same resource are handled by the server depends fully on the server implementation.
The same is true when the requests are done within independent TCP connections. The order might be even more unpredictable than with HTTP/2 because the requests might be handled in different threads or processes and thus the order also depends on the scheduling of these in the operating system.

Non-serial pipelined HTTP possible?

RFC 2616 section 8.1.2.2 states:
A client that supports persistent connections MAY "pipeline" its requests (i.e., send multiple requests without waiting for each response). A server MUST send its responses to those requests in the same order that the requests were received.
Serial responses are often more harm than good, since serial responses actually require the server to do more processing and negates the performance benefits gained by pipelining.
For example, if a HTTP client requests for files 1.jpg, 2.jpg, 3.jpg, 4.jpg, and 5.jpg, it doesn't matter if 3.jpg is returned before 1.jpg, or if 4.jpg is returned before 3.jpg. The client simply want the responses as soon as they are available, in any order.
How can a HTTP client gain the benefits of pipelining, and at the same time not pay for the disadvantages of response queueing?
A client can't circumvent HOL-queueing as it's part of RFC 2616. The only benefit of pipelining (in my opinion) is in extremely specific and narrow cases. Consider:
R1cost = Request A processing cost.
R2cost = Request B processing cost.
TCPcost = Cost of negotiating new TCP connection.
Using pipelining would, therefore, be viable in specific cases where:
R1cost ≥ R2cost ≤ TCPcost
How often is a request more expensive than a previous request and less expensive than negotiating a new TCP connection? Not often. I would add that Websockets are (by far) a more interesting and appropriate solution (as far as parallel back-end processing is concerned).
It can't (in HTTP/1.1). It might be in a future version of HTTP.
There is no default mechanism in the HTTP headers to identify which response would match which request. A response is known to be that to a specific request because of the order in which it's received. If you requested 1.jpg, 2.jpg, 3.jpg, 4.jpg, and 5.jpg and sent the responses in any order, you wouldn't know which one is which.
(You could implement your own markers in client and server headers, but you'd certainly not be compliant with the protocol and most implementations would not know how to deal with that. You would have to do some processing to map, which may negate the anticipated benefits of this parallel implementation too.)
The main benefits you get from the existing HTTP pipeline mechanism are:
Possible reduced communication latency. This may matter depending on your connection.
For request that require some longer server-side computation, the server could start this computation in the background, upon reception of the request, while it's sending a previous response, so as to be able to start sending the second result earlier. (This is also a form a latency, but in terms of response preparation.)
Some of these benefits can also be gained by more modern web-browser techniques, where multiple requests can be sent separately and parts of the page may be updated progressively (via AJAX).

Why can HTTP handle only one pending request per socket?

Being curious, I wonder why HTTP, by design, can only handle one pending request per socket.
I understand that this limitation is because there is no 'Id' to associate a request to its response, so the only way to match a response with its request is to send the response on the same socket that sent the request. There would be no way to match a response to its request if there was more than one pending request on the socket because we may not receive the responses in the same order requests were sent.
If the protocol had been designed to have a matching 'Id' for requests and responses, there could be multiple pending requests on only one socket. This could greatly reduce the number of socket used by internet browsers and applications using web services.
Was HTTP designed like this for simplicity even if it's less efficient or am I missing something and this is the best approach?
Thanks.
Not true. Read about HTTP1.1 pipelining. Apache implements it and Firefox implements it. Although Firefox disables it by default.
To turn it on in Firefox use about:config and write 'pipelining' in the filter.
see: http://www.mozilla.org/projects/netlib/http/pipelining-faq.html
It's basically for simplicity; various proposals have been made over the years that multiplex on the same connection (e.g. SPDY) but none have taken off yet.
One problem with sending multiple requests on a single socket is that it would cause inefficient queuing.
For instance, lets say you are in a store and there are 2 cashiers, and 10 people waiting to be checked out. The ideal way to make the line is to have a single queue of 10 people and the next person in line goes to a cashier when they become available. However, if you sent all the requests at once you would probably send 5 people to cashier A and 5 to cashier B. However, what if you sent the 5 people with the largest shopping carts to the same cashier? That's bad queuing and what could happen if you queued a bunch of requests on a single socket.
NOTE: I'm not saying that you couldn't use queuing well, but it keeps it simple to do it right if there is no queuing on a single socket.
There are a few concidertaions I would review.
The first is related to the nature of TCP itself. TCP suffers from 'head-of-line' blocking issue where there can only be a single outstanding (unacknowledged) request (connection/TCP level) in flight. Given traditional latencies this can be a problem from a load time user experience perspective compared to results of parallel connection scheme browsers employ today. The higher the latency of the link the larger the impact of this fundemental limitation.
There is also a concurrency issue in that sometimes you really want to load multiple resources incrementally / in parallel. Back in the day one of the greatest features mozilla had over mosaic was that it would load images and objects incrementally so you could begin to see what was going on and use a resource without having to wait for it to load. With fewer connections there is a risk in that for example loading a large image on page before a style sheet can be catastrophic from an experience point of view. Expecting some kind of mitigating intelligence or explicit configuration to optimally order requests may not be a realistic or ideal solution.
There are proposals such as HTTP over SCTP that will more or less totally correct the issue you raise at the transport level.
Also realize that HTTP doesn't necessarily mandate a Content-Length header to serve data. Even if each HTTP response was ID'd, how would you manage streaming binary content with no content length (HTTP/1.0 style)? or if the client sent the Connection: close header to have the client close due to non-known lengths?
To manage this you would have to HTTP chunk (already present) in multiplex (I don't think anyone implements this) and add some non-trivial work to many programs.

Connecting http request/response model with asynchronous queue

What's a good way to connect the synchronous http request/response model with an asynchronous queue based model?
When the user's HTTP request comes it generates a work request that goes onto a queue (beanstalkd in this case). One of the workers picks up the request, does the work, and prepares a response.
The queue model is not request/response - there are only requests, not responses. So the question is, how best do we get the response back into the world of HTTP and back to the user?
Ideas:
Beanstalkd supports light weight topics or queues (they call them tubes). We could create a tube for each request, have the worker create a message on that tube, and have the http process sit and wait on the tube for the response. Don't particularly like this one since it has apache processes sitting around taking memory.
Have the http client poll for the response. The user's initial HTTP request kicks off the job on the queue and returns immediately. The client (the user's browser) polls periodically for a response. On the backend the worker puts its response into memcached, and we connect nginx to memcached so the polling is light weight.
Use Comet. Similar to the second option, but with fancier http communication to avoid polling.
I'm leaning towards 2 since it's easy and well know (I haven't used comet yet). I'm guessing there's probably also a much better obvious model I haven't thought of. What do you think?
Here's how to implement request-response efficiently on JMS which might be helpful (though Java/JMS centric). The general idea is to create a temporary queue per client/thread then use correlationIDs to correlate requests to replies etc.
Polling is the simple solution; comet is the more efficient solution. You've got it nailed :)
I personally love comet (although I'm biased, since I helped write WebSync), it nicely lets your clients subscribe to a channel and get the message when your server process is ready. Works like a champ.
I'm looking to implement a Beanstalkd and memcached system to run a number of processes following a request - in this case, looking up information when a user logs in (the number of messages a user has waiting for example). The info is stored in Memcached and then read back on the next page load.
Without knowing a little more about what tasks you are doing though, it's not so easy to say what needs to be done, or how. Option #2 is however the simplest, and that may be all you need - depending on what you are pushing back into the workers.

Resources