RE: Why web-style session state management doesn't work for web services, methinks

I think this is basically a correct analysis.  Some comments:

1)  Shared data makes sense to put on the server, usually.  For example,
inventory counts.  So your comments apply mostly to client-specific
data.
2)  There *are* good reasons for storing client-specific state on a
central machine referenced via token.  For example, a site may want to
make sure that shopping cart data gets saved even if the user's machine
crashes.  Or a music site may want to enable users to access their song
playlists no matter what machine the user logs in from (home, work,
etc.).
3) For server-side code to run processes that depend on the client-side
data, you have to pass the data from client to server every time you run
the processing.  Passing a token and allowing the server to get at the
data locally *could* be more efficient in cases where there are lots of
operations that get repeatedly invoked against the majority of
client-specific data.
4)  You are correct, though, that many of the times that state is stored
on a central server, it is just because the data storage and access
technologies on the client are not capable of storing that state.  You
mention that cookies cannot be globally assumed, and in the case of
things like WAP and GPRS devices, the capabilities of these
microbrowsers are even less dependable.  Storing client-specific state
on the server is one way to aim for lowest common denominator client
capabilities.
5)  Message-based web services are actually, IMO, a case where we are
starting to be liberated from the client-side storage problems.  An XML
message can contain all of the state necessary, and the state will be
intact even after being passed through intermediaries, etc.  Take the
example of a "purchase order" which is basically the same as a shopping
cart.  You could download a catalog from a vendor, then while
disconnected on an airplane or something, do all of your shopping and
create a purchase order that contains all of the items you want to buy.
Then when you re-connect, just post the XML purchase order.  This way
the client-state stays on the client until it is needed by the server,
without having to have the round-tripping.  But keep in mind that you
will still have to get a session token to represent the long-running
transaction.  But at least the token only has to be used when it is
actually appropriate.  There *are* conventions for storing web services
long-running transaction IDs (use the SOAP header), although I am not
aware of something that is specifically a *standard*.


> -----Original Message-----
> From: Clemens Vasters [mailto:clemensv@newtelligence.com]
> Sent: Friday, January 18, 2002 11:24 AM
> To: 'xml-dist-app'
> Subject: FW: Why web-style session state management doesn't work for
web
> services, methinks
> 
> I thought this may be interesting here as well, although it's somewhat
> ASP.NET related...
> 
> -----Original Message-----
> From: Clemens Vasters [mailto:clemensv@newtelligence.com]
> Sent: Friday, January 18, 2002 7:19 PM
> To: 'dotnet@discuss.develop.com'
> Subject: Why web-style session state management doesn't work for web
> services, methinks
> 
> 
> [First, sorry for the cross-posting on DOTNET/SOAP, but I really
didn't
> know where this fits best. Also, sorry for the abuse as my mind dump.]
> 
> I am currently writing something about web services performance and
part
> of the server-side performance consierations is, of course, state
> management. Now, when I was writing that section this morning, I
> suddenly realized why I always had this very bad gut feeling about
using
> something like cookie-based state management (as ASP.NET does it) for
> web service state management. Here's what I think and it'd be great to
> hear some opinons. I can't follow all of the discussions here (who
can?)
> so this may even have been discussed, but I didn't see it.
> 
> Simple technical problems first. The classic approach to state
> management with HTTP is to pass some kind of identifier to the client
> that is returned in a subsequent request and allows the server to
> reassociate the request with the buffered session state. There are
three
> ways to do this: Cookies, URL injection and soring references in the
> response body:
> 
> (a) Use of cookies: From the start, cookies aren't covered by RFC2616
> (HTTP 1.1), but by RFC2964 (HTTP State Management) and entirely
> optional. If a client receives a cookie that the server uses for
> managing state, the client can just completely ignore that cookie and
> still play fair by all written rules. While perfectly legal, this will
> break cookie based state management.
> 
> (b) Use of URL injection: It's pretty obvious, but I am still going to
> say that the ASP.NET style cookieless sessions that work by injecting
> information into returned reference URLs won't work, because a web
> service client simply doesn't receive reference URLs to click on.
> 
> (c) Response body: The most obvious place would be a SOAP header.
> Perfectly doable, but there is no widely circulated proposal for this
> (or I didn't look hard enough) and every approach is therefore
> proprietary. My very special ASP.NET problem with this: ASP.NET's HTTP
> session model is a closed shop. Most classes are private to the
> HttpModule that sits in the ASP.NET pipeline and filters/injects the
> cookie and/or URL from/into the in/outbound stream. So if I wanted to
> relay some sort of session cookie via SOAP header I'd have to roll my
> very own session management as well. This is unless I would write an
> HTTP module that would sit before the ASP.NET session manager and
would
> parse and peel the session-id from the SOAP header and set it as an
HTTP
> Cookie header for ASP.NET to pick up. On the way out, I'd have to grab
> the ASP.NET session cookie and stick it into the SOAP header. That'd
be
> very nasty, because that'd require SOAP processing entirely outside of
> the web services infrastructure.
> 
> So, in essence, if the client chooses to ignore cookies, the state
> management issue doesn't really look good anywhere at this point.
> 
> That were the technical "status quo" issues. Pretty bad, but
manageable
> in some ways and by convention.
> 
> ----
> 
> Now, thinking about this, I have come to the conclusion that the
> web-style approach to state management using any of these three
> techniques is (!) utter nonsense (!), because they are all based on a
> completely wrong assumption. They still assume that the client is
> completely dumb and just smart enough to push back an opaque value
that
> the server is providing. It is also based on the assumptions that the
> transport is HTTP and that web service call sequences are never
> cascading.
> 
> Here's the (somewhat lengthy and right off the top off my head ==
> confusing) reason why I think that's wrong:
> 
> Given I have some kind of web service proxy for a web service
interface
> and a call sequence A->B. The call sequence happens to establishes
some
> sort of server state in an initial call to A (for some good and
> justifiable reasons) and that state is required to execute B. When A
is
> called a second time, the state is not newly initialized but updated
> taking current state information into account. This is perfectly okay
as
> long as the client stays in the same context. If the client switches
> contexts (in the sense of "business logic contexts"), it will want a
new
> context (freshly initialized server session if you will) to be set up
on
> a call to A.
> 
> How's that currently done? It works because when establishing a new
> logical context you will create a new proxy that doesn't know about
the
> cookies that were sent previously and therefore ASP.NET will create a
> new session and hand out a new session cookie. So, the ASP.NET proxy
> ("Add Web Reference" proxy) does indeed keep record of a remote object
> identity through its caching of cookies. The remote object is the
stored
> state. If you want a new object, create a new proxy.
> 
> So far, so good.
> 
> Given I have a web service proxy for a web service interface and a
call
> sequence A->B. The web service establishes some sort of server state
in
> an initial call to A and that state is require to execute B. The
> implementation of A calls the method X of another web-service with a
> call sequence X->Y, where that web service establishes some sort of
> server state in an initial call to X and that state is require to
> execute Y. Now, A calls X, B calls Y. Y depends on the state of X
> established by the call from A.
> 
> Because A and B are stateless methods and the web service class is in
> fact discarded between calls, B will build a new proxy and the state
of
> the secondary web service will no longer be available, because the
> original proxy didn't live to remember the cookie. Bummer.
> 
> While this is just an effect of statelessness in ASP.NET and there are
> technical workarounds that I could figure, I could just as well make
the
> scenario quite a bit worse and virtually unmanageable. The question
that
> will remain is: "Can any web service server implementation make a
> correct judgement about the context of its invocation based on
> traditional, web-style state management means?"
> 
> I say: The only instance that can make any proper judgement about call
> contexts and about how and when state needs to be managed is the
topmost
> caller.
> 
> If the initial caller would tell A that it is in context "C" and A
would
> pass this on to X, the same context "C" could be used by B and Y to
> retrieve their state information later on, independent of
implementation
> issues and even transport. I think it's fundamentally wrong to have
any
> web service server decide on state identity in a stateless environment
> where cascaded service request can occur. The topmost client is the
only
> instance can decide about logical context boundaries and therefore it
> must be the instance controlling state management boundaries.
> 
> Therefore it's my current state of opinon, that a SOAP header is
> required that defines the current call context and the context origin
> that must be understood by all state managing services.
> 
> To illustrate my point:
> 
> <ctx:context contextId="uuid:0B4E71D0-5383-4db2-9BA5-EE17B7E46627"
>              contextExpires="2001-18-01T23:00:00+01:00"
>              soap:mustUnderstand="1"
>              xmlns:ctx="urn:schemas-newtelligence-com:soap:contexts"/>
> 
> 
> * contextId is an URI that MUST be globally unique and that identifies
> the logical call context originating from the topmost web service
> client.
> * A web service server MUST understand the context and associate all
> session state with the contextId value.
> * If a web service client is itself part of a web service server
> implementation, it MUST NOT create a new context, but MUST pass the
> contextId and the contextExpiration on to its server, if the server
> implementation received a context header.
> * A web service server MUST keep the session information associated
with
> the context until the time indicated by contextExpires. If the server
> decides that the time-span between "now" and the contextExpires time
is
> too long (to avoid DoS) it MUST fail with
> ctx:Client.ContextTimeoutNotAccepted [this is a client provoked error]
> * A server SHOULD allow a timespan of 10 minutes for context
expiration.
> * If the context has expired (independent of whether the information
is
> still available), the server MUST fail with
> ctx:Client.ContextTimoutExpired [this is a client provoked error]
> * The context owner (topmost client) MAY adjust the contextExpiration
> value into the future at each call.
> 
> 
> In essence I am saying that the identifier with which all state must
be
> associated throughout the web service call hierarchy must be defined
by
> the topmost caller.
> 
> Shoot me! :)
> Clemens
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 

Received on Friday, 18 January 2002 15:02:29 UTC