- From: Joshua Allen <joshuaa@microsoft.com>
- Date: Fri, 18 Jan 2002 12:01:44 -0800
- To: "Clemens Vasters" <clemensv@newtelligence.com>, "xml-dist-app" <xml-dist-app@w3.org>
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