E-business sites are increasingly utilizing dynamic Web pages since they enable a much wider range of interaction than static HTML pages can provide. Dynamic page generation, also known as dynamic scripting, allows a Web site to generate pages at runtime, based on various parameters.
Delaying content decisions until runtime provides several advantages to Web sites, including greater personalization and interactivity. For instance, a site might recognize and greet a returning customer based on his login (or perhaps from a cookie stored on his machine), e.g., "Welcome, John Smith." A more elaborate customization scheme might provide John with a set of recommendations, based on his past purchases.
Still another advantage of the dynamic content generation paradigm is that it allows greater control over content. Updates to content can be made in a single place (e.g., a database), rather than to every single HTML file, as is done in the case of static pages. This aspect allows a site to truly separate presentation from content.
Java is the development environment of choice for dynamic sites for a number of reasons. The Java platform simplifies enterprise application development by utilizing standardized, modular components, by providing a complete set of services to those components, and by handling many details of application behavior automatically, without the need for complex programming.
These features are part of the Java 2 Platform, Enterprise Edition (J2EE) standard, which provides many features including portability, support for Enterprise JavaBeans (EJB) components, Java Servlets API, and JavaServer Pages (JSP). Another advantage of using the Java development platform is that there is significant vendor support for Java-based scripting technologies among the high-end application server products.
The Impact on Server-Side Performance
While the dynamic scripting paradigm has provided the above-mentioned benefits, it has simultaneously resulted in serious performance problems due to the increased load it places on the site infrastructure. Each request for a dynamically generated page invokes a program on the application server, which in turn contacts various resources in order to generate the requested HTML page. The specific delays associated with dynamic content generation include (but are not limited to):
As user load increases, the effects of these delays are compounded, significantly impairing site scalability.
- Delays due to accessing persistent storage (e.g., databases, file systems)
- Network delays due to accessing remote resources (e.g., legacy systems, databases, external data feeds)
- Data formatting and transformation delays (e.g., XML-to-HTML transformations)
- Interaction bottlenecks (e.g., database connection pools)
- Overhead of JVM garbage collection
- Overhead of script execution
Performance Acceleration Solutions
In order to mitigate this list of content generation delays, a number of Dynamic Content Caching solutions have emerged. The basic idea behind these solutions is to reuse content that has already been generated to service a request; thus the redundant work in content generation is eliminated. The benefits of deploying such solutions are threefold: faster response times, higher throughput, and lower infrastructure requirements.
Dynamic Content Caching solutions can be categorized into two broad types: 1) application-specific solutions and 2) purpose-built solutions.
Application-Specific Caching Solutions
Application-specific solutions include caching functionality as an "add-on" feature. For instance, a number of application server vendors have recently incorporated JSP cache tagging into their products. One such vendor is BEA, with the introduction of WebLogic Server Cache Tags in WebLogic Version 6.0.
JSP cache tagging solutions allow page and fragment level JSP output to be cached. Fragment-level caching is enabled by marking or tagging the script code that produces cacheable output. When the script executes, if a tagged fragment is found in cache, then the script code that generates the fragment is bypassed.
A key advantage of application-specific caching solutions is that they are cost-effective since the caching features are included with the product. There are a few drawbacks to be aware of, however. For instance, JSP cache tags are only capable of presentation-layer caching; thus these solutions provide little value for sites based on the Model View Controller (MVC) design paradigm, as virtually all of the "real" work is done within the servlets and business components.
Another disadvantage of these solutions is that the caching process competes with the numerous other application server tasks for both CPU and memory resources. Furthermore, clustered implementations require multiple caches, creating issues in maintaining cluster-wide cache coherency.
Purpose-built solutions are typically standalone products designed specifically to address the delays caused by dynamic page generation. They can be further classified into two categories: page-level and component-level caching.
Page-level caching solutions intercept requests for specific HTML pages and cache the resulting output. For instance, consider the following request, which displays a page corresponding to a particular product category in an online catalog:
As long as the URL uniquely identifies the page that will be displayed, a page-level cache can store the resulting content to fulfill future requests. Vendors of Java-based solutions in this category include Oracle and Persistence Software.
There are a number of advantages associated with page-level caching solutions. Since the entire page is cached, these solutions can completely offload work from the application server, as the request never reaches that resource. In addition, these solutions allow some degree of personalization (e.g., in cases where users sharing the same preferences are served the same content), and they are relatively simple to implement.
On the other hand, there are several limitations to consider. By far, the most significant drawback is that caching only applies when the URL uniquely identifies a page. This is often not the case in dynamic Java-based sites, where complex business logic in the script determines the page that is created and served. In addition, on highly personalized sites page-level caching results in low cache hit rates since each page instance is unique to a user.
A component-level caching solution stores and serves dynamic page components (e.g., stock quotes, product descriptions, weather reports) that are reusable across multiple-user sessions, obviating significant work for the application server. For instance, consider a dynamically generated page in a news site, as shown in Figure 1.
The page consists of multiple components: Ad, Navigation, Headlines, and Personalized. While each page instance may be unique due to the Personalized component, it is likely that much of the content (e.g., Navigation, Headlines) will be the same for multiple requests during a given time interval. Component-level solutions capitalize on such reusability by caching and serving these components, eliminating the need for the application server to create them again and again.
Implementation of component-level caching requires identification of the specific components that cause performance bottlenecks. The corresponding application code that generates such bottleneck components is tagged, which involves inserting an API into the script. When the script executes, the API instructs the application server to check for the component in cache before generating any content.
The goal is to fulfill a high majority of requests from cache, thus producing site-wide infrastructure efficiencies. The only vendor in the component-level caching category is Chutney Technologies.
With component-level caching, cache invalidation policies are vital. Components must always be kept up-to-date, so that "stale" data is never served. Several strategies for cache invalidation exist, the most popular of which are time-based, event-based, observation-based, and on-demand.
Time-based policies are the most straightforward, and basically flush components at pre-set time intervals. Event-based invalidation is keyed on an external occurrence, such as a database update made by another application. In this case, the database is programmed to send a notification to the cache when a component's value changes. Observation-based policies are utilized by sites where updates to data sources occur inside the scripts, such as with exchange or auction sites.
Finally, on-demand invalidation allows keywords or regular expressions to be used to remove cached components at the site administrator's discretion. To maximize flexibility, a component-level cache allows the use of all of these methods concurrently to accommodate the data's unique characteristics.
There are several advantages to using component-level caching. Such solutions deliver high cache hit rates since most components have high reusability levels, if only for a brief time period. This factor enables even highly personalized sites to achieve significant performance benefits.
In addition, component-level caching solutions typically reside on a separate machine, eliminating the resource contention problems that are inherent with application-specific solutions. This "separate-box" architecture allows for enterprise-class scaling, as a single component-level cache can interface with a rack of application servers. Also, unlike application server cache tagging, component-level caching can be applied within nested script calls at the business logic layer, where much of the work is done in Java-based architectures.
A disadvantage of component-level caching solutions is that they require identification of the specific components that cause the most severe delays. This is either accomplished through site-specific knowledge or load profiling tools. After these components are identified, code-level integration is necessary to insert the appropriate caching tags within the scripts. Therefore, component-level caching's main tradeoff is one of implementation simplicity for maximized performance.
Putting the Solutions into Context
Figure 2 provides a simplified schematic indicating where each of these solutions fits into an end-to-end Web site architecture. Application-specific solutions, such as JSP cache tags, are part of the application server process, and therefore reside on the application server machine itself. Page-level caching solutions interact with the Web server, and may reside on either the Web server machine or a separate system. Component-level caching solutions interact with the application server, and reside on a separate machine.
Java is the technology of choice for enterprise e-business Web sites. Dynamically generating pages is highly advantageous but causes strain on a site's infrastructure There is a set of solutions (collectively known as Dynamic Content Caching) that are designed to alleviate these resource issues. A specific solution should be chosen based on a site's architecture, development plans, and business objectives, but some general guidelines do apply:
Summing up, Dynamic Content Caching is a valuable technology that should be built into any new Java site's design and architecture.
- Application-specific caching solutions are best suited for sites that are not clustered and where content is primarily generated at the presentation layer.
- Page-level caching solutions are most appropriate for sites where seamless integration and simplified management are critical.
- Component-level caching solutions are optimal for highly personalized sites that will perform code-level integration to achieve enterprise-class scaling.
Helen Thomas is a cofounder of Chutney Technologies and a technical expert in
the area of decision-support databases. She received an M.S.E.
degree in operations research and industrial engineering from the
University of Texas at Austin, and a B.S. degree in decision and
information sciences from the University of Maryland at College Park.
She is currently a Ph.D. candidate in the DuPree School of Management at
Georgia Tech. [email protected]