views:

867

answers:

5

What people have seen in real projects out there?

1) Web Services MUST be stateless: Basically you must send username/password with every request, every request must use HTTPS and I will authenticate and load the User object everytime if needed.

2) A Session for Web Services: like in a web container so I can at least save the authenticated User object and have something similar to a session ID so I don't need to authenticate, load and check the User on every request.

3) Sticky Service (persistent service across requests): https://jax-ws.dev.java.net/nonav/2.1/docs/statefulWebservice.html

I understand the scalability problems of stateful services (and of web application sessions), but sometimes you must have some kind of state, for example for a shopping cart. But you can also put this state in the database (use the back-end as a kind of session argh) or passing the entire state to the client (the client becomes responsible for resending the entire shopping cart).

The truth is, at least for web applications, the session helps a lot in many situations. Scalability issues can be ignored if your system accepts that "the user must start over doing whatever he is doing if his web server happens to go down" or you can try a session cluster if that's unacceptable.

How it is for web services? I am inclined to conclude that web services are very different than web applications and accept option 1) (always stateless), but it would be nice to hear other opinions based on real project experience.

+2  A: 

Highly dependent on whether the service is single transaction oriented (say getting stock quotes) or if the output from the service is dependent on a data provided from a particular client across multiple transactions(in that case state must be maintained.)

As far as scalability issues, storing state in a database isn't actually a bad way to go (in fact it's probably the only way to go if you're load balancing your service across a server farm.)

Jason Watts
You would have to clean from time to time the database, but you may be right. Looks ugly but it is actually not that bad. :-)If you have a session, another option would be a session cluster, or you can live with the fact that if your server goes down you have to start over (assuming you have a smart load balancer that sends requests from a user to the same server, which is not difficult nowadays I would assume)
Sergio Oliveira Jr.
+3  A: 

Ideally webservices (and web sites) should be stateless.

Unfortunately this takes very well thought out problem domain, and clear separation of concerns.

I've found that in practice most real-world web sites depend on state even though this limits their scalability.

I've also found that many real-world web-services also rely on state.

Ultimately the 'right' decision is the one that works for the specific problem, so it's probably okay to write a webservice that relies on state, and refactor it later if scalability becomes an issue.

John Weldon
Thanks for this real-life experience feedback, John. So my question is: if you decide you will need state, what should you use. 1) Database, 2) State on the client, 3) session, 4) persistent service. Is there an easy way to use 3 ??? Is 4 working ??? I am starting to agree with Jason that the database is the best option. :-)
Sergio Oliveira Jr.
A: 

I think with Flex clients the state is moved out of the service and into the client tier. Keep the services stateless and let the clients maintain the state needed. The services stay simple, and the clients are free to mash them together as they wish.

duffymo
A: 

You seem to be equating state and authentication. Perhaps you're accustomed to storing username and password in session state?

This is not necessary, even with old ASMX web services. Simply pass whatever information you need to your "Login" operation. This operation will be defined to return an "Authentication Ticket" header.

All other operations that require authentication will require this "Authentication Ticket" header. They will each check the header to see if it represents a valid, authenticated user. If so, then they will perform their task. If not, then they will return a SOAP Fault indicating that authentication is required.

No state is required. Simply make sure that the authentication ticket can be validated on any server your service runs on (for instance, in a web farm), and you'll be fine.

John Saunders
The authentication ticket works like a session ID. So can I get the authenticated User object from this ticket or do I have to send the user_id performing the service on every service call? I may be mistaken here, but I would think that this ticket is a form of state, no?
Sergio Oliveira Jr.
It would be your ticket - do it whichever way you like. You could include the user id _in_ the ticket if you want, or have an entire Dictionary<ticket,User> in memory, loaded from a database, and index on your ticket on every call.
John Saunders
This ticket system you are talking about does not seem to be present on JAX-WS. It looks like they suggest that you grab the underlying HttpSession which is conceptually the same thing as this ticket system. But you must assume (fair enough) that you will be using HTTP for your services.
Sergio Oliveira Jr.
@Sergio: they suggest you grab something platform-specific? Do they plan for you to send it across the wire? And why limit yourself to HTTP?
John Saunders
What is the other option for JAX-WS? Implement a ticket system myself? Not hard at all, but If am sure I will be using HTTP, as the majority of WS does, why bother re-implementing HttpSession? (feel free to throw your arguments, this debate is a learning process to me, not a competition)
Sergio Oliveira Jr.
A: 

While it's only a small difference but it should still be mentioned:

It's not state in web services that kill scalability, rather it's state on the App Server that's hosting the web services that will kill scalability. The moment you say that this user needs to access this server (as done in sticky sessions) you are effectively limiting your scalability options. The point you want to get to is that 'Any of your free load-balanced App servers' can handle this web service request and if I add 1 more App Server I should be able to handle % more users.

It's totally fine (and personally recommended) if you want to maintain state to pass in an authentication token and on each request get the service to retrieve your 'state' from a data store (preferably a redundant and partitioned one, e.g. distributed+replicated key/value data store). That's how Amazon does it with SimpleDb and Google with BigTable.

Ebay takes a slightly different approach and stores most of the clients state in a cookie so it gets passed in with every request. Although it generates a lot more traffic, it still scalable as any of their servers can still handle the request.

If you want a scalable data store I would recommend looking at redis it has speed and features that can't be beat in a key/value data store.

You should also check out highscalability.com if you want access to good material on how to build fast and scalable services.

mythz