Lucee session clustering can be enable by configuring a cache that has session storage enabled, and using that cache as the location for session storage. This can be done easily with the Memcached extension.
Installing extensions in Lucee
Lucee 5.x supports installing extensions via the LUCEE_EXTENSIONS
environment variable, which is ideally set as part of your Dockerfile
so that the installation can take place during the build rather than on container startup.
The format of the environment variable value is the same as is used for specifying dependencies in the Java Manifest files used by Lucee and it’s extensions, a comma separated list of extensions which include an ID, Name and Version separated by semi-colons.
SOME-ID;name=Some Extension Name;version=1.0.0.0,
ANOTHER-ID;name=Another Extension Name;version=1.2.0.0
The extension IDs and version numbers are found on the Lucee extensions download page:
http://stable.lucee.org/download/?type=extensions
Installing the Memcached extension
Add the environment variable to your Dockerfile;
ENV LUCEE_EXTENSIONS "16FF9B13-C595-4FA7-B87DED467B7E61A0;name=Memcached;version=3.0.2.29"
To ensure the extension is installed at build time, we need to “prewam” Lucee by starting Tomcat and waiting for Lucee to finish initialising, followed by stopping Tomcat. With the current version of Lucee 5.2 this can be done using a RUN
command in the Dockerfile
;
RUN /usr/local/tomcat/bin/prewarm.sh
(Note: the web context logs are cleared first, because the test for Lucee finishing it’s startup process is to check for the existence of the application.log
)
Configuring the application
In the psuedo-constructor of your Application.cfc
, or in the case of a FarCry Core application in your farcryConstructor.cfm
, add the following;
this.cache.connections["sessions"] = {
class: 'org.lucee.extension.io.cache.memcache.MemCacheRaw'
, bundleName: 'memcached.extension'
, bundleVersion: '3.0.2.29'
, storage: true
, custom: {
"socket_timeout":"30",
"initial_connections":"1",
"alive_check":"true",
"buffer_size":"1",
"max_spare_connections":"32",
"storage_format":"Binary",
"socket_connect_to":"3",
"min_spare_connections":"1",
"maint_thread_sleep":"5",
"failback":"true",
"max_idle_time":"600",
"max_busy_time":"30",
"nagle_alg":"true",
"failover":"true",
"servers": server.system.environment["SESSION_MEMCACHED_SERVERS"] ?: ""
}
, default: ''
};
this.sessioncluster = false;
this.sessionstorage = server.system.environment["LUCEE_APPLICATION_SESSIONSTORAGE"] ?: "memory";
NOTE: this.sessioncluster
should be set to false
to avoid race conditions with session access. A previous version of this document recommended LUCEE_APPLICATION_SESSIONSTORAGE
be set to true
which is incorrect. The better value to use is false
in conjunction with sticky sessions when load balancing across multiple containers.
In the docker-compose.yml
file for you application, populate 2 new environment variables with appropriate values;
- "LUCEE_APPLICATION_SESSIONSTORAGE=sessions"
- "SESSION_MEMCACHED_SERVERS=memcached:11211"
Testing session persistence
With docker-compose
you can restart a single service that is defined in your docker-compose.yml
file. If your application service is named lucee
you can run the following command to restart it, which would usually result in all in-memory sessions being lost upon restart;
docker-compose restart lucee
This way even, if your memcached container is a linked service within the same docker-compose.yml
file, it will stay running just fine after issuing this command.
You can test the session persistence in your app by hitting a particular part of the application that uses sessions, such as logging in, then restart your application container and reload a page to confirm that you are still logged in and your session remains intact, even after the application server was restarted