[Design of EJB 3.0] - Transaction behavior of clustered SFSB caching
by bstansberry@jboss.com
Discussion thread related to http://jira.jboss.com/jira/browse/EJBTHREE-845.
Original intent of the JIRA was to examine if it made sense to have the JBoss Cache used for SFSB replication participate in any transaction associated with the request.
My take on this was that this was a bad idea. If JBC participates in the transaction, and the tx rolls back, any changes made to the cache during the course of the transaction will be rolled back. The effect is the copy of the bean in the cache will be reverted to the version that existed before the tx started (even if the bean was removed during the tx). While that kind of behavior might be something some users would enjoy, IMHO it's not something the SFSB cache should be doing.
However, a side effect of not using transactions is we currently replicate the SFSB after every invocation. Very chatty, and wasteful if a tx is in effect. If a tx is in effect, the client side proxy won't allow a failover anyway after a call has reached a server. So there's no point replicating state prior to tx commit.
A possible improvement we discussed last month in Austin is to use the JBC BatchModeTransactionManager to control replication. BTM is basically a simple TM with functionality sufficient to trigger the JBC's "batch" functionality. See http://wiki.jboss.org/wiki/Wiki.jsp?page=BatchModeTransactionManager .
Basic idea here is:
1) StatefulReplicationInterceptor has reference to BTM. Uses it to check if there is a BTM tx associated with the caller thread. If yes, call proceeds as normal.
2) If no, check if there is a regular JTA tx associated with the invocation. If yes, start a BTM tx, and register a Synchronization with the JTA tx.
2a) In afterCompletion() callback, commit the BTM tx, thus triggering replication. (Hmm -- doing work in afterCompletion() isn't so good).
We commit the BTM tx whether the JTA tx completes successfully or not. Committing the BTM tx is what causes replication to occur; good or bad the current state of the cache needs to replicate to ensure consistency across the cluster.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4077944#4077944
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4077944
18 years, 7 months
[Design of Clustering on JBoss (Clusters/JBoss)] - Re: Transaction Sticky LB policy for 4.2/trunk
by galder.zamarreno@jboss.com
What do you mean by existing semantics? Do you mean existing defaults?
TransactionSticky LBP would do:
Object txStickyTarget = invocation.getTransientValue("TX_STICKY_TARGET");
| if (txStickyTarget != null && familyClusterInfo.getTargets().contains(txStickyTarget))
| {
| log.trace("transaction bound target exists: " + txStickyTarget);
| return txStickyTarget;
| }
|
| return chooseNewTarget(familyClusterInfo, invocation);
where chooseNewTarget is:
private Object chooseNewTarget(FamilyClusterInfo familyClusterInfo, Invocation invocation)
| {
| Object newTarget = super.chooseTarget(familyClusterInfo, invocation);
| log.trace("new target chosen: " + newTarget);
| invocation.getTransientPayload().put("TX_STICKY_TARGET", newTarget);
|
| return newTarget;
| }
If there's no transaction, txStickyTarget will be null. txStickyTarget will also be null in the very first call of a transaction.
This is because at the beginning of each invocation, UnifiedInvokerHAProxy checks whether there's a running transaction and whether this transaction has a target in the map. If both are true, it adds the txStickyTarget to the transient invocation payload.
If there's no transaction running, or is the first call of a transaction, the txStickyTarget will be null falling back on standard RoundRobin LBP and will also be added to the transient invocation payload.
Adding txStickyTarget to the transient invocation payload if no transactions are running would have no secondary effects, because any access/check in the txFailoverAuthorizations would require an existing tpc. However, I agree that adding it is an unncessary operation in this situation.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4077915#4077915
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4077915
18 years, 7 months
[Design of Clustering on JBoss (Clusters/JBoss)] - Transaction Sticky LB policy for 4.2/trunk
by galder.zamarreno@jboss.com
A 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=TransactionStickyLoadBalancePoli...
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?
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4077902#4077902
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4077902
18 years, 7 months
[Design of JBoss ESB] - Re: How to use FaultTo
by jaroslaw.kijanowski
Ok, I create now an ESB aware message, where I define the FaultTo that way:
| PortReference pr = new PortReference();
| pr.setAddress("jms://localhost/queue/quickstart_exceptions_faults_receiver");
| pr.addExtension("jbossesb:java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
| pr.addExtension("jbossesb:java.naming.provider.url", "localhost");
| pr.addExtension("jbossesb:specification-version", "1.1");
| pr.addExtension("jbossesb:connection-factory", "ConnectionFactory");
| pr.addExtension("jbossesb:message-selector", "serviceName='ExceptionCaughtServiceReceiver'");
| EPR epr = new EPR();
| epr.setAddr(pr);
| .
| .
| .
| esbMessage.getHeader().getCall().setFaultTo(epr);
| ListenerUtil.tryToDeliver(esbMessage, category, name);
|
Then, while processing the message, I throw an ActionProcessingException/ActionProcessingFaultException but the fault message still doesn't want to go to the quickstart_exceptions_faults_receiver queue:
18:58:55,337 ERROR [ActionProcessingPipeline] Failed to send error to address EPR: PortReference < <wsa:Address jms://localhost/queue/quickstart_exceptions_faults_receiver/>, <wsa:ReferenceProperties jbossesb:java.naming.factory.initial : org.jnp.interfaces.NamingContextFactory/>, <wsa:ReferenceProperties jbossesb:java.naming.provider.url : localhost/>, <wsa:ReferenceProperties jbossesb:specification-version : 1.1/>, <wsa:ReferenceProperties jbossesb:connection-factory : ConnectionFactory/>, <wsa:ReferenceProperties jbossesb:message-selector : serviceName='ExceptionCaughtServiceReceiver'/> >.
org.jboss.soa.esb.couriers.CourierException: org.jboss.soa.esb.couriers.CourierException: Unknown destination type
at org.jboss.internal.soa.esb.couriers.JmsCourier.deliver(JmsCourier.java:147)
How should I define the EPR?
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4077879#4077879
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4077879
18 years, 7 months