The Dopefly Tech Blog

I was going to diss client variables...

posted under category: General on April 26, 2011 at 1:00 am by MrNate

A couple months ago, an edict from on high (AKA my company's enterprise IT infrastructure middleware hosting support department -- it's a big company) came down that said in order to host our applications on the new ColdFusion 9 server cluster, we have to stop using session variables and switch to client variables.

They sent us all a document detailing how to do it. It's easy, (1) you just do a find-and-replace to turn session.* into client.*, then (2) watch Nathan's blood boil with pure hatred.

The reasoning behind it was simple (meaning both obvious and dull-witted). The new server environment is clustered, if one server crashes, we'll lose our session, but client variables will live on in a shared client variables database. <red flags>! I could rant for a few days about the policy. There are a number of other factors that increase the fallability of the recommendation, including the use of our single sign-on service, use of sticky sessions, the fact that I tend to put components into the session scope, and on and on.

So I wrote.

First, I wrote some code to get around the entire fiasco without using a single stupid client variable.

Then, I started writing in Evernote. I have about 5 printed pages worth of blog material. I was going to blog it all, it was going to be epic. Then, I saw there were lightning talks at CF.Objective() 2011, and they needed volunteers for speeches. I pitched the Client Variable Ultimate Smackdown and was accepted! Now, I'm saving the blog-rage for sometime after May 12th-14th, and instead you should come see my lightning talk on client variables on Thursday May 12th at CF.Objective()! LTs are a lot more informal, but it's going to be a lot of work for me. I'm really excited to be speaking twice now!

I'm trying to treat my Lightning Talk a little like a melodrama, a little like a speech to anger everyone, a little like just sharing something that interests me, and a lot like revealing the shocking evidence on why client variables are probably the worst aspect of the ColdFusion Markup Language.

On Apr 26, 2011 at 1:00 AM Shawn Holmes (shawn.a.holmes@example.com who would have preferred an address at gmail.com) said:

I have some bad news.

It's going to be a lot more involved than a find-and-replace.

SESSION variables and CLIENT variables have a very important difference that's going to require some thought on the part of those involved in your re-architecture:

CLIENT vars cannot contain complex values.

So, if you have something like a User struct to carry your currently logged in user's info:

session.user.user_idsession.user.first_namesession.user.last_name

You are *not* going to be able to do this:

client.user.user_idclient.user.first_nameclient.user.last_name

On Apr 26, 2011 at 1:00 AM John Blayter (jblayter at the ever popular gmail.com) said:

Nate,

Take a look at this. http://sessionswap.riaforge.org/

I wrote a little thing that serialized the session scope into a string that can be stored in the database. It uses java serialization so it is very fast and only interacts with the database when necessary. I have done the session variable clustering and it does work. However, I found that it worked best when I had a private dedicated network (NIC cards going into a VLAN) for the traffic.

On Apr 26, 2011 at 1:00 AM Damon Gentry (gentryd@example.com who would have preferred an address at ohsu.edu) said:

Shawn is correct, you cannot store complex objects in the session scope (Structs, Arrays, or Objects [components, or pojos]). You can, however, use WDDX to serialize/deserialize complex data types and save the WDDX as a client variable. This is very scalable, but comes at the cost of performance.

BTW: At my organization, I AM the 'enterprise IT infrastructure middleware hosting support department'. We chose not to implement in-memory session replication for 2 reasons: 1) it is buggy, and 2) is can easily be abused by developers who put TONS of data in SESSION scope.

Our stance is to inform the developers about our environment (load balanced, but not clustered). We use session-affinity at the load balancer to keep a user tied to a single application server, but they may fail from time to time. We leave it up to the application owners to assume the appropriate level of risk for the app. Some apps use session scope, other use client scope. It's all about whether or not they are willing to have a user be logged out or not in the event of a server failure.

There is also this decent compromise: Use client scope to save authentication information (Yes, the user is logged in as user 'X'.) But store more relevant information about each user in the session scope. In your app, test for the existence of session data; if it is not present, check the client scope to see if the user has authenticated. If they have, then re-create the session scope based on the client scope data. For example, you might have the following:

On Apr 26, 2011 at 1:00 AM Nathan Strutz (www.dopefly.com) said:

Shawn,You hit it head on, but there's a lot more going on. The common approach is to WDDX the data, which is pretty ugly. You should come to the Lightning Talks at CF.Objective() and hear the whole thing!

John,I don't remember seeing that project before, but it does seem very reminiscent of something from back in the i-sites days. Great work-around to the client/session & bandwidth problem - it really illustrates how easy a fix for client variables would be.

On Apr 26, 2011 at 1:00 AM Nathan Strutz (www.dopefly.com) said:

Damon,Thanks for your comments. Your suggestions are spot on, and similar to what I did to get around the entire client variable problem. Watch out that you know your client variable storage, too. Obviously don't put them in the registry or in a cookie, but don't use a shared database either, or they will be joined at the hip to something that could go down (1 client var database goes down = entire cluster of apps goes down), and then there's still the noisy database chatter problem... Ehhhh, really just don't do it at all!

Joe Rinehart asked about clustered sessions on the Facebook repost of this blog. Here's what I said:

----Yeah session replication does work, but it's a lot of overhead that middleware didn't want to take on. The way it works is that EVERY server in the cluster gets a copy of EVERY session variable across the ENTIRE cluster. This weighs heavily on network bandwidth, on server communication, and especially on CF's memory footprint. Every time a session variable changes, the user's entire session is re-replicated across the cluster. If you have a server that is maxing out its memory so you add another clustered server, now you have two servers maxing out their memory and doing a lot of chatter back & forth.

Session replication is great for some applications, and can truly be a life saver when you begin to reach a processing threshold, but are a big hindrance in other situations.

So our middleware group decided to play it safe because they don't control any of the applications going into the cluster. IMO a good decision.