We are running our apps in a containerized environ...
# cfml-general
d
We are running our apps in a containerized environment, but have been running each app with only one pod because we know we’ll need to change some things to account for multiple instances of the app running at the same time. (e.g. sessions are currently saved on the server instead of a persistent database or something like that). Are there any other things we should be looking for as we try to scale horizontally? We’re running the Lucee nginx image, FYI.
Why not just use the browser for session data? It seems to be an option in the Lucee admin settings.
r
if you are wanting to use a HA clustered setup with nginx you will need a persistent session manager that is used to share the session data between servers. Redis is one option that you can setup with lucee for this purpose.
q
I've got a few apps that we've been scaling horizontally. If you are depending on static variables for your application/server scope, but do dynamic things in the session scope, you should be able to turn on sticky session in your load balancer/proxy. That way you shouldn't have to change too much in your apps. Using an engine like redis is very much an option for session and application management if you want to go that route. Using a DB is also an option as well, but make sure you do proper locking/checks when updating variables so they don't get pulled out from underneath you.
b
I think you'd be very surprised at how easy it is to move the session scope (specifically) into Redis but, like quetwo said, you don't really need to... you can enable sticky sessions so, once a user lands on a pod, they stick to THAT pod where their session data is.
d
Thanks for the replies. What is forcing our hand is we’ve been running into a node getting too busy, kicking out a pod (single instance of the app running) to another node to free up resources, but it kills the old pod before the new one is ready. My team isn’t in charge of the infrastructure level, but that team said that is why they always suggest having multiple instances of the app running at all times. 🤷‍♂️ I say that because it seems like it would also make sticky sessions problematic.
Can anyone speak to Redis vs just using the DB? pros/cons?
b
distributed cache or some other central storage location (i.e. the database) is exactly for solving the problem you described. At the end of each request, the current session is written out to your session storage location (i.e. Redis). At the beginning of the request, the session belonging to your cfid is pulled in and loaded up. So, even if you move from server to server on every request, your session moves with you. Outside of normal memory storage, I have only ever stored sessions in Redis. I've (unfortunately) had to deal with client variables forever and those have been stored in the database... that has always been a real pain under heavy load for us. Now, we also store client variables in Redis (until we can refactor and get rid of them or move them to session scope) I don't have any stats around comparing Redis to storing sessions in the database because, frankly, I'd really rather not store them in the database.
we still use sticky sessions, run around 14 pods on average load and stoire our sessions in Redis (in elasticache). So the only time a user gets moved to another pod is if the one they are on is terminated for whatever reason... crash, rollout deploy... whatever.
The DB will work. but the location of your DB will matter in terms of speed. But, if everything (db, redis and web apps were all sitting in the same VPC, I'd wager Redis would be the faster option). Plus there is no worry over heavy load causing blocking on a DB table that is critical to EVERY single request (much like when using client variables and storing those in the database)
One thing to consider, to store your sessions in Redis, the session data MUST serialize... i.e., no errors when you do #serialize( session )#. I would have to assume that is a requirement for storing them in the database as well but can't so for sure since I've never used the DB for sessions.
Another thing to consider with Redis (not siure if it applies to storing in the database), you have to use sessionType="cfml" so if your app is dependent on jee sessions, that might be a problem (something else that had to be refactored for us to move to Redis)
d
Ok, interesting. Super helpful stuff there, thanks! Is there a downside to cfml vs jee? We're currently using cfml, it looks like, which I assume would be the default.
q
CFML session tokens are sometimes tagged as being less secure. Older versions of ACF didn't do great with randomness on them (and even earlier versions were sequential), so it was possible to hijack or jump sessions. J2EE was the better fix for that but it did introduce other incompatibilities.
Newer versions of ACF (2016+) and all versions of Lucee are sufficiently random at the session trackers to not really be an issue.
b
There was one gotcha switching if I recall... j2ee sessions and the default setClientCookies of true means you don't have to do anything to make the cookies actual session cookies (meaning they will "expire" when the browser closes as session cookies should and you would get a NEW cfid when coming back). This is a security audit must for us). Simply switching to cfml session types made the cookies just normal cookies with an expiration matching the session timeout settings. So you would just need to set this.setClientCookies to false and set the cfid/cftoken cookies manually without an expiration date to make them behave the same again. for example. in onSessionStart
Copy code
sessionInvalidate();
cfcookie( name = "cftoken", value = "#session.cftoken#" );
cfcookie( name = "cfid", value = "#session.cfid#" );
👍 1