Web application clustering involves two aspects: setting up an HTTP load balancer, and telling JBoss to make the application's user sessions HA. How to do the former depends on what load balancer you choose (mod_cluster
is our suggested choice); the latter could not be simpler—just add the <distributable/>
tag to your application's web.xml
file.
Let's see in concrete how to pursue both steps.
You have several choices available in order to achieve load balancing of your HTTP requests; you can opt for a hardware load balancer that sits in front of your cluster of servers, or you can choose from the many available software solutions for JBoss AS, which include the following:
mod_jk
to route your requests to your nodesmod_proxy
that configures Apache to act as a proxy server and forwards requests to JBoss AS nodesmod_cluster
to achieve dynamic load balancing of your requests.Here we will illustrate how to get started with mod_cluster
. The advantage of using mod_cluster
against other options can be summarized in the following key points:
As a matter of fact, when using a standard load balancer such as mod_jk
, you have to provide a static list of nodes that are used to spread the load. This is a very limiting factor, especially if you have to deliver upgrades to your configuration by adding or removing nodes or you simply need to upgrade releases used by single nodes. Besides this, using a flat cluster configuration can be tedious and prone to errors, especially if the number of cluster nodes is high.
When using mod_cluster
, you can dynamically add or remove nodes to your cluster, because cluster nodes are discovered through an advertising mechanism.
In practice, the mod_cluster
libraries on the httpd side send UDP messages on a multicast group, which is subscribed by AS7 nodes. This allows AS7 nodes the automatic discovery of httpd proxies where application lifecycle notifications are sent.
The next diagram illustrates this concept better:
The mod_cluster
module is implemented as a core AS 7 module, which is a part of the distribution, on the httpd side as a set of libraries installed on the Apache web server.
On the JBoss AS 7 side, you can find already bundled the mod_cluster
module's subsystem as part of the clustered configuration file. You can locate it either in the standalone-ha.xml
file or in the standalone-full-ha.xml
(and of course in the domain.xml
file) configuration file:
<subsystem xmlns="urn:jboss:domain:modcluster:1.0"> <mod-cluster-config advertise-socket="modcluster"/> </subsystem>
The subsystem contains just a bare-bones configuration that references its socket binding through the advertise-socket
element:
<socket-binding name="modcluster" port="0" multicast-address="224.0.1.105" multicast-port="23364"/>
On the Apache web server side, we have to install the core libraries, which are used to interact with mod_cluster
. This is a very simple procedure: point the browser to the latest mod_cluster
release at http://www.jboss.org/mod_cluster/downloads.
Once the binaries are downloaded, extract the archive to a folder; then, navigate into the extracted folder. The mod_cluster
binaries consist essentially of a bundled Apache web server with all required libraries installed.
The bundled Apache web server configuration, however, requires defining from scratch all the web server key elements, such as server root, binding ports, loaded modules, and directories' configuration. I personally find it much more immediate to use my own Apache web server 2.2 installation; just pick up the modules from the mod_cluster
bundle, and copy them in the modules
folder of your Apache web server.
So, whether you choose to use your own Apache web server or the bundled one, you have to load the following libraries into your httpd.conf
file:
LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_ajp_module modules/mod_proxy_ajp.so LoadModule slotmem_module modules/mod_slotmem.so LoadModule manager_module modules/mod_manager.so LoadModule proxy_cluster_module modules/mod_proxy_cluster.so LoadModule advertise_module modules/mod_advertise.so
Each of these modules covers an important aspect of load balancing, listed as follows:
mod_proxy
and mod_proxy_ajp
: These are the core modules that forward requests to cluster nodes using either the HTTP/HTTPS protocol or the AJP protocol.mod_manager
: This module reads the information from AS 7 and updates the shared memory information in conjunction with mod_slotmem
. The mod_proxy_cluster
module is the module that contains the balancer for mod_proxy
.mod_advertise
: This is an additional module that allows httpd to aadvertise via multicast packets—the IP and port—where the mod_cluster
module is listening.The next part of the configuration that we need to add is the core load balancing configuration:
Listen 192.168.10.1:8888 <VirtualHost 192.168.10.1:8888> <Location /> Order deny,allow Deny from all Allow from 192.168.10. </Location> KeepAliveTimeout 60 MaxKeepAliveRequests 0 ManagerBalancerName mycluster ServerAdvertise On </VirtualHost>
Basically, you have to replace the 192.168.10.1
IP address with the one where your Apache web server listens for requests, and replace the port value of 8888
with the one you want to use for communicating with JBoss AS.
As it is, the Apache virtual host allows incoming requests from the subnetwork 192.168.10
.
The KeepAliveTimeout
directive allows reusing the same connection within 60 seconds. The number of requests per connection is unlimited, since we are setting MaxKeepAliveRequests
to 0
. The ManagerBalancerName
directive provides the balancer name for your cluster (defaults to mycluster
).
Most important for us is the ServerAdvertise
directive, which sets to On
and uses the advertise mechanism to tell the JBoss AS to whom it should send the cluster information.
Now, restart the Apache web server and the single application server nodes. If you have correctly configured the mode cluster on the httpd side, you will see that each JBoss AS node will start receiving UDP multicast messages from mod_cluster
.
Clustering web applications requires the least effort for the developer. As we have just discussed, all you need to do to switch on clustering in a web application is to add the following directive in the web.xml
descriptor:
<web-app>
<distributable/>
</web-app>
Once your application ships with the distributable stanza in it, the cluster will start, and provided you have correctly designed your session layer, it will be load balanced and fault tolerant.
In order to support in-memory replication of HTTP session states, all servlets and JSP session data must be serializable.
Additionally, in an HTTP servlet that implements javax.servlet.http.HttpSession
, you need to use the setAttribute
method to change the attributes in a session object. If you set attributes in a session object with setAttribute
, by default the object and its attributes are replicated using the Infinispan API. Every time a change is made to an object that is in the session, setAttribute
should be called to update that object across the cluster.
Likewise, you need to use removeAttribute
to remove an attribute from a session object.
In the applications included in this book, we have used JSF and CDI API to manage the web session. In this case, we transparently replicate the other server nodes to the beans, which are marked as @SessionScoped
.
Clustering JSF-based applications requires special attention in case you are dealing with both HTTP and EJB sessions created by SFSB. In the earlier servlet-centric frameworks, the usual approach was to store references of Stateful Session Beans in javax.servlet.http.HttpSession
. When dealing with high-level JSF and CDI Beans, it is vital to provide a @SessionScoped
controller to your application, which gets injected in the SFSB reference, otherwise you will end up creating a new Stateful Session Beans at each request.
The following is an example of how to adapt your Ticket CDI application (described in Chapter 4, Learning Context Dependency Injection) to a clustered environment. At first, as we said, we need to include the distributable stanza in your web.xml
file to trigger clustering modules:
<web-app> <distributable/> </web-app>
Next, apply the same changes to the TheatreBox
singleton that we described in the Turning your cache into a distributed cache section:
@Singleton @Startup public class TheatreBox { @Resource(lookup="java:jboss/infinispan/container/cluster") private CacheContainer container; // Apply the same changes described in // "Turning your Cache into a distributed cache"section }
Since our controller component is bound to a @SessionScoped
state, you don't need to apply any changes in order to propagate your session across server nodes:
@SessionScoped @Named public class TheatreBookerBean implements Serializable { }
Finally, remember to include the Infinispan dependency in your META-INF/MANIFEST.MF
:
Dependencies: org.infinispan export
Once your application is deployed on both nodes of your cluster, you can test it by hitting the Apache web server (http://localhost:8888/ticket-agency-cluster
in our example) and start booking tickets:
Since the mod_cluster
subsystem is configured by default to use sticky web sessions, all subsequent requests from the same client will be redirected to the same server node. Therefore, by shutting down the sticky server node, you will get evidence that a new cluster view has been created and you can continue shopping on the other server node:
3.149.253.210