Stateful Web Services and WSRP
I just came across
this
long thread on stateful vs. stateless web services. The main question
discussed in this thread was whether stateful web services can scale.
I think the answer is “it depends�?. It depends on how much
state is maintained by the service (in memory)
vs. how much state is transferred to the client. It depends on whether the
client is pinned to the service instance holding the state or not. It
depends on whether the client can effortlessly hold on to the state for the
required duration.
Since I work with WSRP at my day job, I would like to examine the state
management issues with WSRP. In this post, look for italicized text
for performance and scalability related observations. If you are looking for
more explanation on some of the terms used below,
WSRP Primer is the best place to look for more information.
Cookies
The markup interface of WSRP specifies an operation called initCookie.
The purpose of this operation is to let a Producer send some cookies back to
the Consumer. The Consumer is required to supply these cookies with future
requests (over HTTP binding, of course) till they expire naturally. This
operation is borrowed from HTTP. The primary use case for this operation is
to allow Producers to set any cookies necessary for load-balancing and
failover. Consumer will have to maintain these cookies at least for the
duration of the user’s session on the Consumer.
(Looking back, I wonder if it was a good choice in the first place to add
this operation to the protocol. This operation does assume HTTP at the
transport level. Besides that, any token necessary for load balancing and
failover can be exchanged within the protocol.)
When the Consumer sends expired cookies or drops the cookies, Producer
returns an InvalidCookie fault. In response to this, the
Consumer will have to send an initCookie request, capture
the returned cookies, and then resubmit whatever operation caused the fault.
Producer/Consumer implementations will also have to guard against
repeated fail/retry, and make sure retries are safe (idempotency
is good).
Sessions
This is another concept borrowed from HTTP. When a user interacts with a
portlet via a Consumer, the Producer hosting the portlet can initialize a
session, and return its ID to the Consumer. The Consumer will then have to
return it with future requests so that the Producer can maintain a user
session, which means the Consumer will have to maintain this session ID
for the duration of the user’s session on the Consumer.
When the Consumer sends an expired session ID, Producer returns an fault. In response to this, the Consumer will have to
InvalidSession
drop the current init cookies, drop the current session ID, send an
initCookie request, capture the returned cookies, and then resubmit whatever
operation caused the fault.
An interesting consequence of sessions with WSRP is that, there can be "n +
1" sessions for one user accessing a Consumer with "n" portlets on a
Producer; with one session on the Consumer, and "n" sessions on the
Producer. These sessions can keep the replication layer busy on the
Producer.
Navigational State
Navigational state is one of the clever pieces in WSRP. Producers can use
this to push state to Consumers, and avoid/minimize session state on the
Producer side. The protocol is designed such that, at least in theory,
Consumers can also push this state into URLs, and let the browser maintain
the state. Does this improve scalability? I think "it depends". If the
navigational state is short, Consumers can try to embed this state into
URLs. But given URL length restrictions in browsers, Consumer may not
always be able to push this state into URLs. Another thing to consider
is cost of encoding state into navigational state.
Registration State
Producers can even push state of a Consumer registration to Consumers, so
that they don’t have to persist this state (see
Client-Stateless-Server Hierarchical Style). But this approach can
negatively impact scalability if the registration state is large.
Portlet State
Similar to registration state, Producers can also push long-term state of
portlets to Consumers. But again, portlet state can be large, and
transporting it across the wire can affect scalability.
State is not necessarily bad. Scalability can not be judged by state alone.
As we make choices in software design and implementation, it is important to
treat state as a necessary evil.



No comments yet.