Two posts ago the chouchbase-manager for glassfish was presented and the previous one showed some numbers in a two glassfish server cluster. The conclusion was that a special sticky configuration was needed to transform the manager into a competitive option. From now on it manages a sticky property that, when set, makes the implementation to interact much less with the couchbase server.
A sticky configuration means that the balancer element always sends all the request for the same session to the same glassfish server. Using mod_jk this is done cos glassfish adds a special tag to the JSESSIONID which indicates the server that is attending the session, the tag is called jvmRoute. So the first access of the client (no cookie is set) is distributed to any of the all possible servers but the rest of them (JESESSIONID cookie marks the server) are sent against the same glassfish instance. This configuration assures that all the requests for a session are going to be processed by the same server and, therefore, a lot of couchbase operations could be saved. I am going to show the same diagram I presented before but using sticky processing.
As before the first method to be called is findSession (if the session was already created), the session is searched in the local map. If found that session is returned, if not found the session is got from couchbase. This method is more or less the same cos maybe the instance that was processing the session is down and the balancer is redirecting the request to a new server. But although the procedure is the same you have to realize that in sticky configuration the session is never read from couchbase again (in non-sticky the session is read from couchbase as many times as different servers are accessed for the first time). If the session is new the AppServer calls the createSession method. Sticky setup does the same process, the session is created locally and in couchbase.
When the session is requested to be locked (lockForeground) no access to couchbase is done. In non-sticky the session had to be locked in couchbase (preventing modifications for any other instance) but now sticky configuration assures that no other server is going to modify the same session, so the lock is done only locally (internal JVM). This part is the main improvement.
Session is managed by the JavaEE application.
Same as before if the session is dirty (modified by the application) it is saved in couchbase and if only accessed it is touched (refreshing expiration). In this step no big change is performed but in refresh only one method is executed (remember that couchbase has no touchAndUnlock and that meant two calls were needed in non-sticky when refreshing). Same as in non-sticky if the session is only accessed for a long time a save is forced. Cos the session is re-used the attributes are never cleared (in non-sticky attributes are cleared to save space and to check if the solution worked).
Deletion and expiration are managed just in the same way. Local timestamps are managed but a final call against couchbase is performed to check that the session is finally expired in the repo. The difference here is that now the sticky configuration assures that the local timestamps are true (cos there is no access from other instance, the local timestamps are the correct ones for sure). The repository check for expiration could even be saved (cos now timestamps are valid) but I preferred to only trust in couchbase, besides this call is only done a few times (normally just once) per session life-cycle.
So the idea is quite simple, sticky configuration improves the performance cos the manager can trust that the session is only being modified by that instance. So in normal update or refresh operation only one operation against couchbase is done (set or touch) and, in general, one operation is always saved (in the four operations the first getAndLock is not necessary). Besides this setup does not perform any lock/unlock operation in couchbase, operations which, presumably, are more expensive. Sticky solution guarantees High Availability, if a glassfish instance goes down the balancer redirects its requests to another instance and the new instance will recover the session from couchbase. Obviously this solution does not work in non-sticky balancer configuration. One final comment, couchbase does not have a set operation that returns a cas (cas is only returned in get ops), it would be nice a kind of sets operation that would save the object and return the new cas. Cos there is not such operation, no cas is used in sticky configuration.
After the proper code changes I performed the same tests that were done in the previous post but just using sticky and non-sticky couchbase manager setups (again the sheet is here). I do not know why, times this time are a little better (even non-sticky configuration gets better performance) but what it is clear is that sticky improves the solution a lot.
My personal conclusion is that sticky configuration is as fast as a replicated solution, but with the enormous advantage of only storing in the internal map the sessions each instance is managing (in replication, all sessions are stored in all instances). In order to improve the non-sticky solution I have a new idea (but this will be commented in a new entry). But take in mind that the cost of non-sticky will never be zero. Besides I would need some collaboration from couchbase guys, as I said before, times would be better if some methods were implemented (touchAndUnlock and unlockAndDelete) and if buckets were more configurable (no disk storing for example). I think the couchbase-manager is ready to be presented, I will try to clean up the whole solution, document installation and configuration, manage errors correctly and I also need to decide the project license (I am thinking to distribute it only with GPLv2 with the classpath exception but comments are welcome, I have no idea about licenses).
Cheerio!
Comments