Tuesday, 4 June 2013

File Upload is Easy in JSF2.2

To bring the File Upload feature in Java based web application is one of the difficult and complex job, we need to dependent on 3rd party libraries like Apache Commons FileUpload Libraries. These libraries codes are complex and most of them boilerplate code.

If we are using Java Server Faces (JSF), we have the page with some fields and file upload menu the its add more complexity, fields are binded to backing bean but these file uploads components are need to tie up with some 3rd party file upload libraries.

In Primefaces provide easy way to do the file upload in JSF web application, even though primefaces internally used the same Apache Commons FileUpload Libraries, but provide simple JSF tags. We need configure  some listeners.

In Servlet 3.0 they introduced the Part Interfaces and @MultiPartConfig annotations for easy way to do the file upload without any 3rd party libs, Servlet 3.0 is part of Java EE 6 specification. so any servlet 3.0 implementation servers  like Tomcat 7, Jboss 6, GlassFish 3 they can get benefit of servlet 3.0. but this feature is not available in JSF 2.1. so again still it's complex to use file upload in JSF, because we need to mix servlet and JSF backing bean.

Recently JSF 2.2 is released as part of Java EE 7 specification. Now this specs are final and its going to release Q2 of 2013.

Check my post about An introduction to JSF 2.2

in this post i going to show the File Upload feature with a demo

At last JSF 2.2 is added the File Upload component, so we just use <h:inputFile> tag to make the file upload web application so easily, and this component use the Part interface, which its introduced its part of Servlet 3.0. so this JSF2.2 libraries is working perfectly with Tomcat 7 (because tomcat 7 is implemented the Servlet 3.0 spec).

To bring the File Upload feature we need to follow 3 step process

  1. Add <h:inputFile> tag in JSF page
  2. Add enctype="multipart/form-data" attribute in enclosing <h:form> tag
  3. Create the field in Backing bean with Part data type.

Setup the Environment

JSF 2.2 lib are part of Java EE 7, but we can include as a libraries into existing Java EE 6 platform without upgrading the server.
we can get the JSF 2.2 libraries (Mojarra implementation) from here

Step 1:  Add <h:inputFile> tag in JSF page

In JSF page add the <h:inputFile> tag where we need file upload component

  <h:inputFile value="#{demoBean.file1}" />

here i bind the value property to file1 field, which data type is Part, check the third step


Step 2:  Add enctype="multipart/form-data" attribute in enclosing <h:form> tag

When u want file upload feature then we need to inform the browser that form may contain multiple normal text input field  and some file upload component, so prepare the POST request in special form, like parts by part with special delimiter boundary.
 <h:form enctype="multipart/form-data">
</h:form>

so index.xhtml file looks like

    
        Facelet Title
    
    
        Hello from Facelets
        
        
            

            
             

            
        
    




Step 2:  Create Backing Bean

now create the backing bean for this page. we need to create the fields for input File component with Part type. Part interface is introduced in servlet 3.0 for represent the file chunks sent by browser, JSF 2.2 use this Part interface, Using the Part interface we can get the header information of each file chunk sent by browser, these header contain the file name and other meta information about the file.

Part interface also contain write() method to write the file contents into specified server location, or u can get the InputStream then we can process it.

DemoBean.java

import java.io.IOException;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.servlet.http.Part;


/**
 *
 * @author ramki
 */
@ManagedBean
@SessionScoped
public class DemoBean {

    private Part file1;
    private Part file2;

    // getters and setters for file1 and file2

    public String upload() throws IOException {
        
        file1.write("F:\\data\\"+getFilename(file1));
        file2.write("F:\\data\\"+getFilename(file2));
        return "success";
    }

    private static String getFilename(Part part) {
        for (String cd : part.getHeader("content-disposition").split(";")) {
            if (cd.trim().startsWith("filename")) {
                String filename = cd.substring(cd.indexOf('=') + 1).trim().replace("\"", "");
                return filename.substring(filename.lastIndexOf('/') + 1).substring(filename.lastIndexOf('\\') + 1); // MSIE fix.
            }
        }
        return null;
    }
}


here we need get the file name from the Header of the chunk, so there is boilerplate code can do, here i don't like this method :-(

there is no direct method to retrieve the file name. so use this code we can get the name of the file is uploaded by client, then using write method we can store into server.


Get my sample project from my Github or download from here

For more information (step by step) see the screencast

Screencast

An Introduction to JSF 2.2

Recently Java EE 7 specification goes into final. Next week (June 12) oracle going to release the Java EE 7 specification and Glass Fish 4 as reference implementation to general availability.

Java EE 7 adds more features like JSF 2.2, Servlet 3.1, Json Processing, websocket support, etc..
click here about the spec.

In this post i'm going walk through in JSF 2.2

JSF 2.2 is added more features, and JSF as  a main presentation layer of Java EE platform. compare to JSP, jsp is not getting more feature, they just add maintenance release.

Features of JSF 2.2

  • File Upload Component
  • Faces Flow
  • HTML5 Support
  • Cross Site Request Forgery Protection (CSRF)
  • Multi-Templating

File Upload Component


This is most awaited feature in JSF, now we can build the file upload feature in web application without any 3rd party libraries.

i am going to cover this topic in another post.

Faces Flows


Faces flows provides to create the JSF web application in modular way, each module is self contained pages , own backing beans and entry and exit points. Its make the module more reusable.

Faces flows are inspired from Spring Web Flows and Oracle Task Flows

Arun Gupta described his post about Faces Flows

HTML5 Support


HTML5 is future of the web, old JSF libraries are doesn't support HTML5 tags and attributes like placeholder attribute in input field tag, etc.
  <h:inputText   value="#{backingBean.field}"   p:placeholder="Enter text"  />

Cross Site Request Forgery Protection (CSRF)


CSRF is one kind of security attack, Its make the request on existing session.

For example i opened the Tomcat Manager web application and i logged in, now i try to open another web site in different tab, now that website try to execute the code like
http://localhost:8080/manager/html/stop?path=/app1

then browser make the request to that server (localhost:8080), browser already have session, so that server stop the application.

so we need to add CSRF protection token for every request, if token is not found or invalid then that request is not proceed further, server ignores the request

tomcat 7 uses own CSRF token
http://localhost:8080/manager/html/stop?path=/app1&org.apache.catalina.filters.CSRF_NONCE=CEF9F082EF983140038CF804CA81F29E

here tomcat 7 adds the CSRF token

now JSF 2.2 we can declaratively add the CSRF token to protecting the resources from CSRF attacks


Multi - Templating


Multi Templating is another feature to add more templates (Layout, skins), to web applications.
so we can change the template in run time like wordpress we can change the themes,
just put the theme jar file in classpath, Java platform discovered and apply the templates.


If u have any comments welcomed






Monday, 28 January 2013

Tomcat Clustering Series Part 5 : NginX as Load Balancer

Hi this is my fifth part of the Tomcat Clustering Series. In this post we are going to discuss how to replace Apache httpd load balancer to Nginx as a load balancer. [Check the video below for better understanding]

Hi i finished Tomcat Clustering Series. In these series we have 2 big setups needed for Tomcat Clustering
  1. Setup and configure the Load Balancer
  2. Configure the Session Replication in Tomcat.




In first setup, we configure the Load Balancer using Apache httpd web server. Its open source and widely used.
Second setup is session replication in Tomcat through modify/add <cluster> tag in server.xml file. These tomcat instance may run on single machine or different machine.



In our Tomcat Clustering Series, the big part is configure the Load balancer (Apache httpd web server). Because there are lots of steps are involved
  1. Install the Apache httpd web server from either source or repo
  2. Compile and install the mod_jk connector
  3. Create the workers.properties file (add tomcat IP and ajp port information )
  4. Configure into httpd.conf file (Add mod_jk related settings)
these setups are take more time and very difficult to debug.

Is there is any alternative to load balancer?
    Yes, Nginx its emerging web server. this post we are going to discuss how to setup nginx as a load balancer in our tomcat cluster.

What is Nginx?
      Nginx is open source and alternative to Apache httpd web server. Its provide more performance and little memory foot print.

Install Nginx
    we can install nginx through either repository (apt-get,yum) or from source. here i m build nginx from source from here. then extract the compressed file.
./configure --help      
above command shows possible command line options available for compile
for install use this command
./configure   --prefix=/home/ramki/nginx   --with-http_ssl_module     
here
--prefix used to specify where nginx server want to install, here i m using my home folder (like /usr/local/nginx)
--with-http_ssl_module here i specified install SSL module (https), its not necessary. If we want secure webpage then this module is needed.

then compile the source
 make      

install the nginx based on our configuration
sudo make install     

now installation is done, To start the nginx
cd /home/ramki/nginx/sbin   
sudo ./nginx     

now open browser and go to http://localhost to get nginx default page.

To stop the nginx, we need to pass stop signal via -s option
sudo ./nginx  -s stop     

Configure as a Load Balancer
     Nginx configurations are stored in nginx.con file in conf/ folder.  We need to perform 2 steps to make nginx as load balancer.

First define Upstream block in nginx.conf file

            Upstream block provides simple load-balancing across upstream (backend) servers. In upstream block have unique name (here  tomcatcluster), later we need to point out from other block.

       upstream tomcatcluster  {
                server 127.0.0.1:8181;
server 127.0.0.1:8282;
server 127.0.0.1:8383;
         }

here we define the back-end servers (Tomcat instances) via server directive.
In each server directive we mention IP address of server and HTTP port number(Not AJP port number). 

Second forward (proxy) the request to back-end servers

             This step is forward the request to upstream blocks, where we define the back end servers.

 location / {
             proxy_pass http://tomcatcluster;
        }   

here if location / is already present, then remove and add this new one.

here proxy_pass directive, proxifier(forward) the requests to upstream servers. here tomcatcluster is name of the upstream block and we used http protocol to forward the request.

that's it. Load balancer is ready.

now start the tomcat instances based on my previous post (session replication). then start nginx.
now access http://localhost.

now nginx forward the request in round robin fashion to back-end servers. all servers have the session, so it can able to process the request

This is same as non-sticky session method we used in my previous posts.


If we want sticky session, then nginx directly not provide, but some 3rd party patches are available. but nginx provide ip_hash directive. Its forward all request from single IP to same tomcat like sticky session. But sticky session works based on cookie (session). but ip_hash is based on IP address of client.

If u want to configure ip_hash, then modify the upstream block, add ip_hash

upstream tomcatcluster  {
                ip_hash;
                server 127.0.0.1:8181;
server 127.0.0.1:8282;
server 127.0.0.1:8383;
         }

just restart the server, u feel like sticky session concept.

when we compare the Nginx to Apache httpd web server, nginx is provide simple configuration, and can handle huge amount of traffic, consume little memory foot print and its take little CPU load.
search Nginx vs Apache we get some amazing benchmark results. 

Screen Cast :



Wednesday, 5 December 2012

Tomcat Clustering Series Part 4 : Session Replication using Backup Manager

Hi this is my fourth part of the Tomcat Clustering Series. In this post we are going to discuss the how to setup session replication using Backup Manager in tomcat clustering environment. Session replication makes High availability and full fail-over capability to our clustering environment.[Check the video below for better understanding]

Its continuation of the last post (session replication using Delta Manager). In delta manager each tomcat instance need to replicate the session information to all other tomcat instances. Its take more time and replication if our cluster size is increased. so there is alternative manager is there. Its Backup Manager.

Backup Manager is replicate the copy of session data to exactly one other tomcat instances. This big difference between both managers. here which tomcat creates that is primary copy of the session. and another tomcat whose hold the replicate session is backup copy. If any one of the tomcat is down. back up tomcat serve the session. Its achieve the fail over capability.

The setup process of backup manager is same as Delta manager. except we need to mention the Manager as BacupManager (org.apache.catalina.ha.session.DeltaManager)  inside <Cluster> element.


Suppose we have 3 tomcat instances like previous post. and i configured into backup manager.

now user try access the page. User request comes to load balancer, and load balancer redirect the rquest to suppose tomcat1. Now tomcat one create the session, now tomcat1 is responsible to replicate exactly one copy to any one of the tomcat. so tomcat1 picks any tomcat which is part of the cluster (multicast). here tomcat1 picks tomcat3 as a backup. so tomcat3 hold the backup copy of the session.

we are run the load balancer in sticky session mode. so all further request from that particular user  is redirect to tomcat1 only. all modification in tomcat1 is replicate to tomcat3.

now tomcat1 is crashed/shutdown for some reason



now same user try to access the page. this time load balancer try to redirect to tomcat1. but tomcat1 is down. so load-balancer pick one tomcat from the remaining tomcats. here interestingly 2 case are there.

Case 1:

  Suppose Load balancer pick the tomcat3 then tomcat3 receive the request and tomcat3 itself hold the backup copy of the session. so tomcat3 make that session as primary copy and tomcat3 pick any one tomcat as backup copy. so here remaining only one tomcat is there. so tomcat3 replicate the session to tomcat2. so now tomcat3 hold primary copy and tomcat2 hold the backup copy. now tomcat3 give the response to user. all further request is handled by tomcat3 (sticky session).

case 2:

 Suppose Load balancer pick the tomcat2 then tomcat2 receive the request and tomcat2 don't have the session. so tomcat2 session manager (Backup Manager) ask to all other tomcat manager "hi anybody hold the session for this user (based on session id [cookie])". Actually tomcat3 have the backup session. so tomcat3 inform to tomcat2. and replicate the session to tomcat2. now  tomcat2 make that session as primary copy and tomcat3 whose already have copy of session as remains as a backup copy of that session. so now tomcat2 hold primary copy and tomcat3 hold the backup copy. now tomcat2 give the response to user. all further request is handled by tomcat2 (sticky session).

so in either case our session is replicate and maintained by backup manager. Its good for large cluster.
check the video below

check my configuration in my github repo or get as ZIP file


Note:


Load balancer also faces single point failure. to resolve this we need to put another load balancer with public address and update the new IP to DNS server with same URL. so our URL like example.com query resolves the 2 IP address for 2 load balancer.

How its work:-
-> If browser want to access http://example.com then it first ask DNS server.
-> DNS server gives 2 IP address to browser
-> Browser take the first IP address and try to connect.
-> If in the case that server is failed to respond then browser side make timeout
-> then browser contact second IP address, now second load balancer is works fine.

This kind of adding more load balancer makes to our website more scalable and reliable in case of tragedy.

check in ur terminal

>     nslookup google.com      

its gives 11 IP address. these all are google load balancer's located in various geographic locations


Another thing this DNS servers not return same order of IP list to browser. each an every time its rotate(round robin) the IP list. so in 2 different machine ask google.com get different order of IP list. so these 2 differnt machine connect different google load balancer. so here DNS server also play little role for distribute the requests(loads).

to verify use same command twice. and verify the IP order.



Screen Cast:


Tuesday, 20 November 2012

Tomcat Clustering Series Part 3 : Session Replication

Hi this is my third part of the Tomcat Clustering Series. In this post we are going to discuss the how to setup session replication in tomcat clustering environment. Session replication makes High availability and full fail-over capability to our clustering environment.[Check the video below for better understanding]

In my previous post we discussed about setup simple load balancer and how to make session affinity concepts.

How to setup Session Replication in tomcat
   before going to session replication we need to understand 2 important concepts
  • Multicast
  • Session Manager in Tomcat
Multicast

     Multicast is To transmit a single message to a select group of recipients. here multicast used by tomcat cluster to identify the instances those part of cluster. 

There is 2 types of cluster
  • Static Tomcat Cluster
  • Dynamic Tomcat Cluster
In static cluster there is no need multicast, because each tomcat we statically defined/configured the other instances. But dynamic Cluster we are not defined anything. so each tomcat in that cluster some how to identify the other tomcat instances.

so here multicast concepts is used. each and every tomcat first joining to single multicast group. and send the heartbeat signals in periodic interval. so other tomcat instances received these signal and add the member to the cluster.

Session Manager in Tomcat

      Session Manager is used to create and manage the session behalf the application. In Servlet Specification request.getSession(); line is mention that container (tomcat) is responsible for create the session. here tomcat use the Session Manager for this purpose.

there is 4 types of Session Manager
  • Standard Manager
  • Persistent Manager
  • Delta Manager
  • Backup Manager

Standard Manager

Its is the default manager used by tomcat. Even though we are not mention in our web application tomcat use this manager for managing our session. If u want to customize the this standard manager then add <Manager> tag in context.xml file.

<Manager className=“org.apache.catalina.session.StandardManager” />

here org.apache.catalina.session.StandardManager is fully qualified class name of the Standard Manager.

Persistent Manger

This mnager is to sote the session information into persistent place after some interval. here two types of store is available.
  • File Store
  • JDBC Store
File Store helps to store all session information in separate files in underlying file system (local HDD or shared file-system like NFS,..) 
JDBC Store helps to store the session information to relational database.

so using the Persistent Manager we can achieve the tomcat cluster. but its not swapped out in real time. its pushes the information after certain interval. so if anything badly happen(crash) before that interval then in-memory session data is gone.

Delta Manger

In this post we are going to use this manager. Its replicate the session to all other instances. so this manager usually used clustered environment. but not good for large cluster.

Backup Manager

this manager usually used clustered environment. Its like delta manger. but it will  replicate to exactly one other instance(backup instance). Its acted like one instance is Primary  and another instance as backup  

Steps to make Session Replication in Tomcat Clustering

here i will continue from exactly where i left in last session affinity post. so check that post and make sure jumRoute all are set properly. so steps are
  1. Enable Multicast routing
  2. Add <Cluster> Entries in conf/server.xml file for all instances.
  3. Enable the Web Application as distributable

1. Enable Multicast routing


       In Linux Environment most of the system kernel is capable to process the multicast address. but we need to add route entry in kernel routing table.
sudo route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0

here eth0 is my Ethernet interface. so change according to your  interface
In multicast address is belong to Class D address Range (224.0.0.0 to 239.255.255.255). so we inform to kernel if any one access these address then it goes through eth0 interface.

2. Add <Cluster> Entries in conf/server.xml file for all instances.


     This very important part for tomcat clustering. We need to Add <Cluster> tag in conf/server.xml file in all tomcat instances.

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>

we can add this <Cluster> tag in either inside the<Engine> tag or <Host> tag.

here SimpleTcpCluster is Tomcat Cluster implementation

This tag is looks like simple but its has many inner tags. if we omitted then its takes the default values. if we want do any cutomization (like change multicat address, receving address port) we need to use complete <Cluster> tag

this is complete <Cluster> 


<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" 
                        channelSendOptions="8">

<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>
<Channel className="org.apache.catalina.tribes.group.GroupChannel">
<Membership className="org.apache.catalina.tribes.membership.McastService"
address="228.0.0.4"
port="45564"
frequency="500"
dropTime="3000"/>

<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="auto"
port="4000"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/>
<Interceptor  
                                  className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor 
                  className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
</Channel>

<Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=""/>

<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

<ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>

<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>

</Cluster>


Check my sample conf/server.xml file (for reference)

here most of the code are  boiler plate code. just copy and paste. if we need we can customize. for example we can change the multicat address and port number.

<Manager className="org.apache.catalina.ha.session.DeltaManager"/>

here Manager tag define the delta manager. Delta manager means replicate to all instances.


<Channel className="org.apache.catalina.tribes.group.GroupChannel">
Tomcat Clustering use the Apache Tribes communication framework.  This group commnication framework is responsible for dynamic membership (using multicast) , send and receive the session delta information using uni-cast (normal TCP connection).


<Membership className="org.apache.catalina.tribes.membership.McastService"
address="228.0.0.4"
port="45564"
frequency="500"
dropTime="3000"/>
This is Membership definition. here address is multicast address. we can pick any address from Class D address range (224.0.0.0 to 239.255.255.255)and any port number.

Each and every tomcat send the heart beat signal to multicast address in periodic (frequency) interval. all other tomcat whose joined the multicast address they can receive these signals and add the membership to the cluster. if heat beat signal is not revive some particular interval (dropTime) from any one of the tomcat, then we need to consider that tomcat is failed.

Note:-
     All tomcat instances which is part of the clustering, should have same multicast address and port number.


<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
here sender use the PooledParallelSender have pooled connections to use the send the session information concurrently. so its speedup the session replication process.


<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="auto"
port="4000"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/>
here we define which port Receiver can bind and used for receiving the session replicate information. here two properties are important. address and port. here address is ur system IP address and port is any unused port. here address="auto" its automatically pick the system IP address.


we have some interceptor
TcpFailureDetector -Its ensure that instance are dead. In some case multicast messages are delayed, all tomcat instances are think about that tomcat is dead. but this interceptor to make tcp unicast to failed tomcat and ensure that instances is actually failed or not

another important listener is JvmRouteSessionIDBinderListener, we talk about later

3. Enable the Web Application as distributable


   We need to make the our web application distribuable. its simple add <distributable/> tag in web.xml file. In according to servlet specification  <distributable/> tag in web.xml mention that any container to consider this application can work in distributed environment.

Note:
All session in our web application must me serializable.


Do these steps to all tomcat instances and start the tomcat and httpd server. check my configuration in my github repo or get as ZIP


This is my configuration. all 3 tomcat instances are configured in delta manager and i deployed the distributed web application. all tomcat use the multicast to maintain the membership.

now client make the request and first tomcat process and create the session, then looks like this
then tomcat 1 is responsible to replicate the session using Apache tribes group communication framework to replicate the session to all instances.

now all tomcat instance have exact copy of the session. so if tomcat 1 crashed or shutdown, then any other tomcat still can process the request [see the video below]

We used session affinity like previous post. based on that cookie id contain the tomcat name (worker name). so when first tomcat1 return the session id end with tomcat1. but when tomcat 1 is failed and tomcat 2 take the responsible for all further request. but session id still contain the tomcat1. so its makes the load balancer difficult. because tomcat1 is down. and load balancer pick any other tomcat. but actually tomcat2 takes the responsible. so we need to reflect these changes in session id.
JvmRouteSessionIDBinderListener  take care to change the client session id to tomcat2 when failure is occurred  so load balancer redirect to tomcat2 without confusing.

Check the git hub for all configuration files and tomcat clustering setup is available. or u can download as ZIP

Reference:




Screen Cast:


Tuesday, 30 October 2012

Tomcat Clustering Series Part 2 : Session Affinity Load Balancer

Hi this second part of the Tomcat Clustering Series. In my first part we discuss about how to setup simple load balancer. and we seen how load balancer distribute the request to tomcat instance in round robin fashion. [Check the video below for better understanding]

In this post we discuss about what is the problem is occur in simple load balancer when we introduce sessions in our web application. and we will see how to resolve this issue.

Its continuation of my first part of this series. so kindly go read my first part then continue here.

How Session works in Servlet/Tomcat?
       Before going into problem, let see the session management in Tomcat.
If any if the page/servlet create the session then Tomcat create the Session Object and attached into group of session (HashMap kind structure) and that session can identify using session-id, its just random number generated through any one of the hash algorithm. then respond to client with cookie header field. That cookie header field are key value pair. so tomcat create jsessioid is the key and random session-id is the value.

Once response reached to client (Web Browser) its update the cookie value. If already exist, then its overrides the cookie value. Then all further communication browser send the cookie attached with request to that server.

HTTP is stateless protocol. so server can't find the client session usual way. so server reads the header of the request and extract the cookie value and server got the Random session-id. then it search through group of session maintained by the tomcat. (It usually hash-map). then tomcat got perfect Session of that particular client (Web Browser).

If client cookie value doesn't match with group of sessions then tomcat create the completely new session and send the new cookie to browser. then browser update it.


this index.jsp code to deploy all tomcat instances
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.Date"%>

<%@page import="java.util.List"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>


    
        
        JSP Page
    
    

        Instance 1 


        
       
        
Session Id : <%=request.getSession().getId()%> Is it New Session : <%=request.getSession().isNew()%> Session Creation Date : <%=new Date(request.getSession().getCreationTime())%> Session Access Date : <%=new Date(request.getSession().getLastAccessedTime())%> Cart List
    <% String bookName = request.getParameter("bookName"); List listOfBooks = (List) request.getSession().getAttribute("Books"); if (listOfBooks == null) { listOfBooks = new ArrayList(); request.getSession().setAttribute("Books", listOfBooks); } if (bookName != null) { listOfBooks.add(bookName); request.getSession().setAttribute("Books", listOfBooks); } for (String book : listOfBooks) { out.println("
  • "+book + "
  • "); } %>

Book Name



What is the Problem In Simple Load Balancer?
     If we deploy the web application, in which its used the session then actual problem is occurred.

I describe with sequence

1. User request one web page, in that web page its used sessions (like shopping cart).
2. Load balancer intercept the request and use the round robin fashion its send to one of the tomcat. suppose this time its send to tomcat1.
3. tomcat1 create the session and respond with cookie header to client.
4. load balancer just act as relay. its send back to client.


5. next time user request again the shopping cart to server. this time user send the cookie header also
6.Load balancer intercept the request and use the round robin fashion its send to one of the tomcat. this time its send to tomcat2.
7. Tomcat 2 receive the request and extract the session-id. and this session id is doesn't match with their managed session. because this session is available only in tomcat1. so tomcat 2 is create the new session  and send new cookie to client
8. Client receive the response and update the cookie(Its overwrite the old cookie).


9. Client send one more time to request that page and send the cookie to server.
10. Load balancer intercept the request and use the round robin fashion its send to one of the tomcat. this time its send to tomcat3.
11. Tomcat 3 receive the request and extract the session-id. and this session id is doesn't match with their managed session. because this session is available only in tomcat2. so tomcat3 is create the new session  and send new cookie to client
12. Client receive the response and update the cookie.(Its overwrite the old cookie).


13. Client send one more time to request that page and send the cookie to server.
14. Load balancer intercept the request and use the round robin fashion its send to one of the tomcat. this time its send to tomcat1.
15. Tomcat 1 receive the request and extract the session-id. and this session id is doesn't match with their managed session. because client session id is updated by tomcat 3 last time. so even though tomcat 1 have one session object created by this client. but client session id is wrong.so tomcat1 is create the new session  and send new cookie to client (for more info watch the video below)
16. Client receive the response and update the cookie.


this sequence is continue ...

as the result every request one session is created. instead of continue with old one.


Here root cause is Load balancer. If load balancer redirect the request correctly then this problem is fixed. but how load balancer know in advance about this client before is processed by particular tomcat.
HTTP is stateless protocol. so HTTP doesn't help this situation. and other information is jsessionid cookie. its good but its just random value. so we can't take decision based on this random value.
ex:
Cookie: JSESSIONID=40025608F7B50E42DFA2785329079227


Session affinity/Sticky Session

Session affinity overrides the load-balancing algorithm by directing all requests in a session to a specific tomcat server. so when we setup the session affinity our problem is solved. but how to setup because session values are random value. so we need to generate the session value some how identify the which tomcat generate response.

jvmRoute

Tomcat configuration file (server.xml) caontain  <Engine> tag have jvmRoute property for this purpose. so edit the config file and update the <Engine > tag like this

<Engine name="Catalina" defaultHost="localhost“ jvmRoute=“tomcat1” >

here we mention jvmRoute="tomcat1" here tomcat1 is worker name of this tomcat. check the workers.properties file in last post

Add this line to all tomcat instances conf/server.xml file and change the jvmRoute value according to workers name and restart the tomcat instances.

Now all tomcat generate the session-id pattern like this
<Random Value like before>.<jvmRoute value>

ex: tomcat1 generate the session id  like
Cookie:JSESSIONID=40025608F7B50E42DFA2785329079227.tomcat1


here tail have which tomcat generate the session. so load balancer easily find out to where we need to delegate the request. in this case its tomcat1.

so update all tomcat instances conf/server.xml file to add the jvmRoute property to appropriate worker name values. and restart the instances. all problem is fixed and entire load balance works fine even session based application.

but there is still one drawback

if 5 user acessing the website. In session affinity is setup. here

tomcat 1 serves 2 user,
tomcat 2 serves 2 user, 
tomcat 3 serves 1 user,  then suddenly one of instance is failed, then what happen?

suppose instance 1 (tomcat1) is failed, then those 2 users lost their session. but their request are redirect to one of the remaining tomcat instances (tomcat2,tomcat3). so they still access the web page. but they lost previous sessions. this is one of the draw back. but its compare to last post load balancer. its works in session based web application also.

next post we will see how to set up the session replication in load balancer.


please share ur thoughts through comments.

Update : Check the Session Replication Process in Third Part of this Series


Screen Cast:

Related Posts Plugin for WordPress, Blogger...