Introduction

Sessions are typically initiated by users via the Webinterface of the Open-Xchange Server, Outlook or mobile devices, every session is bound to one Open-Xchange server until it is terminated. In a clustered Open-Xchange environment, sessions are assigned to one server of the cluster by random algorithms. Since Open-Xchange uses caching via the network all data is available to every user on every server in the cluster. But sessions are still bound to one server and if that server is going to be shut down, users would encounter an error message and are kicked off the cluster. To solve this problem, sessions migration has been introduced with the OSGI implementation of Open-Xchange Server. This feature allows sessions to migrate to another server at the cluster without having any influence to the end user. Typical scenarios where sessions need to be migrated are hardware and software upgrades of the server as well as emergency shutdowns.

The implementation of the session migration is based on a cache which is filled with all sessions of a server if its "sessiond" bundle is shut down. Other groupware servers fetch the sessions from the cache and take over the migrated session. Therefor it is mandatory to shut down the sessiond bundle prior to the server shutdown. Note that it may take some time until all sessions are put to the cache. If a user request collides with the short time where sessions are put to the cache it is possible that the request will fail, but in most cases a user should not mention anything at all.

Preparation

To enable session migration, the session cache need to be configured, this needs to be done for all Open-Xchange server that should be capable to migrate sessions

$ vim /opt/open-xchange/etc/groupware/sessioncache.ccf

[...]
jcs.auxiliary.SessionLTCP.attributes.TcpListenerPort=58849
jcs.auxiliary.SessionLTCP.attributes.UdpDiscoveryAddr=224.0.0.1
jcs.auxiliary.SessionLTCP.attributes.UdpDiscoveryPort=6789
jcs.auxiliary.SessionLTCP.attributes.UdpDiscoveryEnabled=true

In this case Open-Xchange is listening on port 58849 for incoming sessions and discovers other Open-Xchange session caches via UDP multicast on port 6789. Shortly after server startup all servers should connect to the cache. This can be checked by running netstat, this is an example with two Open-Xchange Servers:

OX1:

$ netstat -tulpa
tcp6       0      0 *:58849                 *:*                     LISTEN     27449/java
tcp6       0      0 oxhegw01.open-xch:58849 oxhegw02.open-xch:55499 ESTABLISHED27449/java

OX2:

$ netstat -tulpa
tcp6       0      0 *:58849                 *:*                     LISTEN     11816/java
tcp6       0      0 oxhegw02.open-xch:55499 oxhegw01.open-xch:58849 ESTABLISHED11816/java

Both groupware servers have connected to each other and are ready to accept sessions

Migration

This is what happens to a users session at the webinterface, as we can see at the users cookie, he is currently logged in the second groupware server ("OX-2"):

GET http://server.ox/ajax/calendar?action=all&columns=1%2C20%2C207&end=1215043200000&folder=25&session=6e3be7938169670c47fa4fe916045699&start=1214956800000 (34ms)
Cookie: JSESSIONID=41165f534d652a3e662d9c44b0b6efd439f310ad.OX-2

Now this servers is going to be shut down. First stop the sessiond bundle

$ /opt/open-xchange/sbin/stopbundle com.openexchange.sessiond

Wait some seconds until all sessions are put to the cache. Currently the best way to look at the migration is to watch the traffic on the port through that the session caches are connected:

$ ngrep -qd eth0 port 58849

If the traffic finished on that port all sessions are published to other OX machines. Now tell apache that this OX is not more able to fulfill requests. The balancer manager is an excellent tool for this. Look at the screen shot. Every OX can be put into a disabled mode. Further requests will the redirected to other OX machines.

Balancer manager.jpg

Now every existing session can continue to life on some other OX machine. You can stop now the OX instance and do updates or something else.

$ /etc/init.d/open-xchange-groupware stop

In some cases, requests and session migration collide. A error message is shown but the next request will succeed and does not terminate the users session:

The required service com.openexchange.sessiond.SessiondService is temporary 
not available. Please try again later. (SRV-0001,-1021469715-4)

The next request triggered by the user is answered by a Open-Xchange server that has taken over the session.

GET http://server.ox/ajax/calendar?action=all&columns=1%2C20%2C207&end=1215216000000&folder=25&session=6e3be7938169670c47fa4fe916045699&start=1215129600000 (26ms)
Cookie: JSESSIONID=9235ba164ca5ac3119cee006a92e4a574e31c32b.OX-1

The identifier of the server at the users cookie has been set to OX-1 and the user is able to continue working at this server without any interruption.

After migration

After updating or doing some administrational work on the shut down OX instance you can start again. But do not enable that OX instance in the balancer manager. First do some checks. Connect to the JMX management console of some others OX instance with this command

$ jconsole service:jmx:rmi:///jndi/rmi://127.0.0.1:9999/server

Go to the JCSCacheInformation MBean and trigger the operation getMemoryCacheCount for the SessionCache. In the screenshot you see 11 sessions that are not fully migrated. The client browser did not make a request in the mean time and still has the restarted OX instance in its JSESSIONID cookie.

SessionsInCache.png

If you would enable that OX instance now the clients request will be delivered to that instance but the clients session is not there because we migrated it to other OX caches. The request will fail with a not found session. Therefore we have to wait until the number of sessions in the cache is decreased to zero. Then all sessions are fully migrated and we can enable that OX instance again.