LRWPinJava - Long Running Web Process in Java
- Support added for Python, Ruby and WebLogic
- - Run Python, Ruby cgi programs unchanged with LRWPinJava/Glassfish
- - Run Perl/PHP/Python/Ruby applications unchanged on WebLogic now
- Implementing REST Web Services using GlassFish/LRWPinJava - high performance, scalable web services
Best Practices for Deploying TWiki Software On GlassFish Application Server Using LRWPinJava - See BluePrint. Run TWiki 2x times faster with Glassfish/LRWPinJava compared to Apache 2.0
Benchmarking DRUPAL, a PHP application with Glassfish/LRWPinJava and Apache 2.0 . See comparable performance for fork mode .
Run PHP applications with no changes. See Case Study - Deploying PHP (DRUPAL) with Glassfish/LRWPinJava.
Long Running Web Process in Java ( LRWPinJava) is an open source implementation of the Long Running Web Process (LRWP) using Java technology. 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. . 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 supports multiple peers concurrently.
LRWPinJava has been implemented using Servlets (Glassfish container) leveraging the container multi-threading to support multiple peers concurrently. The implementation is light-weight and extremely fast. The performance of LRWP in Java is faster then the C implementation by 78% on a 4 core system in a real world C++ application.
How does LRWPinJava work ?(taken from blueprint)
LRWPinJava uses the LRWP protocol, a servlet, a LRWPAgent and cgi-wrappers to execute a client request and return back a response. The servlet runs on a servlet container such as Glassfish. The servlet, also acts as a LRWPAgent server and opens a server socket waiting for connections from LRWP client peers. A LRWP client peer is a client application in Perl/PHP/C/C++/Ruby/Python that is coded to use the LRWP api to communicate with the LRWPAgent using the LRWP protocol. A cgi-wrapper is a LRWP peer client application that automate the process of using the LRWP api to communicate. A cgi-wrapper wraps an existing application such as php-cgi or perl or ruby or python interpreter enabling it to act as a LRWP peer. The communication is handled by the cgi-wrapper while the execution is delegated to the interpreter application.
The cgi-wrapper executes the interpreter application (perl/php-cgi/ruby/python) in two modes, a fork mode and a persistent mode. In the fork mode, a Perl/PHP interpreter is forked and executed for each request by the cgi-wrapper. In the persistent mode, an embedded Perl/PHP interpreter is used within the cgi -wrapper to execute the request.
A sample request flow from a http client such as a browser:
1. A user uses a browser to access a URL.
2. The browser sends the request to Glassfish. LRWPinJava servlet gets activated since it is watching for requests on /* context. It takes a look at the context and if the context matches one of the cgi-wrapper contexts (see cgi-wrapper context below) forwards the request to the cgi-wrapper, if not the request is forwarded back to Glassfish defaultServlet to execute the request.
3. The LRWPinJava servlet on startup, not only acts as a servlet but also acts as an LRWPAgent ie. opens a server socket and waits for connections requests from LRWP client cgi-wrappers on port 1081. A LRWP cgi-wrapper is a client that knows how to communicate with the agent server using the LRWP protocol. A cgi-wrapper can be started on the same host as LRWPAgent server or on another host on the network. When a cgi-wrapper is started, one of the parameters to it is the context. The context can be /*.php or /bin/* or /bin/*.pl or /bin/*.rb or /bin/*.py, etc.
4. When a request matching a context is received by Glassfish, it forwards the request to LRWPinJava servlet since it is listening for requests across /*. LRWPinJava servlet looks at the context and if it matches a cgi-wrapper context as registered by a cgi-wrapper as in step 3, the request is forwarded to the cgi-wrapper. For eg. If http://server:80/index.php is requested from a browser, since /index.php matches /*.php as in step 3, the request is passed to the cgi-wrapper to execute while a request for http://server:80/images/abc.gif is not since “/images” does not match any context, so the LRWPinJava servlet forwards the request to Glassfish's defaultServlet.
5. Once a cgi-wrapper receives the request, it reads the input from the socket and writes it to a tmp file. The cgi-wrapper redirects STDIN to the file, redirects STDOUT to a file, and fork/executes a Perl/Php interpeter (perl/php-cgi) to execute the requested script. For example as in the example in step 4, it would be the index.php script. The output from the Php script, which is in the output file is returned as a response to the LRWPinJava agent, which returns it back to the browser as the response.
In the Persistent mode, instead of forking a Perl/Php process, embedPerl/lib-php is loaded once which processes the request as above. All of the communication is across Sockets allowing a cgi-wrapper to be anywhere on the network.
How to use these cgi-wrappers?
The cgi-wrappers are in
the examples directory under [os]. Change to the examples directory and start
the wrapper as follows:
./startcgiforkperl.sh 32 ipaddress "/bin/*" "/bin" or ./startcgiforkphp.sh 32 ipaddress "/*.php" "/"
The wrappers start the number of processes as in the first argument which act as LRWP peers and communicate with the LRWPAgent, while the second is the ipaddress of the peer host (usually localhost) and the third and fourth arguments is the context, and type of extension to look for, etc. The startcgiforkperl.sh wrapper enables PERL applications while the startcgiforkphp.sh enables PHP applications.
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".
The implementation in
Java uses the
Servlet container to handle HTTP requests and also
Servlets to handle the LRWP processing. The LRWPAgent
replaces the default servlet, and listens to the /* context (Note: You can
start the LRWPAgent on a context like /php or /perl also). It also accepts
TCP/IP based connection requests from LRWP peers storing the peer context
using a ode>ContextAssistantManager. When a client (browser) or http based
clients make a request to a servlet context, the agent looks up the context
ContextAssistantManager and passes on the
request to the associated LRWP peer. If there is no context match, the LRWP
agent, passes on the request to the container (Glassfish's) default servlet
for normal processing. So everything works as before except for requests to
the LRWP peer contexts which are now handled by the LRWP peers.
Salient features of this design are:
- This design supports multiple instances of LRWP agents, configurable during deployment.
- Each peer can open multiple connections with the same LRWP agent, which is also configurable through web.xml.
- Only one thread is used per LRWP agent; the servlet thread management is exploited for peer connectivity.
- The implementations
LRWPAgentManager, and the
RequestHandlerare made transparent through the use of interfaces.
Documents1. Installation and Getting Started Doc openoffice pdf doc
2. Architecture doc openoffice pdf doc
3. LRWP protocol txt
Papers1. Making Java Technology Faster Than C with LRWPinJava
2. LRWP Architecture description
3. Sun Blue Print - Best Practices for Deploying TWiki Software On GlassFish Application Server Using LRWPinJava
4. Implementing REST Web Services using Glassfish/LRWPinJava, openoffice pdf doc
Case Study1. Deploying PHP Application (DRUPAL) with Glassfish/LRWPinJava openoffice pdf doc
2. Improving the performance of TWIKI using Glassfish/LRWPinJava openoffice pdf doc
Benchmarks1. Benchmarking Drupal, a PHP application with Glassfish/LRWPinJava and Apache 2.0 openoffice pdf doc
Download1. LRWPinJava ver 1.2 (Solaris/Linux/Cygwin (Windows))
Rest Web Services
Related Projects1. Glassfish
2. Xitami Web Server