SoFunction
Updated on 2025-03-02

Improve the performance and stability of JSP applications using buffering technology

1. Overview

In web applications, it may take a long time for the database to calculate the generation of some reports; some websites provide weather information, which requires access to a remote server for SOAP calls to obtain temperature information. All of this is an example of complex information. Adding too much complex information to the web page may cause excessive load on the web server and database server. JSP code block buffering brings developers the freedom to arbitrarily increase various complex information.

JSP can encapsulate and run complex Java code in the tag library, which makes JSP page files easier to maintain and makes it more convenient for non-professional developers to use JSP page files. There are many tag libraries now, either commercial products or source code open products. But most of these products only implement functions that could have been implemented in a simple Java Scriptlet, and few products use custom tags in some creative way, providing usage that is nearly impossible to implement before the JSP custom tag library appears.

The OSCache tag library is designed by OpenSymphony, a pioneering JSP custom tagging application that provides the ability to implement fast memory buffering within existing JSP pages. Although some suppliers are already offering various forms of cache products, they are all products for specific suppliers. OSCache is able to run on any JSP 1.1-compatible server, which can not only buffer existing JSP code blocks for all users, but also buffer in users. OSCache also includes some advanced features that improve scalability, such as: buffering to disk, programmable buffering flushing, exception control, and more. Additionally, like OpenSymphony's other products, OSCache's code is also released for free under an open source license.

This article takes a hypothetical auction website design process as an example to introduce the working process of OSCache. This imaginary web site will include: a management page that reports recent auction events; a homepage with complete functions and various promotional information; and a special navigation bar that contains all the users' unsold auction events.

2. Management page

The auction website contains a management report, and it takes seconds for the database server to create such a report. It is important to have long report generation time because we may have multiple administrators monitor the system's operation while also wanting to avoid regenerating the report every time the administrator visits. To achieve this, we will encapsulate the entire page into an application-level buffered mark, which is refreshed every 1 hour. Some products from other vendors have similar features, except that OSCache does better than them.

For simple purposes, we will not pay much attention to format issues. When writing an administrative page, we first add the tag library declaration to the page:

<%@ taglib uri="cachetags" prefix="cache" %>

Next we will use cache tags to surround the entire page. The default buffering time for cache tags is 1 hour.

<cache:cache> .... Complex management reports .... </cache:cache>

The management page has now been buffered. If the administrator accesses the same page again within one hour after the page is generated, what he sees will be the previously cached page and the database server does not need to generate this report again.

3. Home page

The homepage of the auction website shows the website activity and promotes those auctions that are about to end. We want to show the number of auctions ongoing, the number of current login users, the list of auctions that will end in the short term, and the current time. This information has different time accuracy requirements. Auctions on the website usually last for several days, so we can set the time to buffer the number of effective auctions to 6 hours. The number of users will obviously change more frequently, but here we will buffer this value for 15 minutes each time. Finally, we want the current time displayed in the page to always be the exact page access time.

After declaring the tag library in the home page, we first output the current date directly in a buffered manner:

Now it is: <%=new ()%>

Next, we want to show a list of those auction activities that will end in the short term:

<cache:cache> <ul> <% // Construct an Iterator containing the latest auction Iterator auctions = .... while (()) { Auction auction = (Auction)(); %><li><%=auction%></li%< } %> </ul> </cache:cache>

Finally, we want to show the number of ongoing auctions, which requires 6 hours of buffering. Since the cache tag requires the number of seconds to buffer the data, we convert 6 hours to 21,600 seconds:

<cache:cache time="21600"> <% //Query the database to get the total number of auction activities int auctionCount = .... %> There are <%=auctionCount%> ongoing auction activities on this website! </cache>

As you can see, we constructed a homepage with a complex buffering system using only a small amount of code. This buffering system buffers each part of the page separately, and the buffering time of each part is exactly in line with the degree of frequency of their respective information changes. With buffering, we can now put more content in the homepage; in the past, when there was no buffering, putting too much content in the homepage would slow down the page access speed and might even bring too much load to the database server.

4. Navigation bar

Suppose when planning the website, we decided to display the cart content below the left navigation bar. We will display the number of bids and current quotes for each item auctioned by the user, as well as a list of all those items with the highest bids currently by the user.

We use session-level buffering capabilities to construct the above functions in the navigation bar. Put the following code into the template or include the file so that other pages in the website can refer to this navigation bar:

<cache:cache key="navbar" scope="session" time="300"> <% //Extract and display the current bid information %> </cache:cache>

Here we introduce two important properties, namely key and scope. In the code earlier in this article, since the cache tag can automatically create a unique key for the code block, we do not need to manually set this key attribute. But here we want to reference this buffered code block from the rest of the website, so we explicitly define the key attribute of that cache tag. Second, the scope attribute is used to tell cache to mark the current code block must be buffered in users, rather than buffering once for all users.

It should be very careful when using session-level buffering, and it should be clear: while we can reduce complex navigation bars by 5 or 10 times the server load, it will greatly increase the memory space required for each session. In terms of CPU capabilities, it is undoubtedly ideal to increase the number of concurrent users, but this solution is no longer ideal once the number of concurrent users is reduced to the CPU limit in terms of memory support capabilities.

As mentioned earlier in this article, we want to reference this buffered code block from the rest of the website. This is because when a user adds an item for auction, or bids for items for auction by other users, we want to refresh the buffer so that the navigation bar will have the latest content the next time it is read. While this data may change due to the activity of other users, if the user sees his listing still not changed after performing an action on the website.

The flush tag provided by the OSCache library can refresh buffered content. We can add the following code to the page that handles user actions and may affect this area:

<cache:flush key="navbar" scope="session" />

The navbar buffer block will be refreshed the next time the user accesses it.

So far, the construction work of our sample website has been completed and can be started. Let’s take a look at the exception handling capabilities of OSCache. Even if the buffered content is invalid, such as a Java exception in the buffer block, the OSCache tag library still allows us to display these contents in a programmatic way. With this exception control function, we can remove the connection between the database server and the web server, and the website can continue to run. The JSP 1.2 specification introduces the TryCatchFinally interface, which allows the tag itself to detect and handle Java exceptions. Therefore, tags can be combined with this exception handling code, making the JSP page simpler and more organized.

OpenSymphony is planning to implement other buffering mechanisms and a better manageable main system that will enable us to manage the RAM and disk space used by the buffer. Once these features are available, we can further improve the response speed and reliability of our website.

【Conclusion】OSCache can help us build more colorful and higher performance websites. With the help of the OSCache tag library, we can now use it to solve some problems that affect website response capabilities, such as peak visits and overloaded database servers.