Skip Headers

Oracle9i Application Server Oracle HTTP Server powered by Apache Performance Guide
Release 1 (v1.0.2.1) for AIX-Based Systems, Compaq Tru64 UNIX, HP 9000 Series HP-UX, Linux Intel, and Sun Solaris Intel

Part Number A90444-01
Go To Documentation Library
Library
Go To Table Of Contents
Contents
Go To Index
Index

Go to previous page Go to next page

5
Optimizing Apache JServ

This chapter describes the JServ architecture, and discusses ways you can improve JServ performance. It also includes performance information on OracleJSP pages (the Oracle implementation of Sun Microsystems' JavaServer Pages 1.1.)

Overview of JServ

Apache JServ is made up of an Apache module called mod_jserv, which runs in the httpd process, and a servlet engine, which runs in a Java process. mod_jserv, which is implemented in C, functions as a dispatcher, routing each servlet request to a JServ process for execution.

The servlet engine runs in its own JVM (Java Virtual Machine) and is solely responsible for parsing the request and generating a response. As Figure 5-1 shows, multiple JServs can service requests. The HTTP server process and the JServ process communicate using the Apache JServ Protocol 1.2.

Figure 5-1 Apache JServ components


Text description of modjserv.gif follows.
Text description of the illustration modjserv.gif

Optimizing Servlet Performance

This section discusses strategies for optimizing JServ performance: loading servlets when starting the JVM, and load balancing.

The terms "repository" and "zone" are used in this discussion. Servlets, repositories, and zones are analogous to files, directories and virtual hosts. A servlet is a single unit, a repository is a collection of servlets, and a zone is a collection of repositories.

Loading Servlet Classes

Apache JServ allows you to load servlet classes when the JVM is started. To do this, put the servlets to load in the servlets.startup directive in the servlet zone properties file. When the servlet is loaded, its init()method is called. All other servlets (those not listed in servlets.startup) are loaded and initialized on first request.

Using this facility increases the start-up time for your JServ process, but improves first-request latency for servlets.

Pre-Loading with JSPs

If you are using a JSP as the servlet (your code does not extend HttpServlet), you will be unable to use this pre-load option, but you could pre-load the JSP runner by including the oracle.jsp.jspServlet in servlets.startup.

If the first-request latency for your initialization routines is really a performance issue, you can achieve some of the results described above by creating a dummy servlet to call your one-time initialization routines in its init() method. You must add the name of the dummy servlet to servlets.startup.

Reloading Servlet Classes Automatically

If autoreload.classes is set to true for a zone (the default), then each time one of that zone's servlets is requested, every class that has been loaded from a repository in that zone is checked to see if it has been modified. If one of the classes has changed, then all previously loaded classes from the zone's repositories are unloaded, which means that as the classes are needed, they will be loaded from their class files again.

This is a useful development feature, because you can install new versions or drop in new class files without restarting the server. For optimal performance in production environments, however, you should set both automatic class reloading parameters to false, since there is a performance cost in checking the repositories on every execution of a servlet. Change these parameters in the zone properties file:

autoreload.classes=false
autoreload.file=false

How to Perform Load Balancing

It is often beneficial to spread the servlet application load among multiple JServ processes, especially when the application is run on a multiprocessor system or if the servlets and HTTP server are run on separate nodes. Running multiple Apache JServ processes generally results in higher throughput and shorter response time, even on a single-processor host. (See Chapter 3, "Sizing and Configuration" for specific recommendations.)

Using Automatic Load Balancing

The mod_oprocmgr module shipped with Release 1.0.2.2 enables you to specify a `auto' setting in jserv.conf for the ApJServManual directive. mod_oprocmgr provides automatic load balancing and death detection for JServ processes. See Using mod_oprocmgr with mod_jserv in the Oracle9i Application Server documentation library for instructions on using this module.

Using Manual Load balancing

This section explains how to balance incoming requests between two JServ processes running on the same host as the HTTP server. Examples from the jserv.properties files are included with the procedures; substitute your own port numbers and directory locations where needed.

With this method of load balancing, you must start and stop processes manually, because JServ cannot automatically start and stop more than one JServ process. (Sample scripts for starting and stopping the JServ processes and the Oracle HTTP Server are included in the $ORACLE_HOME/Apache/Apache/bin/ directory.) This means that if a process terminates for any reason, JServ will not restart it. To prevent processes from terminating due to memory shortage, ensure that you have a sufficient maximum heap size set for your JServ processes. See "Determining Java Heap Size".

Configuring the JServ processes

Each JServ process in your load balancing scheme must be configured to listen on its own port and to log to its own file. If you have a jserv.properties file containing the parameters needed to run your application, you can duplicate it to create a properties file for each JServ process.

  1. Create a properties file for each JServ process.

    prompt>cp jserv.properties jserv1.properties
    prompt>cp jserv.properties jserv2.properties
    
    
  2. Edit jserv1.properties as follows:

    	port=8001
    	log.file=/usr/local/jserv/logs/jserv1.log
    
    
  3. Edit jserv2.properties as follows:

    	port=8002
    	log.file=/usr/local/jserv/logs/jserv2.log
    
    


Note::

If your HTTP server will be running on a different host than the JServ processes, you must also add the IP address of the host running the HTTP server to the security.allowedAddresses parameter in each jserv.properties file.  


If JServ is included in your CLASSPATH, you can start the JServ processes with these commands:

java JServ jserv1.properties
java JServ jserv2.properties

To start and stop the processes and the web server, it is convenient to use scripts. Samples are included in the $ORACLE_HOME/Apache/Apache/bin/ directory (startJServ.sh and stopJServ.sh).

Modifying jserv.conf to distribute the load

  1. Set the flag to start processes manually.

    	ApJServManual on
    
    
  2. Indicate where the servlet request is to be sent.

    1. Locate the ApJServMount directive.

      	ApJServMount /servlets /root
      
      

      If the user requests http://your.server.com/servlets/testServlet, the ApJServMount directive above will execute testServlet in the zone called /root.

    2. Change the zone identifier from /root to balance://Jserv_set/root and then add the ApJServBalance, ApJServHost, ApJservRoute directives for each process sharing the load, as shown below:

      	ApJServMount /servlets balance://JServ_set/root
      	ApJServBalance JServ_set JServ1
      	ApJServBalance JServ_set JServ2 2
      	ApJServHost JServ1 ajpv12://127.0.0.1:8001
      	ApJServHost JServ2 ajpv12://127.0.0.1:8002
      	ApJServRoute JS1 JServ1
      	ApJServRoute JS2 JServ2
      	ApJServShmFile /usr/local/apache/logs/jserv_shm
      
      
      • The ApJServMount directive, with /servlets balance://JServ_set/root, now balances requests for servlets in /servlets between JServ1 and JServ2.

      • The ApJServBalance directive identifies JServ1 and JServ2 as the processes that share the load. The '2' following JServ2 is a weight value. It specifies that twice as many requests will be sent to JServ2 as would be otherwise, i.e., that JServ2 will get about 2/3 of all incoming requests. See "Distribution of JServ Requests" below for details.

      • The ApJServHost directive identifies the host and port on which the processes are listening.

      • The ApJServRoute directive associates JServ processes with sessions. JServ uses this information to keep all of a session's requests together in one process. The JServ session mechanism sends the process route information back to the user (generally in a cookie). You need only modify it if your application uses sessions.

      • The ApJServShmFile directive specifies a shared memory file that the httpd processes may use to track the state of the JServ processes.

Distribution of JServ Requests

The following process explains how mod_jserv selects the JServ engine to handle a request:

  1. An httpd process is started.

  2. mod_jserv creates a list of available JServs, with extra entries for JServs with a weight value greater than 1 (for example, JServ2 in the example above, as specified by ApJServBalance Jserv_set JServ2 2).

  3. An httpd daemon receives a servlet request and hands it to mod_jserv.

  4. mod_jserv selects the JServ engine that will handle the request.

    1. mod_jserv checks to see if the request is part of a current session. If so, it uses the ApJServRoute directives to find the JServ that handled the other requests for that session.

    2. If the request is not part of a session, mod_jserv selects an engine based on the process ID of the httpd process and the number of entries in the list of available JServs, as follows:

      JServ_id to handle the request = httpd_pid % (modulo) number of JServs in the list

      This method dibstributes requests across the available JServ engines fairly evenly.

Using Single Thread Model Servlets

Oracle recommends that you write your servlets to implement the SingleThreadModel (STM) interface. An application that was modified to implement the STM interface demonstrated a 25% improvement in response time.

It is also much easier to manage database connections with STM servlets. The database connection can be set up in the init() method of the servlet, and closed in the destroy() method. When executing the servlet's doGet() or service() method, you need not be concerned with obtaining a database connection. You can also manage database connections with JDBC connection caching.

There are three parameters in the zone.properties file that impact the performance of STM servlets in particular. These govern:

Because it is very costly to generate instances while the system is running, Oracle recommends that you set your minimum to equal your maximum value. The optimum value depends somewhat on how many connections your database server can handle. This should be split among the JServ processes, as follows:

Total DB connections / Number of JServ processes =

Number of STM servlet instances per process

See Chapter 3, "Sizing and Configuration" for suggestions on determining the right number of JServ processes for your application, and "How to Perform Load Balancing" for the steps to configure them. Suppose you've determined that you want 10 servlet instances per process. The capacity settings in the zone.properties file would be:

singleThreadModelServlet.initialCapacity = 10
singleThreadModelServlet.incrementCapacity = 0
singleThreadModelServlet.maximumCapacity = 10


Warning:

The value for singleThreadModelServlet.maximumCapacity in the zone properties file must be at least as large as the value for security.maxConnections in the jserv.properties file. If it is not, and the number of requests sent to the JServ process exceeds the maximum capacity, requests will fail.  


What is OracleJSP?

OracleJSP 1.1.0.0 is Oracle's implementation of the Sun Microsystems JavaServer Pages 1.1 specification. Some of the additional features it includes are custom JavaBeans for accessing Oracle databases, SQL support, and extended data types. See the Oracle9i Application Server Overview Guide in the Oracle9i Application Server documentation library for detailed descriptions of the features.

Tuning OracleJSP Pages for Performance

This section explains how you can improve OracleJSP pages' performance.

Impact of Session Management

In general, sessions add performance overhead; they consume about 0.5 KB of resident memory. You must turn off sessions if you do not want a new session to be created with each request. By default, sessions are enabled in OracleJSP pages, so if they are not being used, turn them off by including the following line at the top of the page:

<%@ page session="false" %>

If you are going to use sessions, ensure that you explicitly close them. If you don't, they will linger until they time out (the default value for session timeout is 30 minutes). To close a session manually, use the session.invalidate() method.

See the OracleJSP Developer's Guide and Reference in the Oracle9i Application Server documentation library for more information on configuring OracleJSP pages.

Developer Mode

Another parameter that has a significant effect on performance is developer mode. It is a useful feature for debugging during development, but it degrades performance. The default value is true, so you will need to set it to false in the jserv.properties file as follows:

servlet.oracle.jsp.JspServlet.initArgs=developer_mode=false

With developer mode set to true, OracleJSP and the servlet engine examines every request to determine whether to reload or retranslate the page or application. With developer mode off, only the first request is examined.

In a test using JDK 1.2 with 50 users, 128 MB heap, and the default TCP settings, the performance gains with developer mode off were 14% in throughput, and 28% in average response time.

Buffering

If an OracleJSP page is not using any features that do not require resetting the buffer (such as error pages, contextType settings, forwards, etc.), disabling the JSP page buffer will improve performance. This is because memory will not be used in creating the buffer, and the output can go directly to the browser. Use this page directive to disable buffering:

<%@ page buffer="none" %>

The default size of an OracleJSP page buffer is 8 KB. 

OracleJSP Performance Tips

The configuration actions below can enhance the performance of your OracleJSP pages.

Caching database connections

Since the performance cost of creating database connections is high, it is more performant to use a cache of connections. If you use a cache of database connections, then the OracleJSP application can get a connection from the cache and return it when it is finished.

Configuring the statement batch value

The JDBC driver accumulates a number of execution requests (the batch value) and passes them to the database to be processed at the same time. You can configure the batch value to control how frequently processing occurs.

Caching JDBC statements

Cache executable statements that are repeatedly used, to avoid re-parsing, statement object re-creation, and recalculation of parameter size definitions.

Pre-fetching rows

During a query, pre-fetch multiple rows into the client to reduce round trips between the database and the server.

Caching rowsets from the database

Cache small sets of data that are accessed frequently and do not change often. This is not as beneficial for large data sets, since they consume more memory.

Invoking static includes

To invoke static includes, use the page directive:

<%@ include file="/jsp/filename.jsp" %>

Static include creates a copy of the file in the JSP, thereby affecting its page size. This is useful in avoiding trips to the request dispatcher (unlike dynamic includes, which must go through the request dispatcher each time). However, file sizes should be small to avoid exceeding the 64 KB limit of the service method of the generated page implementation class.

Invoking Dynamic Includes

To invoke dynamic includes, use the page directive

<jsp:include page="/jsp/filename.jsp" flush="true" />

This directive is analogous to a function call, and therefore does not increase the page size of the JSP. However, a dynamic include increases the processing overhead since it must go through the request dispatcher. Dynamic includes are useful for including other pages without increasing page size.


Go to previous page Go to next page
Oracle
Copyright © 2001 Oracle Corporation.

All Rights Reserved.
Go To Documentation Library
Library
Go To Table Of Contents
Contents
Go To Index
Index