Table of Contents
This chapter describes the concept of EJB clustering and how to configure main functions of EJB.
In order to use the failover and load balancing functions in EJB, individual beans may be deployed across several EJB engines to form a cluster. Clustering is accomplished on the component level (individual beans) and may be used by Stateless/Stateful session beans and entity beans. A Message Driven Bean (MDB) is not a clustering target.
JEUS EJB clustering has the following two functions:
The following figure explains two major functions of EJB clustering, load balancing and failover.
If you deploy modules that need clustering, they are all bound to the same name in the Naming Service. Using this name, client can perform load-balancing and failover. Therefore, even if you deploy the same module by binding it to the Naming Server using a different name, the module will not be included in the cluster.
Stateful session beans use the JEUS session manager for failover. There is only one session manager for each EJB engine, and therefore the clustering scope of a bean should not be dependent on the individual bean. For example, if bean A is bound to EJB engine1 and EJB engine 2, and bean2 is bound to EJB engine1 and engine 3, the session manager wrongly assumes that the bean A and B are clustered on EJB enigne1, engine2, and engine3.
The following explains major functions of EJB clustering.
When a client requests for bean A through lookup or injection, a Naming Server randomly selects and returns one of the 3 beans from one of the 3 EJB engines. The client will then interact directly with the bean from the selected EJB engine through the business interfaces in a standard way.
This implies that each of the three beans will receive an equal share of requests. Thus, we potentially increase the maximum system performance by three times than when having only one engine that services all the requests (not counting the small overhead associated for load balancing).
Failover is the ability to recover from a failure in a single EJB service (e.g., OS crash, network disruption, or severe EJB engine failure).
There are two types of recoveries that the JEUS system can perform:
Re-issuing of a pending (incoming) request to a different bean than the one originally intended if that bean is found to be inaccessible when the client's request is received.
Simply perform load balancing algorithm by excluding the failed/unreachable EJB engine. Select a working, accessible bean or engine and process the new client request.
In JEUS, this fail over re-routing of a request is actually handled by the EJB stub from the client side. This stub is called an "active stub" and is simply a wrapper class for the standard EJB interfaces. The difference when using a wrapper class is that they contain logic that determines if the currently connected bean or EJB engine has failed. If a failure is detected, the active stub, on its own initiative, will request JNDI server for a new stub on behalf of the currently running EJB engine (Point 5 in [Figure 6.1]).
Re-issuing a request in progress to another bean in the cluster if the current bean experiences some kind of runtime failure
Recovery method is very limited in this situation. If the failure is detected during a request, we have no way of telling how much the bean has processed the request and which runtime error occurred at the time of the failure. Simply re-invoking the same method again in a different bean in the cluster could potentially be dangerous, since that may lead to other side effects.
To make this clear, consider a bean instance A. One of its business methods increments the value of a database field by one (e.g., i++). Let's assume that a failure occurs right after the increment is executed. In response to the failure, if you simply try to re-invoke the same business method through another bean B, the method will re-execute the increment. Thus, we would end with an inconsistent, erroneous value in the database. You can avoid such a critical error by declaring an idempotent method, which is described next.
The difference between the previous two scenarios is when the error condition is detected: before invoking a remote EJB business method or while the bean is processing the request.
An Idempotent method is a getter method that has no side effects. This means that we can invoke an idempotent method with the assurance that no states (e.g., instance variables, database fields, etc.) are changed during its execution.
An idempotent method can be used to deal with the second recovery issue of "6.2.2. Failover(EJB Restoration)": if a method is idempotent, we can safely re-invoke it on a different bean even if the first attempt to invoke the method failed during execution. However, if a method is not idempotent, there is nothing we can do in such a scenario. It is better to throw an exception than re-executing the method when a runtime error occurs. Hence, EJB failover performs better when more Idempotent methods are used. The status of the business method must be identified before configuring it.
A stateful session bean uses JEUS session manager to back up sessions. Generally, session state changes according to each business method invocation. Thus the session manager requests for a back up of sessions to JEUS session manager whenever a method is called and the result is returned in JEUS. This backup process is also called Session replication.
JEUS session manger can copy sessions either synchronously or asynchronously, which is called a replication mode in JEUS.
Both methods have pros and cons, thus JEUS lets the user select the mode according to the bean and business method characteristics. The user also can specify not to use session replication. For more information, refer to "6.3. EJB Clustering Configuration".
In JEUS, by default, session replication uses the Sync mode for stateful session beans that are clustered. But this configuration can be change by the user.
EJB clustering can be configured either by using annotation in the bean class or the jeus-ejb-dd.xml file. Configuration items for clustering include the Bean to be configured, idempotent methods of the bean, and session replication mode of each bean or method.
This section shows how to configure annotation and descriptor (xml) for clustering through examples.
Configure classes or methods of a clustered bean by using annotation as follows.
[Example 6.1] Clustering Configuration through Annotation:<<CounterEJB.java>>
package ejb.basic.statelessSession; import javax.ejb.Stateful; import jeus.ejb.Clustered; import jeus.ejb.Replication; import jeus.ejb.ReplicationMode; @Stateful(name="counter", mappedName="COUNTER") @Clustered @Replication(ReplicationMode.SYNC) @CreateIdempotent public class CounterEJB implements Counter, CounterLocal { private int count = 0; public int increaseAndGet() { return ++count; } @Replication(ReplicationMode.NONE) public void doNothing(int a, String b) { } @Idempotent public int getResult() { return count; } @Idempotent @jeus.ejb.Replication(ReplicationMode.ASYNC) public int getResultAnother() { return count; } ... }
Descriptions for each class are as follows:
The following configuration for each clustered bean can be configured inside the <clustering> tag in the JEUS EJB module DD file (jeus-ejb-dd.xml).
[Example 6.2] Clustering Configuration Using XML: <<jeus-ejb-dd.xml>>
<jeus-ejb-dd>
. . .
<beanlist>
. . .
<jeus-bean>
<ejb-name>counter</ejb-name>
<export-name>COUNTER</export-name>
. . .
<clustering>
<enable-clustering>true</enable-clustering>
<ejb-remote-idempotent-method>
<method-name>getResult</method-name>
</ejb-remote-idempotent-method>
<ejb-remote-idempotent-method>
<method-name>getResultAnother</method-name>
</ejb-remote-idempotent-method>
<create-idempotent>true</create-idempotent>
<replication>
<bean-mode>sync</bean-mode>
<methods>
<method>
<method-name>doNothing</method-name>
<method-params>
<method-param>int</method-param>
<method-param>java.lang.String</method-param>
</method-params>
<mode>none</mode>
</method>
<method>
<method-name>getResultAnother</method-name>
<method-params>
<method-param>void</method-param>
</method-params>
<mode>async</mode>
</method>
</methods>
</replication>
</clustering>
. . .
</jeus-bean>
. . .
</beanlist>
. . .
</jeus-ejb-dd>
Descriptions for each tag are as follows:
Tag | Description |
---|---|
<enable-clustering> | Completely activates or inactivates the clustering of the bean. |
<ejb-remote-idempotent-method> | Defines idempotent methods among bean methods. (Refer to @jeus.ejb.Idempotent in"6.3.1. Clustering Configuration through Annotation"). |
<ejb-remote-idempotent-exclude-method> | Defines methods that need to be excluded from methods that are defined as idempotent. This has precedence over the <ejb-remote-idempotent-method> setting, but is used in the same way. |
<ejb-home-idempotent-method> | Defines idempotent methods among methods defined in 2.x style home interface (Refer to @jeus.ejb.CreateIdempotent of "6.3.1. Clustering Configuration through Annotation"). This is used in the same way as <ejb-remote-idempotent-method>. |
<ejb-home-idempotent-exclude-method> | Defines methods that need to be exclude from idempotent methods defined in 2.x style home interface. This has higher priority over <ejb-home-idempotent-method>, but is used the same way as <ejb-remote-idempotent-method>. |
<create-idempotent> | Defines whether to declare a bean as idempotent when creating a session bean. |
<replication> | Specifies the session replication mode at the bean or method level. For more information, refer to "6.2.4. Session Replication" and [Example 6.2]. |
In order for the previously defined bean clustering to work, you must consider these issues.
All beans participating in clustering should have the same settings inside the <clustering> element.
In order to create a cluster, beans should have the same <export-name> value.
In order to execute stateful session beans in a clustered environment, node clustering and session manager configurations are additionally required.
To configure a Session Manager using the WebAdmin,
Click [Clusters] on the left pane to go to the Clusters page. Select a cluster from the list to configure a Session Manager. On the Cluster page, click the [Session Router Config] tab.
Click [Lock & Edit] to change to the edit mode to dynamically applying the changes.
Configure the required Session Router properties and then click [OK].
To apply the changes on the server, click [Apply Changes] on the left pane of the screen.
For more information about Session Manager settings, refer to JEUS Session Management Guide. "2.7. Session Server Configuration".
A client may use the EJB reference (Stub) by caching it or using injection, instead of doing a look up each time. In this case, failover may not be performed even though there is another alive end-point. This may occur when MSs, that were alive in the EJB end-point list at the time of the lookup, are not alive, and only new MSs that started after the lookup are alive.
EJB references are looked up internally at the time of the failover, and a new EJB reference is sent to the client. However, if all deployed MSs are terminated when you are doing a lookup of an EJB reference that is in use, failover cannot be performed even though there is a new EJB end-point that is deployed after the lookup and is able to provide the service.
In the previous case, the termination of existing MSs means that the nodes are abnormally terminated or shut down, or an EJB end-point is undeployed and cannot provide the service. The deployment of a new EJB end-point can mean that the time when the new MS was included to a cluster was too late (when EJB reference is already looked up and used), downed MS was restarted too late, or the undeployed EJB end-point was redeployed too late.
This may occur when two MSs are used for active/backup clustering. The following is an example scenario.
A single EJB engine exists in each MSs: A, B, and C. A client looks up EJB references for the first time and caches them.
EJBs are deployed to A, B, and C, and EJB on A is obtained as a result of a lookup.
EJB on A is abnormally terminated during use. EJB on B is obtained through lookup internally and it continues to provide the service.
EJB on B is undeployed, and EJB on C is obtained through lookup.
At this time, EJB on B is redeployed, and C is abnormally terminated.
In this case, when EJB reference of C is looked up, EJB end-point of B was undeployed and was redeployed after EJB on C was looked up. When C was terminated, B was still alive, but failover was not performed. However, if B was not deployed or undeployed, but was abnormally started or terminated, failover is performed. This is because the status of the engine for rebooting is checked for abnormal terminations.
It is possible to avoid the previous situation, if a new EJB Reference is looked up again and a new end-point list is obtained.