In the previous sections, you read about some HTTP benchmark clients. Now, we show a useful example in Tomcat that demonstrates a benchmark procedure from start to finish and also yields some information that can help you configure Tomcat so that it performs better for your web application.
We benchmarked all of Tomcat’s web server implementations, plus Apache httpd standalone, plus Apache httpd’s modules that connect to Tomcat to see how fast each configuration is at serving static content. For example, is Apache httpd faster than Tomcat standalone? Which Tomcat standalone web server connector implementation is the fastest? Which AJP server connector implementation is the fastest? How much slower or faster is each? We set out to answer these questions by benchmarking different configurations, at least for one hardware, OS, and Java combination.
Because benchmark results are highly dependent on the hardware they were run on, and on the versions of all software used at the time, the results can and do change with time. This is because new hardware is different, and new versions of each software package are different, and the performance characteristics of a different combination of hardware and/or software change. Also, the configuration settings used in the benchmark affect the results significantly. By the time you read this, the results below will likely be out-of-date. Also, even if you read this shortly after it is published, your hardware and software combination is not likely to be exactly the same as ours. The only way you can really know how your installation of Tomcat and/or Apache httpd will perform on your machine is to benchmark it yourself following a similar benchmark test procedure.
Tomcat connectors and Apache httpd connector modules
Tomcat offers implementations of three different server designs for serving HTTP and implementations of the same three designs for serving AJP:
This is Tomcat’s default connector implementation, unless the APRConnector’s libtcnative library is found at Tomcat startup time. It is also known as “Coyote.” It is a pure Java TCP sockets server implementation that uses thejava.iocore Java network classes. It is a fully blocking implementation of both HTTP and AJP. Being written in pure Java, it is binary portable to all operating systems that fully support Java. Many people believe this implementation to be slower than Apache httpd mainly because it is written in Java. The assumption there is that Java is always slower than compiled C. Is it? We’ll find out.
APR (Apache Portable Runtime)
This is Tomcat’s default connector implementation if you install Tomcat on Windows via the NSIS installer, but it is not the default connector implementation for most other stock installations of Tomcat. It is implemented as some Java classes that include a JNI wrapper around a small library named libtcnativewritten in the C programming language, which in turn depends on the Apache Portable Runtime (APR) library. The Apache httpd web server is also implemented in C and uses APR for its network communications. Some goals of this alternate implementation include offering a server implementation that uses the same open source C code as Apache httpd to outperform the JIO connector and also to offer performance that is at least on par with Apache httpd. One drawback is that because it is mainly implemented in C, a single binary release of thisConnectorcannot run on all platforms such as the JIO connector can. This means that Tomcat administrators need to build it, so a development environment is necessary, and there could be build problems. But, the authors of thisConnectorjustify the extra set up effort by claiming that Tomcat’s web performance is fastest with thisConnector implementation. We’ll see for ourselves by benchmarking it.
This is an alternateConnectorimplementation written in pure Java that uses thejava.niocore Java network classes that offer nonblocking TCP socket features. The main goal of thisConnector design is to offer Tomcat administrators aConnectorimplementation that performs better than the JIOConnectorby using fewer threads by implementing parts of theConnector in a nonblocking fashion. The fact that the JIOConnectorblocks on reads and writes means that if the administrator configures it to handle 400 concurrent connections, the JIOConnector must spawn 400 Java threads. The NIOConnector, on the other hand, needs only one thread to parse the requests on many connections, but then each request that gets routed to a servlet must run in its own thread (a limitation mandated by the Java Servlet Specification). Since part of the request handling is done in nonblocking Java code, the time it takes to handle that part of the request is time that a Java thread does not need to be in use, which means a smaller thread pool can be used to handle the same number of concurrent requests. A smaller thread pool usually means lower CPU utilization, which in turn usually means better performance. The theory behind why this would be faster builds on a tall stack of assumptions that may or may not apply to anyone’s own webapp and traffic load. For some, the NIOConnector could perform better, and for others, it could perform worse, as is the case for the otherConnectordesigns.
Alongside these TomcatConnectors, we benchmarked Apache httpd in both prefork and worker Multi-Process Model (MPM) build configurations, plus configurations of httpd prefork and worker where the benchmarked requests were being sent from Apache httpd to Tomcat via an Apache httpd connector module. We benchmarked the following Apache httpdconnector modules:
This module is developed under the umbrella of the Apache Tomcat project. It began years before Apache httpd’s mod_proxy included support for the AJP protocol (Tomcat’s AJPConnectorsimplement the server side of the protocol). This is an Apache httpd module that implements the client end of the AJP protocol. The AJP protocol is a TCP packet-based binary protocol with the goal of relaying the essentials of HTTP requests to another server software instance significantly faster than could be done with HTTP itself. The premise is that HTTP is very plain-text oriented, and thus requires slower, more complex parsers on the server side of the connection, and that if we instead implement a binary protocol that relays the already-parsed text strings of the requests, the server can respond significantly faster, and the network communications overhead can be minimized. At least, that’s the theory. We’ll see how significant the difference is. As of the time of this writing, most Apache httpd users who add Tomcat to their web servers to support servlets and/or JSP, build and use mod_jkmainly because either they believe that it is significantly faster than mod_proxy, or because they do not realize that mod_proxy is an easier alternative, or because someone suggested mod_jk to them. We set out to determine whether building, installing, configuring, and maintaining mod_jkwas worth the resulting performance.
This is mod_proxy’s AJP protocol connector support module. It connects with Tomcat via TCP to Tomcat’s AJP server port, sends requests through to Tomcat, waits for Tomcat’s responses, and then Apache httpd forwards the responses to the web client(s). The requests go through Apache httpd to Tomcat and back, and the protocol used between Apache httpdand Tomcat is the AJP protocol, just as it is with mod_jk. This connector became part of Apache httpd itself as of httpd version 2.2 and is already built into the httpd that comes with most operating systems (or it is prebuilt as a loadable httpd module). No extra compilation or installation is usually necessary to use it—just configuration of Apache httpd. Also, this module is a derivative of mod_jk, so mod_proxy_ajp’s code and features are very similar to those of mod_jk.
This is mod_proxy’s HTTP protocol connector support module. Like mod_ proxy_ajp, it connects with Tomcat via TCP, but this time it connects to Tomcat’s HTTP (web) server port. A simple way to think about how it works: the web client makes a request to Apache httpd’s web server, and then httpd makes that same request on Tomcat’s web server, Tomcat responds, and httpd forwards the response to the web client. All communication between Apache httpd and Tomcat is done via HTTP when using this module. This connector module is also part of Apache httpd, and it usually comes built into the httpd binaries found on most operating systems. It has been part of Apache httpd for a very long time, so it is available to you regardless of which version of Apache httpd you run.