Monday, December 20, 2010

Forwarding apache requests to Tomcat servlet container

Most web applications todays are using favorite Apache web server for its proven architecture and free apache license.
Tomcat is same as a very famous servlet container or java application server.
 Although tomcat itself can be access as a simple web server, for production environments it may lack some features like load-balancing, redundancy, etc.

So the best way to use is to integrate those two application, and finally its a great combination for enterprise applications for excess performance and ease of maintenance.

The theory behind is to use a middle tier connector called mod_jk.so module which communicate using AJP(Apache JSer Protocol ) version 1.3, best of currently available stable version.See the following figure for graphical view.



Here in this small steps guide i configure an Apache2 to a single instance of Tomcat6.Any comments and improvements are welcome at the end.

installations:





install apache2;Web server who listen on port 80
sudo apt-get install apache2






install tomcat6 and its applications>Application server/Web Container who translate application code in to results listen on port 8080 by default

sudo apt-get install tomcat6
sudo apt-get install tomcat6-common
sudo apt-get install tomcat6-examples
sudo apt-get install tomcat6-admin
sudo apt-get install tomcat6-docs
sudo apt-get install tomcat6-user

install libapache2-mod-jk>Connector module to forward web request to redirect in to tomcat's port 8009,8005 etc
sudo apt-get install libapache2-mod-jk

Configurations:

ask Apache to forward default pages to ajp13_worker through installed jk module by adding following two lines to this file by 'gedit /etc/apache2/sites-enabled/000-default'
<.....>
ServerAdmin chand@engineering.com  
JkMount / ajp13_worker JkMount /* ajp13_worker


....... file continues................

to make above to work, verify that following line is there on '/etc/apache2/mods-enabled/jk.load' 
LoadModule jk_module /usr/lib/apache2/modules/mod_jk.so

Now you have to tell jk_mod to find its configuration file path and how it should log errors and other informations.So add the following lines after LoadModule as above


JkWorkersFile /etc/libapache2-mod-jk/workers.properties 
JkLogFile /var/log/apache2/mod_jk.log 
JkShmFile /var/log/apache2/mod_jk.shm
JkLogLevel info
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "


Now Apache will forward the requests to mod_jk module.Now its time to configure mod_jk to forward those request to Tomcat.So goto its configuration file as you defined on the above:

/etc/libapache2-mod-jk/workers.properties 


Here you have to explicitly and correctly define 3 main parameters for jk module:

  • Tomcat Home
  • Java Home
  • Exact parameters of the Worker(ex: ajp13_worker )

in my server its with following configurations.But you can goto relevant folders and find out what are the available folders/java VMs you can configure for.

workers.tomcat_home=/usr/share/tomcat6


workers.java_home=/usr/lib/jvm/java-6-openjdk

worker.list=ajp13_worker

worker.ajp13_worker.port=8009
worker.ajp13_worker.host=localhost
worker.ajp13_worker.type=ajp13
worker.loadbalancer.balance_workers=ajp13_worker


OK! now jk module knows how to forward requests to port 8009, then we have to configure someone to listen on port 8009, and its tomcat.

Goto /etc/tomcat6/server.xml
By default tomcat don't listen to ajp13 protocol on port 8009, only on 8080 fot http requests.
you can uncomment the following line



'< Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /  >'


Now to all those changes to take effect you have to restart both services, but tomcat6 1st and then apache.

When you browse to http://localhost  you must be shown with tomcat's default page as you seen by http://localhost:8080

if both are same... now all your web requests on port 80 that were listen by apache web server are forwarding to Tomcat Servlet container.

In the same way as above, you can configure apache to request PHP sites as well.Lets see it in some other article.

Good Luck!!!!

Sunday, December 19, 2010

Enable Packet forwarding on for Internet Connection Sharing on Linux

Enable NATting for internet connection:


ppp0-internet connected port


add on startup or to /etc/init.d/rc.local


sudo iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE


Enable Packet accep for incoming requests:


Edit following file and change/uncomment following line to enable packet forwarding for incoming request packets.


/etc/sysctl.conf: net.ipv4.ip_forward = 1


to get control over the packet forwarding, we can forward all NATed packets to a local proxy server

to disable direct packet forwarding, change
/etc/sysctl.conf: net.ipv4.ip_forward = 0

then add an additional route;
i don't know whether the sequence of following will affect, just check you guys ans let me know....
:-)

iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j REDIRECT --to-port 3128

iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE

Saturday, December 4, 2010

Approach to Multi Threaded Socket Communication



On this article i will introduce with socket connection on single server multiple clients,Single client multiple messages(transaction based continuous connection),Multiple client multiple transaction (per connection). I will proceed with two methods of threading (extend Thread and implement Runnable).
Also at the requirement, i'll explain the use of synchronized shared objects and serialized data objects.
This article is the extend of basic-socket-programming article on www.chandpriyankara.tk/www.estudents.lk
single server multiple clients
This scenario is the most widely used socket communication in general.For example web servers.Many clients connects to the server requesting some data.The 3way TCP/IP handshake will initiate and identifies the two parties.Here, as regular, client who needs data wants to start the connection.Server or the data source must be up and running, waiting for a connection request form a client for a particular local port number(eg:80).Client will connect to the server,and the server will start a new thread in order to serve the clients request and transfer context to that thread.The master/main thread will resume and will stand by for another request from some other client(may be the same client).The created thread will process independently and serve data to the client.
As soon as the data is served, the connection will be closed.So, same client for some other data, wants to initiate another connection.This way the server is stateless of the clients, or all requests/connections are totally independent with others.
To serve independantly, the server must have a multi-thread application while client may very.

Thursday, December 2, 2010

Basic Socket Programming


Socket programming a is data exchange method used in electrical systems, specially within two or more(even itself) systems within a network reachability.

Inter networked computers are widely using this method to transfer various data and information with remote systems.Socket programming, just up on the TCP layer, provides a mean of interprocess communication. In order to successful completion of the socket communication, all TCP/IP and lower layers need to be fully and correctly in functional.

As this articel involved in explaining simple simple data transfer implementation we will limit the limit our scope into computer application programming with its simplest form.

In order to exchange data within systems, there need to be at least two parties, who Requires some data to transfer to a Listener party. Who request to send data, or the one who initiate to connect is called the client. Who is ready to listen, and waiting for some one else to initiate a request is called server.

In order to start the communication, the server need to be ready and on listening state. So, at a glance lets look how to make a server and make it to listen for a client request.

Most of the languages provides easy way to create this object, while here i go with java.

A socket connection consists of a application layer's port and internet/IP layer's IP address.IP address belongs to the OS. So our application have no control over it.But we can use any[1-65535 (below 1024 need root access)] port[to listen].

According to the requirements we can use several implementation techniques to handle data transfered between a socket connection.It may be uni-directional, client server, multi thread server, transaction based,etc.

We may first go through basic implementation of a TCP listener or a listener socket.

For this article i use JDK 1.6 with NetBeans 6.9 on Ubunut 10.10 but codings are same for any java implementation (for same JDK).

File->New Project->Java(Categories)||Java Application(Application)->Project Name||Create Main Class->Finish

import Server Socket object.
import java.net.ServerSocket;

try {  
ServerSocket serverSocket = new ServerSocket(2000, 1);            
Socket clientSocket = serverSocket.accept();

//this part of the code will handle the business logic

        } catch (IOException ex){
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }

Server socket will reserve a port number for the application process, which waits for a connection request from another process[local/remote].

'serverSocket.accept()'  will return a reference ('clientSocket') to the local end socket for the newly established data pipe.It can be used when ever the process wants to send or receive data back and forth.Initially the server process will run up to above line and hang there until a remote client send a request to connect.

Prepare another java project as above and implement a  client socket:

Socket socket = new Socket("localhost", 2000);
//business logic comes here
} catch (UnknownHostException unknownHostException) {
            System.out.println("Host no Found: " + unknownHostException.toString());
        } catch (IOException iOExceptionx) {
            System.out.println("Connection Failed: " + iOExceptionx.toString());
       } 
   }


Now, the connection can be established.But there is no use till we use it to send and receive data through the connection.So, create read and write iostreams on both socket ends.

on Server side:
InputStream receiveData = clientSocket.getInputStream();            
OutputStream sendData = clientSocket.getOutputStream();

on Client side:
InputStream receiveData = socket.getInputStream();            
OutputStream sendData = socket.getOutputStream();

Now  we can send and receive data through data channel between two processes.

Complete Code for Server:
package javaapplication1;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/** 
* @author chand 
*/
public class Main {
/**
public static void main(String[] args) {
        try {
            // TODO code application logic here
            int maxDataSize = 100;
            String messageToSend = "messageFromServer";
            String receivedMessageFromClient = "";
            ServerSocket serverSocket = new ServerSocket(2000, 1);
            Socket clientSocket = serverSocket.accept();
            InputStream receiveData = clientSocket.getInputStream();
            OutputStream sendData = clientSocket.getOutputStream();

byte[] data = new byte[maxDataSize];
                      int receivedMessageLength = receiveData.read(data);
           receivedMessageFromClient = new String(data);
            System.out.println("\nReceivedMessageFromClient: " + receivedMessageFromClient                    + " messageLength: " + receivedMessageLength);

data = messageToSend.getBytes();
            sendData.write(data);

} catch (IOException iOExceptionx) {
           System.out.println("Connection Failed: " + iOExceptionx.toString());        }    
}
}

Complete Code for Client:

kage javaapplication2;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
/**
*
* @author chand
*/
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
try {
// TODO code application logic here
int maxDataSize = 100;
String messageToSend = "messageFromClient";
String receivedMessageFromServer = "";
Socket socket = new Socket("localhost", 2000);
InputStream receiveData = socket.getInputStream();
OutputStream sendData = socket.getOutputStream();
byte[] data = new byte[maxDataSize];
//write and read events has been interchanged to avoid dead locks
data = messageToSend.getBytes();
sendData.write(data);
int receivedMessageLength = receiveData.read(data);
receivedMessageFromServer = new String(data);
System.out.println("\nReceivedMessageFromServer: " + receivedMessageFromServer
+ " messageLength: " + receivedMessageLength);
} catch (UnknownHostException unknownHostException) {
System.out.println("Host no Found: " + unknownHostException.toString());
} catch (IOException iOExceptionx) {
System.out.println("Connection Failed: " + iOExceptionx.toString());
}
}