Stateless vs. State-free AppServer

Posted by ojfoggin on 19-Jan-2010 04:02

Hi Guys,

About 6 months ago I migrated our system from a badly implemented Client - AppServer connection (where the connection was established every time information was needed and then dropped completely once it was done) to one that it was designed for (establish connection at login and keep that connection until logout).

It has now been rolled out and put live and is working perfectly.

However, as usual, I am not happy until I have it running as best it can be and I've been looking at the difference between stateless and state-free AppServers.

Currently the AppServer is running in Stateless operating mode but from looking at Table 1-4 in the OpenEdge AppServer PDF manual it looks like state-free would be best suited for our implementation.

From what I can gather it looks like a stateless server is one where each time the connection from the client to the agent is activated a script is run to establish the state of the server from the previous connection and then reset on deactivation.

However, we are not using the activation or deactivation programs as we have no state across the system.  The only procedure we use is the StartUp procedure to set up some super procedures at startup.

Given this, I am guessing we can just hit the button that switches to state-free?

Do I need to check anything else?

What additional advantages would we get from our system by doing this given the systems we are using will have up to 300 concurrent users?

Thanks for any help.

Oliver

All Replies

Posted by ojfoggin on 19-Jan-2010 04:20

Hmm...

I've found quite a bit more info on this.

One thing our server code uses almost exclusively is persistent procedures.

The one thing that the Appserver pdf thing mentions is that persistent procedures should not be used at all if possible for a state-free server.

I guess it is something we can work towards.

One question though.

How do you tell the client where the server is?

You can't use the CONNECT method for a state-free server.

Thanks again

Posted by Admin on 19-Jan-2010 04:31

For persistent procedures it's always a difference who launches them and where.

When the client launches them remotely on the appserver it's generally a bad thing. With state-less it's (at least) supported - but that basically turns the connections into state-aware. And that's bad.

State-free does not support remotely launched procedures. So that's a difference.

The AppServer can use persistent procedures on it's own - as libraries. No matter on the run mode.

So RUN xyz.p PERSISTENT SET hProc ON hAppServer is the evil.

Posted by ojfoggin on 19-Jan-2010 05:03

Hi Mike,

Unfortunately that is something that is used a lot in our code.

Fortunately it is only ever used in client super procedure via a PUBLISH command and we think we have come up with a way of changing the way it works so that we can systematically get rid of the remote persistent procedure calls.

I'm still unsure as to how you run something on a state-free appserver though.

At the moment we do something along the line of...

/**check if appserver is already connected**/

/** if not then... **/

create server.

server:connect(connection-params).

/** then **/

run fu.p persistent set lh-fu on server.

then ...

run bar in lh-fu.

then ...

delete procedure lh-fu.

if you can't run the CONNECT procedure for the server then how do you tell the client where to run the non-persistent procedure on a state-free appserver.

I realise I'm jumping the gun here but I'd like to know for a dev meeting we are having on Friday.

Thanks again!

Oliver

Posted by kevin_saunders on 19-Jan-2010 05:57

I think you are getting confused between the 'CONNECT' procedure on the AppServer (executed when a client connects to an AppServer) and the CONNECT method - the connect method is still used, you just have to add the "-sessionModel session-free" option..

Like:

hAppServer:CONNECT('-AppService asbroker1 -H Localhost -S 5162 -sessionModel session-free').

Posted by ojfoggin on 19-Jan-2010 06:06

Ah!

That makes sense

I got an error along the lines of "Invalid CONNECT method" or something.

I assumed from this that you had to connect through a different way.

I will add the extra parameter and try again.

Thanks!

Posted by ojfoggin on 19-Jan-2010 06:10

Thanks!

Working and connected now

Although not ideal as it needs a bit of tweaking and changing but it's connected

Posted by rbf on 19-Jan-2010 07:24

I think the difference between stateless and state-free is enormously underestimated here.

The Stateless AppServer is actually badly named, because the big advantage is that it allows you to maintain some state at virtually no cost. For example, you only have to supply the login credentials when you connect. With a statefree AppServer, you need to verify credentials with each and every call. I am pretty sure your application is not designed that way.

Secondly, the Stateless AppServer provides an extremely fast and efficient way to maintain *some* session context on the server free of charge: SERVER-CONNECTION-CONTEXT. The broker assigns this piece of memory to your agent each call, and you can store context here at virtually no cost. There is no script run as you fear. You certainly should not use activation and deactivation scripts. With a statefree AppServer, there is no such mechanism so you need to communicate context to the server with each and every call (unless you use an even worse construct and save the context in the database). I am pretty sure your application design is not up to this either.

Personally I think that the Stateless AppServer, when used well, provides even for better performance and scalability than the Statefree AppServer.

You need a darn good reason to migrate from Stateless to State-free (one such reason could be that you need to create a Web service interface).

My $0.02

-peter

Posted by ojfoggin on 19-Jan-2010 07:41

Hi Peter,

TBH, I'm not sure what "state/context" is and I wouldn't know what, how or why to save this state?

At the moment we have no state (context, etc...) saved on the AppServer or database.  Each procedure runs with input parameters and passes out output parameters.  I am not sure what advantages we can gain from saving context?

What are the advantages of having context saved on the AppServer (or anywhere for that matter)?

Again, I am unsure why we would have to verify credentials on each appserver call with state-free.  I have set up a small development appserver as state-free and it seems to run with no problems with very little change to the code.  It isn't ideal due to the number of persistent procedures we are using but it ran with no problems.

At the moment I am trying to find the pros and cons of both systems and work towards the one that is best for us.  If that is stateless then I would be happy to stay where I am but if state-free would produce better scalability and performance with 200+ concurrent connections then I'd like to find out what I'd be missing and the best way to set it up.

Thanks

Oliver

Posted by rbf on 19-Jan-2010 07:56

Again, I am unsure why we would have to verify credentials on each appserver call with state-free.  I have set up a small development appserver as state-free and it seems to run with no problems with very little change to the code.  It isn't ideal due to the number of persistent procedures we are using but it ran with no problems.

Ok let's start with this one first:

  • Do you currently provide a userid/password when connecting to your Stateless AppServer?
  • Did you create a Connect procedure that verifies the userid/password?

Posted by Admin on 19-Jan-2010 08:06

I share Peter's preference for state-less AppServers.

There is one more argument for them: A state-less' client's request will check the broker for a server and talk to the server (two roundtrips) as the client is connected to the broker.

With state free every request requires asking the nameserver first, then the broker, then the server (=agent) which are three roundtrips.

With ping times of 70 msec (internet) that's a difference of 140 msec or 210 msec...

Avoiding the name server (direct connect) is an alternative, but reduces scalability. AIA is another option as this keeps the additional hit "in house", but that's an extra component to maintain (on a JSE).

Posted by ojfoggin on 19-Jan-2010 08:16

  • Do you currently provide a userid/password when connecting to your Stateless AppServer?
  • Did you create a Connect procedure that verifies the userid/password?

This too is not set up like I think it should be.  At the moment we have a user table on the database.  This is used to store information about the user (userID, name, branch number, etc...) it also stores the password (unencrypted - I know, please don't shout ).

When the user starts the system they are asked for their userID and password.  The system then establishes a connection to the AppServer and runs a procedure to validate the userID and password against the user table on the database.  This is done as part of a procedure we have written, not as a connect procedure.

If the userID is invalid or the password is incorrect it will throw back a message informing the user and disconnect the AppServer.  If the userID/password is correct then it keeps the connection to the AppServer and saves the handle to it and carries on from there.

When you try to run a remote persistent proc it will check the AppServer is still connected and if not it will connect it again with no verification and then run the persistent proc.

Hope this makes sense.

Thanks

Oliver

Posted by rbf on 19-Jan-2010 08:35

ojfoggin wrote:

  • Do you currently provide a userid/password when connecting to your Stateless AppServer?
  • Did you create a Connect procedure that verifies the userid/password?

This too is not set up like I think it should be.  At the moment we have a user table on the database.  This is used to store information about the user (userID, name, branch number, etc...) it also stores the password (unencrypted - I know, please don't shout ).

When the user starts the system they are asked for their userID and password.  The system then establishes a connection to the AppServer and runs a procedure to validate the userID and password against the user table on the database.  This is done as part of a procedure we have written, not as a connect procedure.

If the userID is invalid or the password is incorrect it will throw back a message informing the user and disconnect the AppServer.  If the userID/password is correct then it keeps the connection to the AppServer and saves the handle to it and carries on from there.

When you try to run a remote persistent proc it will check the AppServer is still connected and if not it will connect it again with no verification and then run the persistent proc.

Hope this makes sense.

Thanks

Oliver

No this does not make sense. It means that any user can connect to your appserver and run what they want as long as the don't run that procedure.

First get your Connect procedure into place to enforce security.

In State-free terms, this means that you need to run the procedure that validates your userID and password on EACH AND EVERY call.

With a Stateless AppServer, you only need to do it once on the Connect procedure.

When this starts making sense we can dive into context management....

Posted by rbf on 19-Jan-2010 08:36

mikefe wrote:

I share Peter's preference for state-free AppServers.

I hope you mean:

I share Peter's preference for Stateless AppServers.

Posted by Admin on 19-Jan-2010 08:41

I hope you mean:I share Peter's preference for Stateless AppServers.

Uupps. Yes!

Posted by ojfoggin on 19-Jan-2010 09:07

OK, the username password thing at connect is something I am going to be setting up.

However, I'm still unsure why you would have to verify the username and password each time you wish to run a procedure in state-free.  The connect is run at startup of the client and infact it doesn't have a connect procedure in state-free.

Posted by rbf on 19-Jan-2010 09:16

ojfoggin wrote:

OK, the username password thing at connect is something I am going to be setting up.

However, I'm still unsure why you would have to verify the username and password each time you wish to run a procedure in state-free. 

Well if security is not an issue than why bother working with a userid and password?

The connect is run at startup of the client and infact it doesn't have a connect procedure in state-free.

Exaclty. So if you want to know who is running the request you will need to verify that on the state-free appserver each and every time.

Posted by ojfoggin on 19-Jan-2010 09:43

OK, putting the userid and password verification aside.

I'm still not sure what I would gain from saving any context information on the AppServer?

Thanks again.

Posted by rbf on 19-Jan-2010 09:52

ojfoggin wrote:

OK, putting the userid and password verification aside.

I'm still not sure what I would gain from saving any context information on the AppServer?

Thanks again.


Good candidates are stuff that you would in a client/server application in the past put in GLOBAL SHARED VARIABLES.

You can store these in SERVER-CONNECTION-CONTEXT in the Stateless AppServer.

In a State-free AppServer, you have to send them along with each request.

Posted by ojfoggin on 20-Jan-2010 08:26

Thanks for all the input with this.

I have been poring over the AppServer manual trying to increase my understanding of the whole client-broker-appserver connection and I'm getting there bit by bit.

There are a few things, however, that I am certain of.

1. In my quick and simple testing of a single connection I could see no improvement (or change at all for that matter) over the network traffic between stateless and state-free AppServers.

2. The way we currently connect to the AppServer allows for anyone with a bit of progress knowledge to make their way onto the AppServer and bypass the user validation check.  This will need to change.

3. We need to get rid of remote persistent procedures.  This will probably return the biggest performance gain (more so than swapping to a different session-model).

Concentrating on getting the current set up working as best it can is going to be more productive in producing performance gains than trying to bodge a session-model change to something that might not provide any performance increase at all.

We'll get there eventually... wherever there is

Thanks again

Oliver

Posted by Thomas Mercer-Hursh on 20-Jan-2010 11:14

wherever there is

One might suggest that you would get there more efficiently, if you figured out the destination first.

Posted by ojfoggin on 28-Jan-2010 04:23

Funny you should say that.

The dev meeting we had the other day that I wanted to prepare this for included a 5 year plan which had a lot of achievable goals to work to

Posted by Thomas Mercer-Hursh on 28-Jan-2010 12:21

It isn't exactly an accident that I mentioned it ... one of the things I do for a living is to help people prepare such plans.

Posted by ojfoggin on 29-Jan-2010 02:32

Sneaky little hobbitses!

Posted by maximmonin on 04-Aug-2010 03:58

For example, you only have to supply the login credentials when you connect. With a statefree AppServer, you need to verify credentials with each and every call. I am pretty sure your application is not designed that way.

Secondly, the Stateless AppServer provides an extremely fast and efficient way to maintain *some* session context on the server free of charge: SERVER-CONNECTION-CONTEXT.

I agree with Peter, stateless server can give better performance and save global vars but it costs exactly 1 thread of appserver.

When I planned web based application I selected state free model with context managment instead stateless model.

1. Context managment webdb was added to keep sessions/Context threads + Context parameters.

2. When client first connects to DB and login/password supplied application creates new session record + new context thread record saving context parameters. Returns ContextKey to client.

In stateless model WSA returns PROGRESS-SESSION-ID unique key instead.

Every call in both models i have to supply this key. In statefree model I have to supply ContextKey as input parameter with every call.

In stateless model I have to supply Session-IDkey in soap header with every call.

So first Diffrence is:

100 concurrent users in stateless model are idling = 100 appserver threads are busy.

100 concurrent users in statefree model are idling = 0 appserver threads are busy.

Second is multiply context threads.

1 sessions in stateless model restricts client to have only 1 copy of gloval vars.

Context managment webdb can save many Context records with it is own context parameters within 1 session. Every time User run some service/module application can create new context threads record coping Parent context parameters and adding some new ones and returns new Context key to Client. Parent module/applications still uses old context key and has it is own Context.

It costs about 20 line of code. Every call in statefree model you have to check ContextKey by Security systems and reintialize global vars from Context thread parameters. It takes some time (1-2ms).

Third is multithread algorithms.

In stateless model you are limited to 1 thread. WSA has special parameter - waitIfBusy = -1. It supports queue of incoming requests and executes it one by one.

In stetefree model you arent limited to 1 thread. WSA seeks for new available thread every call, blocks it while executing request and then free it.

Four is DB transaction scope and record locking.

Stateless model is limited to 1 transaction and many sub transctions within 1 session.

Statefree model can execute many transaction in parallel and roll back it if needed.

But Statefree model cannot lock record when nonpersistent procedure ends and WSA frees appserver thread.

This only way to keep record locking is create remote server object by calling persistent procedure.

At the moment when call of persistent procedure occurs WSA blocks 1 threads of appserver and returns SESSION-ID-key just like with stateless model. You have to supply this key with everycall in soap header. Release method is used to destroy remove server object and free resouces.

Sorry, my english isnt good.

I hope this helps.

Maxim.

Posted by rbf on 04-Aug-2010 04:31

Hi Maxim,

First of all, if you are talking Web services I think you are stuck with State-free anyway.

Secondly, a context database is the biggest performance killer I know. I have seen web applications with context db that spent more than 50% of their time maintaining the context db during calls.

The trick is in avoiding a context database alltogether. That is a big challenge but if you manage that a Stateless AppServer is way more efficient than State-free because of the reasons I mentioned earlier in this thread and the performance and scalability are magnitudes better than State-free with a context db.

Posted by Admin on 04-Aug-2010 04:40

I agree with Peter, stateless server can give better performance and save global vars but it costs exactly 1 thread of appserver.

Can you clarify what you mean with a thread?

In comparing stateless (IMHO best default for GUI clients) and state-free (IHO best default for WSA clients etc) the duration an AppServer agent is locked is the same: Just for as long as it takes to process a request. There is no agent locked or tied to a client when the client is not actually executing a request.

The connections to the broker stand with stateless, and I believe there is a meaning of a connection thread. But that's not a resource you should consider as expensive.

Posted by maximmonin on 04-Aug-2010 05:05

Secondly, a context database is the biggest performance killer I know. I have seen web applications with context db that spent more than 50% of their time maintaining the context db during calls.

As I said it takes about 1-2ms with every call in my case.

Init procedure just queries if contextkey is valid with every call and with 10% calls reinitialize global vars.

Second - performance killer is many little queries to DB. In my case I redesined system and every call do a lot of work. Instead of hundreds quieries I have 10-30 procedures to do all job for specific service. Client (flex) can keep data in internal objects, so I can just call once for data and then client works independent until user clicks refresh/save button.

Maxim.

Posted by maximmonin on 04-Aug-2010 05:11

Thanks Mike, got it.

If no thread blocking then it was my mistake.

Maxim.

Posted by Admin on 04-Aug-2010 05:15

Second - performance killer is many little queries to DB. In my case I redesined system and every call do a lot of work. Instead of hundreds quieries I have 10-30 procedures to do all job for specific service.

Sounds familiar. The AppServer is much better with few large requests that many smaller ones - even if the actual payload is identical.

This thread is closed