Wednesday, March 4, 2009

Stateless

The term "stateless" has been discussed a lot lately. It is about the stateless constraint imposed on the REST architectural style. In the famous dissertation of Fielding, section 5 (Representation Style Transfer), the stateless constraint stated as follows.

"communication must be stateless in nature, as in the client-stateless-server (CSS) style of Section 3.4.3 (Figure 5-3), such that each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client."
(http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)

And the benefits of statelessness "induces the properties of visibility, reliability, and scalability".

The benefits are not difficult to understand. But some consequences are also derived from the nature of statelessness.

One of the consequences of the stateless behavior is the "transient" server resource availability, such as a transaction. How can this stateless design be implemented such that it can fulfill the "web scalable" requirement? As some said, "just add another server and the system is automatically scaled".

For example, if a RESTful application client is in the middle of a transaction on server (A). But the next request was "load balanced" by a less-intelligent load-balancer to a different server (B). To achieve the claimed (stateless) benefit, the transaction processing must proceed as if the request were on the original server (A).

The previous article "Meet The Web, Part 2 (with transaction)" is a typical RESTful transaction scenario to face this challenge.

There are solutions to address the stateless implementation issues.

For example, the following are some possible solutions to handle the stateless nature for a "transient" resource (such as a transaction).
  1. Client includes accumulative information (including previous requests related to the transaction) in the request message.
  2. Mirror a resource state (such as a transaction) in all servers.
  3. Introduce a new (shared) service layer to handle the resource. Such as a transaction service, on a separate machine, to handle transactions. When a transactional request is received, the request is forwarded to the transaction service layer.
  4. Use an intelligent load-balancer.
There are other solutions not mentioned. So the issue is not due to "lack of solution" to implement a stateless behavior. The challenge is that, if attempts to change the existing system to fulfill the constraint, it takes efforts to redesign and rearrange the "guts" in the current design and implementation. And it also takes time to get adjusted to the new design style.

To provide a stateless solution for the case in "Meet The Web, Part 2 (with transaction)", the solution #4 above would probably be a logical choice. All transactional service requests are delegated to the shared transaction service layer. This would meet the stateless constraint challenge for the transient server resource availability. But changes would be required to rearrange the server/service implementation and move some portion of implementation to a separate location (transaction service layer).

When software development model moved from component (such as beans) to service (such as web services), the thinking and design patterns are also evolving. The concept of "software as a service" (SaaS) seems to fit into the RESTful architectural style nicely. And statelessness may likely become a popular "design pattern" for the coming generation of web services.

There are disadvantages about the stateless design as Fielding pointed out below. Especially the performance impact may not be easy to address. But that's the fun part for the fine engineers to resolve.

"Like most architectural choices, the stateless constraint reflects a design trade-off. The disadvantage is that it may decrease network performance by increasing the repetitive data (per-interaction overhead) sent in a series of requests, since that data cannot be left on the server in a shared context. In addition, placing the application state on the client-side reduces the server's control over consistent application behavior, since the application becomes dependent on the correct implementation of semantics across multiple client versions."

No comments:

Post a Comment