One of ways to scale Web application performance is by reducing the latency of serving an HTTP request: Making transactions short, and returning results to the client quickly, allow a Web application to serve a larger number of requests in a given time period. Indeed, Web application performance tuning can lead to requests being serviced with short variations in latency from request to request.
At the same time, as HTTP is put to new uses, especially as a transport protocol for RESTful Web services, it is increasingly used in situations where request latency is diverse: Some requests may be very quick to serve, while other requests may take several minutes to fulfill. One example of such applications is the remote management of server farms or clusters, such as Amazon's EC2 or Sun's nascent Project Kenai effort.
In a recent blog post, Slow REST, Sun's Tim Bray outlines some of the design tradeoffs when dealing with requests of varying latency characteristics in a RESTful Web application, and especially when dealing with slow requests:
In a RESTful context, how do you handle state-changing operations (POST, PUT, DELETE) which have substantial and unpredictable latency?
What we’ve learned, from work with our own back-end based on the Q-layer technology and with some other back-ends, is that Cloud operations are by and large not very fast; and that the latencies show up in weird places. Here’s an example: in our own implementation, creating a Virtual Machine from a template or by copying another VM instance is very snappy. But weirdly, connecting a network (public or private) to a VM can sometimes be extremely slow. Go check out other implementations like EC2 and you see a similar unpredictable-latency narrative.
Bray outlines several possible solutions to this problem, such as the following proposal:
For any and all PUT/POST/DELETE operations, we return “202 In progress” and a new “Status” resource, which contains a 0-to-100 progress indicator, a target_uri for whatever’s being operated on, an op to identify the operation, and, when progress reaches 100, status and message fields to tell how the operation came out. The idea is that this is designed to give a hook that implementors can make cheap to poll.
Another design alternative is based on Comet:
We also thought about a Comet style implementation where we keep the HTTP channel open, and that can be made clean but support for it in popular libraries is less than ubiquitous.
Another possibility Bray outlines uses "Web hooks":
My personal favorite idea was to use “Web hooks”, i.e. the client sends a URI along with the request and the server POSTs back to it when the operation is complete. But every time I started talking about it I ran into a brick wall because it probably doesn’t work for a client behind a firewall, which is where most of them will be...
Do you encounter high-latency HTTP requests in your applications? If so, what solutions have worked for you?
> One of ways to scale Web application performance is by > reducing the latency of serving an HTTP request: Making > transactions short, and returning results to the client > quickly, allow a Web application to serve a larger number > of requests in a given time period.
The number of requests per second served is not related to the length of processing per request except in a single-threaded system. Correlation does not mean causation.
Nonetheless, it is true that optimizing an application will generally shorten the latency per request AND increase the total number of requests per second, which is probably what you meant. In other words, a linear improvement in performance often generates a corresponding improvement in scale (but not scalability).
In a REST design, why would you need to have a separate 'status' resource? Returning 202 for the PUT/POST/DELETE makes sense but then to check on the status, wouldn't you do a GET or HEAD on the resource you tried to create, update or delete?
> In a REST design, why would you need to have a separate > 'status' resource? Returning 202 for the PUT/POST/DELETE > makes sense but then to check on the status, wouldn't you > do a GET or HEAD on the resource you tried to create, > update or delete?
That may only tell you that an update has completed and not whether your update has happened.
> > In a REST design, why would you need to have a separate > > 'status' resource? Returning 202 for the > PUT/POST/DELETE > > makes sense but then to check on the status, wouldn't > you > > do a GET or HEAD on the resource you tried to create, > > update or delete? > > That may only tell you that an update has completed > and not whether your update has happened.
I see. If you need to know whether your change succeeded, you have to have something to look at that uniquely identifies your transaction.
In the post he talks about checking on multiple transactions. I think it would be fine to use a query string that allowed multiple ids to be passed to a GET.
One thing I don't get is why it's often recommended to return URIs in responses. It seems to me that this makes sense for human interaction but for computers, the URIs can be easily derived and by munging information into a string, you make it harder to use it. In this case, instead of returning a URI to the status, you could create a status resource that and use a transaction ID. That would make it easy to support multiple status lookups in a single call.