Long Running Web Process (LRWP) in the Java Platform using GlassFish

   
By Nagendra Nagarajayya, Ashish Bannerjee, Ranjan Kumar, Vikas Gera, Gayathry Manikandan and Dmitry Isakbayev, October 2007  
 
Long Running Web Process (LRWP)

The Long Running Web Process (LRWP) is a protocol used by a web server to communicate with its peers. LRWP is similar to CGI, but faster, since the peer is persistent across requests. In LRWP, a TCP connection is established between the LRWP peer and a LRWP agent. The LRWP agent could be the web container or a process running within the web container and the LRWP peer could be any process running on a network. The LRWP peer at connection registers the web context that the peer is interested in. The web context could be any context, such as "/osp", "/tep", or "/cgi-bin" itself. When a request for that context is made, the agent transfers the input to the LRWP peer and sends the output from the peer back to the web client. The LRWP agent should also be able to support multiple peers concurrently, and each peer makes a connection and registers the context it is interested in.

LRWP Protocol

A web server that implements LRWP protocol listens on a TCP/IP port, 1081 default, for LRWP peers to connect. A peer connects by opening a TCP/IP connection and sending in the context name and an optional host name. The host name is to support virtual host names. The peer then waits for a response from the web server, which is an OK to indicate a connection registration or an error message. After a successful registration, the peer then waits for requests from the web server. The web server sends in environment variables such as the cgi-bin request and the data, and waits for a response from the peer. The peer responds by sending in environment variables such as a cgi-bin program response and the data. The connection is terminated by the web server or the peer by closing the TCP/IP connection. The details of the protocol implementation can be found on the Xitami page, "Extending Xitami with External peer Processes".

LRWP Implementation in Xitami Web Server

Xitami is a lightweight, multithreaded, ServerWatch's hall of fame web server. It supports the following features:

  • HTTP/1.0, FTP, CGI/1.1, SSI protocols and extensions, SSL, CGI, LRWP protocol for persistent (fast CGI), logging, virtual hosts
  • Runs on Windows, OS/2, UNIX, OpenVMS
  • Extremely fast even on small systems and has a very small footprint
LRWP Agent Design in the Java Platform

The design for implementing the LRWP protocol in the Java platform uses a servlet container to handle HTTP requests and also to make use of servlets to handle the LRWP processing. The initial idea was to build a multithreaded LRWP Agent server, running within the servlet container, which would act as a broker between the LRWP peers and the servlets. It would accept requests from LRWP peers, pass on the incoming HTTP requests to the peers, and pass the response from the peers back to the servlets. On an HTTP request, the servlet would communicate the HTTP request to the LRWP agent, which would block the servlet thread, unblock the the peer thread, and pass on the request to the LRWP peer. Then, the response from the peer would be passed back to the servlet by waking it up and blocking the peer thread. This design was modified so that instead of having a multithreaded LRWP agent, we had a single threaded agent, which accepted the connection request from a LRWP peer and stored the connection in a ContextAssistantManager. Instead of blocking while passing on the request to the Agent, the servlet thread instead now looked up the connection to the peer using the ContextAssistantManager and passed on the HTTP request after transforming it to the LRWP protocol itself, waiting for a response from the LRWP peer, and then returning the response as its own.

Salient features of this design are:

  1. This design supports multiple instances of LRWP agents, configurable during deployment.
  2. Each peer can open multiple connections with the same LRWP agent, which is also configurable through web.xml.
  3. Only one thread is used per LRWP agent; the servlet thread management is exploited for peer connectivity.
  4. The implementations of the LRWPAgentManager, and the RequestHandler are made transparent through the use of interfaces.
LRWP Implementation in Java

Interface Classes

  • LRWPAgentManager
     
    This class provides following methods to be implemented by the LRWPAgentManager implementation Class.
     
    Methods
    Description
    start()
    Starts the LRWPAgentManager.
    setNumOfAgents
    Defines the number of agents that would run.
    setStartPort()
    Defines the starting port to which LRWP agent instances would bind. For example, if the starting port is defined to be 1081 and number of agents is 2, then two instances of LRWP agent would start up - first binding to port 1081 and second binding to port 1082.
     
  • LRWPAgentRegistrar
     
    This class provides following methods to be implemented by the LRWPAgentRegistrar Implementation Class.
     
    Methods
    Description
    register()
    Register the Proxy Service Instance (LRWP RequestHandler).
    deregister()
    De-register the Proxy Service Instance (LRWP RequestHandler)
     
  • HttpProxyService
     
    This class provides following methods to be implemented by the LRWP RequestHandler Class.
     
    Methods
    Description
    service()
    Implement the request service algorithm in this method.
    stop()
    Method to stop the RequestHandler/Proxy service instance.
     

Classes

  • HttpProxyServlet
     
    This is a simple HTTP servlet which implements following servlet methods:
     
    Methods
    Description
    init()
    Reads initialization parameters from the servlet deployment file (web.xml) and performs initialization of variables. It also creates an instance of LRWPAgentProxyManager, after fetching the implementation class name from the deployment parameter 'Proxy Manager'.
    destroy()
    Stops the LRWPAgentProxyManager instance and disposes of/destroys the servlet.
    processRequest()
    This method is invoked to service the HTTP Request. This method forwards/delegates the request to the LRWPAgentManager. Now the LRWPAgentProxyManager responds to this request.
     
  • LRWPAgent
     
    The LRWP agent is a server thread that would bind itself to agent ports specified in the configuration file (web.xml). If multiple instances of LRWP agents are defined in the configuration file, then the port defined in web.xml is the starting port. When a new LRWP peer Process connects to an LRWP agent instance, it creates a RequestHandler instance and again waits for a new LRWP peer. This class implements the following methods:
     
    Methods
    Description
    run()
    This is the thread class method overridden by the LRWP agent Class. The LRWP agent binds itself to the server port defined in the configuration file, and waits for the peer process. As soon as the peer process opens a connection with the LRWP agent, it instantiates an LRWP RequestHandler.
    stopThread()
    Stops the LRWP agent server thread and closes the socket port for communication.
     
  • LRWPAgentProxyManager
     
    This class manages the LRWP agent instances. It also maintains a repository of peers which would serve requests against a path (url) of a virtual host. This class implements the LRWPAgentManager and LRWPAgentRegistrar interfaces. It has following methods:
     
    Methods
    Description
    start()
    Creates instance(s) of LRWPAgent class and starts LRWP agent thread(s).
    stop()
    Stops the LRWP agent instance(s).
    setNumOfAgents()
    Sets the number of agents to be started.
    setStartPort()
    Defines the starting port on which LRWP agent would be started. If a new instance of LRWP agent is created, it would bind with a new port (starting port + n).
    register()
    Creates an entry in the repository for a virtual host, path and LRWP RequestHandler (implementor of Service Class interface).
    deregister()
    Removes a virtual host, path and LRWP RequestHandler entry from the repository.
    Service()
    This method implements the logic to get a RequestHandler instance which would serve the client request. If there is no instance of RequestHandler to support the request, or it is busy, the request would be put to wait, or would result in a default response.
     
  • LRWP RequestHandler
     
    This class does the transformation of HTTP requests from the web client to the LRWP Request. The request is then sent to the LRWP peer over a socket connection. Each LRWP RequestHandler is bound to only one LRWP peer over socket connection. One LRWP peer process may be connected to multiple request handler instances over multiple socket connections. This class implements the HttpProxyService interfaces. It implements the following methods:
     
    Methods
    Description
    init()
    Receives and acknowledges the init message from the LRWP peer, which contains information about the virtual host and the path it will serve. Acknowledgment begins with "OK" if the init method is successfully received from the LRWP peer process, or else the acknowledgment contains "ERROR" as the starting string.
    service()
    This is the main method that does the transformation of the HTTP Request to the LRWP Request. The request is sent to the LRWP peer process. The response is then transformed to HTTP Response and sent back directly to the web client (browser).
     
Installing and Deploying the LRWP Agent on GlassFish (Java Application Server)

Requirements:

  1. GlassFish Java EE Application server
  2. LRWP Agent Version 1.0

Installation:

GlassFish Installation and Configuration

  1. For installation of the GlassFish Application server, refer to the GlassFish installation document here.
  2. Refer to the GlassFish Quickstart guide for GlassFish operations.
  3. Make Sure the default http port of GlassFish is 1080 during the server setup.

LRWP agent Installation

  1. Extract LRWPAgent_bin.tar.gz (LRWP agent binaries) files in your directory ($HOME_DIR directory).
  2. Deploy the LRWP agent:
    2.1.  Open the admin console of the Sun Web Application Server.
    2.2.  Give path to LRWPAgent.war file for deployment ($HOME_DIR/LRWPAgent/dist/LRWPAgent.war).
    2.3.  Deploy the war file on the root context of GlassFish. This can be done during the deployment of the war file.
  3. The LRWP agent is now deployed. It can now be tested for LRWP connections from peers.

LRWP agent Configuration

The user can configure/tune different parameters of the LRWP agent module. All parameters are defined in the 'web.xml' file included in the distribution. The parameter names and their functions are described here:

  • Proxy Manager - Defines the class implementing the Proxy Manager Interface. The Proxy Manager class can manage multiple instances of LRWP agents. The parameter name in configuration file (web.xml) is "ProxyManager".
     
  • Number of Agents - Defines the number of LRWP agent instances desired. Default Value is '01' (one instance). However, the LRWP module can support 10 instances of LRWP agents simultaneously. The parameter name in the configuration file (web.xml) is "numAgents".
     
  • Starting Port - Defines the port at which an LRWP agent would run. Default port is 1081. If there is more than one instance defined in "numAgents", then this parameter becomes the starting port. For example, if numAgents is '2', and starting port is defined as '1081', then two instances of the LRWP agent would run, the first instance bound to port 1081 and second instance bound to port 1082. The parameter name in the configuration file (web.xml) is "startPort".
     
  • peer Per Agent - Defines the number of LRWP peers that can connect to one instance of the LRWP agent. This parameter is included for load-balancing. The default number of peers that can be handled is '5'. An agent can handle maximum of fifteen LRWP peers. The parameter name in the configuration file (web.xml) is "peerPerAgent".
Testing with a C LRWP Peer

The LRWP peer is a client which connects to the LRWP agent running on the GlassFish application server . A sample program is available on the Xitami site. The program can be compiled and the resultant binary can serve as the basic testing tool for a LRWP agent on GlassFish.

The program can be compiled from command line and the SFL library from Imatix Inc. needs to be included as the library at the command line.

Before compiling the example code, change the arguments in the lrwp_connect() function. For example, localhost and the port number can be replaced with the hostname of the LRWP agent machine and the port number on which the LRWP agent is running.

lrwp_connect(&lrwp, "hello", "localhost", "81", "");
 

The standard command line for compilation can be like :

%cc -I<path to the SMT library> -I<Path to the SFL Library>  lrwp_peer.c  \
                    

-llrwp_context -lsfl-32b-lrwp -lsfl-32b -lsmt-32b -lsocket -lnsl -o lrwp_peerlrwp_peer
                  
 

Once compiled, the binary can be tested against an LRWP agent. The below mentioned steps can prove the basic functionality of the LRWP agent:

  1. Run the C LRWP peer binary from the command line.
  2. In the browser, type the URL of the GlassFish appserver, http://localhost:1080, appended with hello as the context.
  3. The page displayed would show the total number of requests sent to the LRWP agent and the counter would increase with each request.

A more thorough and better testing can be done using a Java programming language implementation of the LRWP peer called Sokrates [Available at http://www.dreamlandbbs.com/files/gfd/appjava/sokr_v17.zip ].

Testing with a Java LRWP peer (Sokrates)

Sokrates Installation and Startup

  1. Unzip the contents of sokr_v17.zip
  2. Change directory to Sokrates % cd $HOME_DIR/Sokrates
  3. Edit the runner.ini file:
    1. Define host to 'localhost'
    2. Define Port as 1081
  4. Start Sokrates:
    1. % cd $HOME_DIR/Sokrates
    2. % java net.conacom.servletrunner.main.Runner
  5. This will start the Sokrates peer.
  6. In the Web Browser, enter URL: http://localhost:1080/demo

This will launch the Sokrates default page. You can then run the different operations listed on this page.

Test Operations on the LRWP agent using Sokrates

The following set of operations can be tested on LRWP agent using the Sokrates servlet runner.

  1. List Parameters
  2. List Headers
  3. List Request Attributes
  4. List servlet Attributes
  5. List request Methods
  6. List Context Methods
  7. List Cookies
  8. List Session data
  9. Test Form
  10. Test Cookies
  11. Test Sessions
  12. Test Redirect
  13. Test Binary
  14. Test Choice
  15. Test Bigdata
  16. Test Forwarding
  17. Test Include

The above listed operations are the standard test of a fully functional LRWP agent and failure of any of these operations shows a non-implementation of the functionality in the agent.

Conclusions

The LRWP agent in Java with GlassFish works well and works with different language-based LRWP peers. It has been tested with C, C++ and Java programming language-based LRWP peers. The performance of the LRWP agent is very good and in fact exceeds Xitami's implementation on a 4 core x86 system. The LRWP agent implementation will also be made available as open source on java.net.

Acknowledgments

We would like to thank Satyajit Tripathi for excellent project management, managing resources efficiently across time zones with time lines, making communication very efficient and Bruce Chapman for reviewing and providing some fine suggestions making the paper easier to read.

References
  1. LRWP Protocol
  2. Xitami web server
  3. GlassFish
  4. Threads
  5. Xitami Features
  6. Wikipedia
  7. Hall of Fame
Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
Your email address (no reply is possible without an address):
Sun Privacy Policy

Note: We are not able to respond to all submitted comments.