Transaction Sticky LB policy for 4.2/trunk
galder.zamarreno Aug 24, 2007 2:26 PMA few months ago, out of a Skype chat between Brian and myself, the following jira was created: http://jira.jboss.com/jira/browse/JBAS-4455
A few weeks ago, a user came up with exactly the same request, and out of it, an example 4.0.x implementation was created, see: http://wiki.jboss.org/wiki/Wiki.jsp?page=TransactionStickyLoadBalancePolicy40x
It is my intention now, seeing the user's interest in having this in 4.2, to implement this in trunk and 4.2. I'd like to provide a transanction sticky load balance policy for both transactions started via client side UserTransaction and within AS that involves:
1.- Enhancing UnifiedInvokerHAProxy so that:
1a- txFailoverAuthorizations is keyed on tpc (transaction propagation context) rather on javax.transaction.Transaction. By doing this, both client side transactions and in-AS transactions are covered.
1b- for txFailoverAuthorizations, to associate a target per tpc, which is the transaction sticky target. This target would be the typical output from a LoadBalance policy.
1c- whenever an invocation comes in, it checks whether there's a target associated with the incoming tpc within the txFailoverAuthorizations map. If it is, it'll add the target to the transient invocation payload.
1d- invocationHasReachedAServer() associates, if there's no target for that the current running tpc (i.e it's the first invocation of the tx and has already come back from the server), the chosen target with the tpc in the txFailoverAuthorizations map.
1e- rename txFailoverAuthorizations to something more meaningful.
1f- assuming there's no other external usages, encapsulate the use of the renamed txFailoverAuthorizations. This map is currently public.
2.- Create a new load balance policy called TransactionSticky that:
2a- checks whether there's any target in the invocation transient payload map (take in account 2c that comes first and would have added the target to the transient payload, if the transaction had a target in the txFailoverAuthorizations) and whether this target is part of the familyClusterInfo (if it isn't, then this is an unavailable target and should not be used), in which case, returns this target.
2b- extends RoundRobin, so if there's no target in the transient paylod, or the target is invalid, then a new target is chosen based on RoundRobin chooseTarget method implementation. With this, we achieve tx1 invocations to node1, tx2 to node2, tx3 to node1, tx4 to node2...etc.
For the 4.0.x implementation, I have:
1- tested Client side user transactions
2- tested how different ejb invocations (including usage of different ejbs) within a transaction hit the same node for the duration of the transaction.
3- created mock implementations of my invoker and invoker proxy implementations so that they can simulate different failure scenarios. This led to deploying mock EJB versions that used mock invoker and invoker proxy based invoker proxy bindings and container configurations.
4- failure scenarios tested are:
4a- within a transaction, failure of the Nth invocation before reaching the server, i.e. before proxy.invoker(). This failure should be propagated back to the client.
4b- within a transaction, failure of the Nth invocation after reaching the server. This failure should be propagated back to the client because the transaction had already started in the server.
4c- within a transaction, failure of the 1st invocation in the 1st server (as GenericClusteringException.COMPLETED_NO) but success in the second, that should be transparent to the client as the failover is allowed.
4c- within a transaction, failure of the 1st invocation in the 1st server (as GenericClusteringException.COMPLETED_YES). This failure should be propagated back to the client because the transaction reached the server and so failover is not allowed.
4d- within a transaction, failure of the 1st invocation in both servers. This failure should be propagated back to the client.
On top of the tests created for 4.0.x, I hope to add the following to 4.2/trunk:
1.- tests with in-AS started transactions, i.e. with EJBs as clients.
2.- concurrent EJB invocations (using different transactions) to guarantee the safety on the UnifiedInvokerHA/UnifiedInvokerHAProxy if they don't exist already.
Thoughts?