Let's start. First download Railo Express 3.0 Beta from our Website at
www.railo-technologies.com/en/index.cfm?treeID=361
Copy the content of the downloaded zip to a folder of your choice, rename it to railo8888 and make a second copy named railo9999, so that you end up with to folders containing the railo express content.

Change to folder "railo9999".

Open the file server.xml and change the port definition on line 16 from 8888

to 9999.

Start both Railo application servers, (double) click start[.bat] in both folders (railo8888 and railo9999).

Two command prompts should open.

Now change to your browser and tip. http://localhost:8888/railo-context/admin/server.cfm

Enter a password for your server administrator.

Change to page Remote/Security Key.

Copy the Security Key.

Now open a second browser window and open the url. http://localhost:9999/railo-context/admin/server.cfm

Change to page Remote/Clients.

click on

Fill the form as follows (but use your server password and your security key), then save it.

Change to page Remote/Security Key.

Copy the Security Key.

Change back to the other browser (http://localhost:8888/railo-context/admin/server.cfm) and create the same client in this server administrator, but this time with the other security key and the server "http://localhost:9999".

You will now have a bidirectional connection between the two Railo application servers.
Go now to the webroot folder of one of the two Railo server, for example the railo8888 folder, and open the index.cfm file.

Remove the content and add the following code.
your are on:
<cfdump var="#cgi.SERVER_PORT#">
<cfset cluster["port"&cgi.SERVER_PORT]="Hello from "&cgi.SERVER_PORT>
<cfdump var="#cluster#">Do the same for the other Railo server. If you changed the index.cfm file in railo8888 the change now the one in railo9999.

your are on:
<cfdump var="#cgi.SERVER_PORT#">
<cfset cluster["port"&cgi.SERVER_PORT]="Hello from "&cgi.SERVER_PORT>
<cfdump var="#cluster#">Go back to the first browser and call http://localhost:8888/. You should see that you have requested railo 8888 and that this instance of the Railo server has written the key "port8888" to the cluster scope.

Open or go back to the second browser and request http://localhost:9999/. This time you are on the railo 9999 instance and you should see both values in the cluster scope, from port8888 and port9999.

voilĂ you have it!
now stop one railo with stop[.bat], for example railo 9999

and call the other railo in browser
If you stopped railo9999, request http://localhost:8888/. You should see that the cluster scope still shows the two entries.

Because railo9999 is not running, railo8888 can not synchronize the cluster scope. Go to the Railo administrator of the railo8888 instance http://localhost:8888/railo-context/admin/server.cfm and go to Services/Tasks.

In the list you will see one open task, select it and open the detail view.

In the detail view you will see that Railo tried to synchronize the requests. The synchronization failed because the second Railo instance is not available.

Restart railo9999 again and call it in a browser. You will see that railo9999 already took the scope data from the other server instance.

Go back to Services/Tasks list in the Railo administrator. You will see that the open taks is gone.

When you invoke the cluster scope the first time after restarting the server instance, Railo asks the connected instance for the cluster data. This means that you don't need to wait for the synchronisation.
19 responses so far ↓
1 Mike Brunt // Jul 7, 2008 at 2:38 AM
2 Raymond Camden // Jul 7, 2008 at 1:29 PM
<cfif clusterScopeFailed()>
Sorry, we need to kill the site. Our servers are fubared!
<cfabort>
</cfif>
You get the idea. If the admin knows that it wasn't able to update, then you should have programmatic access as well.
3 Michael Streit // Jul 7, 2008 at 2:12 PM
for exmple:
<cfadmin action="getRemoteClientTasks"
type="server" password="myserverpassword" returnVariable="tasks">
<cfadmin action="executeRemoteClientTask" type="#request.adminType#" password="#session["password"&request.adminType]#" id="#data.ids[idx]#">
<cfadmin action="removeRemoteClientTask"
type="#request.adminType#"
password="#session["password"&request.adminType]#"
id="#data.ids[idx]#">
Everything you can do in the Railo administrator (RA) you can to programticly as well. the RA is a (very) simple cfml app based on the tag <cfadmin> (and search and schedule tags), sorry there is no doc for the <cfadmin> tag at the moment, but it will definitly follow.
4 Oscar Arevalo // Jul 7, 2008 at 2:37 PM
5 Streit Michael // Jul 7, 2008 at 2:52 PM
for example:
<cfset cluster.mystruct[4].mycfc.getInnerCFC().setName("susi")>
but railo support serialisation for most of the types inside cfml, including array,struct,cfcs and java object (that are Serializable).
for example:
<cfset ser=serialize(myCFC)>
<cfdump var="#evaluate(ser)#">
6 Raymond Camden // Jul 7, 2008 at 3:36 PM
7 Pete Freitag // Jul 7, 2008 at 6:04 PM
8 Raymond Camden // Jul 7, 2008 at 6:06 PM
9 Pete Freitag // Jul 7, 2008 at 6:09 PM
If you had it throw the exception, you would have to wait for the operation to complete / or fail, that would be very slow.
10 Raymond Camden // Jul 7, 2008 at 6:11 PM
11 Pete Freitag // Jul 7, 2008 at 6:15 PM
12 Streit Michael // Jul 7, 2008 at 6:51 PM
the spooler tries muliple time to execute the task when fails (see above the detail view), if you for example restart one client all other client fails with sync, but after the client is available again, they send all data fails before, nothing lost no problem, no error. but when you have this listener you get a lot errors for nothing, you get the error but not the success message.
why you wanna handle this error, when the error already is handled by railo.
by the way, all tasks of a client are peristent and still exists after a restart.
13 Raymond Camden // Jul 7, 2008 at 6:58 PM
14 Streit Michael // Jul 7, 2008 at 7:43 PM
the cluster scope and the other task types are not on application level, mean you can have multiple App.cfc with different name scopes. the listener should be in the Server.cfc, then "onServerStart" you can use the cluster scope as well.
one thing i forget, even the last try fails the data are not lost, because they are still in pool can be executed manually or when the remote client is available again he pull the data and this info you should provided as well.
pherhaps "onTaskFail" will be called after last try, but one minute later the server is running again and pull the data and everything is fine, should then a other method be invoked like "onSuccessAfterFail"
15 Andrew Grosset // Sep 17, 2009 at 7:29 PM
16 Gert Franz // Sep 18, 2009 at 11:11 AM
Gert
17 Andrew Grosset // Sep 23, 2009 at 2:14 AM
Andrew.
18 Gert Franz // Sep 23, 2009 at 7:14 AM
may I ask how you do this?
Gert
19 Gert Franz // Sep 24, 2009 at 1:01 AM
Two servers: server A and server B.
When user logs in to server A his session is also stored in memcache.
On server A I use an "onClick" javascript url to call via ajax a function to check if user's session is current (logged in).
If it is I create a string: getTickcount and users session.id and encrypt it and call it "token". I return this to the calling page where a javascript function builds a form and places the token in the form and submits it to server B. In the onRequestStart of application.cfc (server B) if "form.token" is detected it is passed to a function that decrypts the token, checks the time difference (compares getTickcount is less than 500ms) and if the user does not already have a session on server B checks memcache for this users session if it is available then the session struct is copied from memcache to server B's session struct and the user is logged in on server B.
One drawback to this: when you store something in memcache you give it an expiry time say 20 mins and this doesn't change unless you set the value to memcache again, compare this to a session value of 20mins: if you hit the server every 19mins the session will never expire so I just give memcache a longer expiry time.
The same principal can be used to duplicate application variables across from server A to server B. As long as you update memcache whenever you change the application (or session) struct then you can keep the user synchronised across the two servers.
I have not exhaustively tested this yet as I'm still developing/testing the idea, but so far its ok.
Andrew.
PS
memcache for coldfusion has been developed by Jon Hirschi http://www.flexablecoder.com
It can be downloaded here: http://cfmemcached.riaforge.org
Leave a Comment