1. Overview
In Web applications, the generation of some reports may take a long time for the database to calculate; some websites provide weather information, which requires access to a remote server to make a SOAP call to obtain temperature information. All of these are examples of complex information. Adding too much complex information to a Web page may cause the Web server and database server to be overloaded. JSP code block buffering gives developers the freedom to add all kinds of complex information at will.
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 already many tag libraries, which are either commercial products or open source products. But most of these products only use tag libraries to implement functions that can be implemented with a simple Java Scriptlet. Few products use custom tags in some creative way, providing almost the same functionality before the emergence of JSP custom tag libraries. Impossible usage.
The OSCache tag library, designed by OpenSymphony, is a groundbreaking JSP custom tag application that provides fast memory caching within existing JSP pages. While there are a few vendors offering caching products in various forms, they are all vendor-specific products. OSCache can run on any JSP 1.1-compliant server, and it can cache existing JSP code blocks not only for all users, but also on a per-user basis. OSCache also includes some advanced features to improve scalability, such as buffering to disk, programmable buffer flushing, exception control, etc. Additionally, like other OpenSymphony products, OSCache's code is freely distributed under an open source license.
This article takes an imaginary 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 activities; a fully functional home page with various promotional information; and a special navigation bar that contains information about all the user's unsettled auction activities.
2. Management page
The auction website contains a management report, and it takes several seconds for the database server to create such a report. It is important that the report takes a long time to be generated, because we may have multiple administrators monitoring the operation of the system, and we want to avoid regenerating the report every time the administrator visits. To achieve this, we will encapsulate the entire page into an application-level buffer tag that is refreshed every hour. Some products from other vendors have similar functionality, it's just that OSCache does it better than them.
For the sake of simplicity, we will not focus too much on formatting issues. When writing the management page, we first add the tag library declaration to the page:
<%@ taglib uri="cachetags" prefix="cache" %>
Next we have to surround the entire page with cache tags. The default cache time for cache tags is 1 hour.
<cache:cache> .... Complex management reports.... </cache:cache>
The management page has now been cached. If the administrator accesses the same page again within an hour after the page is generated, he will see the previously cached page, and there is no need for the database server to generate this report again.
3. Home page
The home page of the auction website displays website activities and promotes auctions that are about to end. We want to display the number of ongoing auctions, the number of currently logged in users, a list of auctions that are due to end in the near future, and the current time. These messages have different time accuracy requirements. Auctions on the website usually last for several days, so we can set the time to buffer the number of valid auctions to 6 hours. The number of users will obviously change more frequently, but here we will buffer this value for 15 minutes at a time. Finally, we want the current time displayed on the page to always be the exact time the page was accessed.
After declaring the tag library in the home page, we first output the current date directly without buffering:
now it is: <%=new java.util.Date()%>
Next, we want to display a list of those that will Auctions that end in the short term:
<cache:cache> <ul> <% // Construct an Iterator containing the most recent auctions Iterator auctions = .... while (auctions.hasMore()) { Auction auction = (Auction) auctions.next(); %><li><%=auction%></li%< } %> </ul> </cache:cache>
Finally, we want to display the number of ongoing auction activities. This Numbers need to be buffered for 6 hours. Since cache marking requires the number of seconds to cache data, we convert 6 hours into 21600 seconds:
<cache:cache time="21600"> <% //Query the database to get the total number of auction activities int auctionCount = .... %> There are <%=auctionCount%> ongoing auctions on this website! </cache>
As you can see, we only use a small amount of code to construct a homepage with a complex buffering system. This buffering system buffers each part of the page separately, and the buffering time of each part is fully consistent with the frequency of changes in their respective information. Thanks to buffering, we can now put more content on the homepage; without buffering before, putting too much content on the homepage will cause page access to slow down, and may even cause problems for the database server. Excessive load.
4. Navigation Bar
Suppose when planning the website, we decide to display the shopping cart content below the left navigation bar. We will display the number of bids and the current price for each item in the auction by the user, as well as a list of all those items for which the current user has the highest bid.
We use session-level buffering capabilities to construct the above functionality in the navigation bar. Put the following code into the template or include file so that other pages in the website can reference 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 attributes, 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 set this key attribute manually. But here, we want to reference this cached block of code from the rest of the site, so we explicitly define the key attribute of the cache tag. Second, the scope attribute is used to tell the cache to mark that the current code block must be buffered on a per-user basis, rather than buffering once for all users.
You should be very careful when using session-level buffering, and it should be clear: although we can make a complex navigation bar reduce the server load by 5x or 10x, it will greatly increase the memory space required per session. It is undoubtedly ideal to increase the number of possible concurrent users in terms of CPU capabilities, but once the number of concurrent users is reduced to the limit of the CPU in terms of memory support capabilities, this solution is no longer ideal.
As mentioned earlier in this article, we want to reference this buffered block of code from the rest of the site. This is because when a user adds an item for auction, or bids for items auctioned by other users, we want to refresh the buffer so that the navigation bar has the latest content the next time it is read. While this data may change due to the activity of other users, it may be very confusing for a user to see that his or her listing remains unchanged after performing an action on the site.
The flush tag provided by the OSCache library can refresh the buffer 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" />
When the user accesses it next time, the navbar buffer block will be refreshed.
So far, the construction of our sample website has been completed and can start running. Let's take a look at OSCache's exception handling capabilities. Even if the buffered content has been invalidated, such as a Java exception occurring within the buffer block, the OSCache tag library still allows us to display the content programmatically. With this exception control feature, we can tear down the connection between the database server and the web server, and the website will still be able to continue running. The JSP 1.2 specification introduced the TryCatchFinally interface, which allows the tag itself to detect and handle Java exceptions. Therefore, markup can be combined with this exception handling code to make JSP pages simpler and more organized.
OpenSymphony is planning to implement additional buffering mechanisms as well as a more manageable main system that will allow us to manage the RAM and disk space used by buffering. Once these features are in place, we will be able to further improve the responsiveness and reliability of the website.
[Conclusion]
OSCache can help us construct 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 the responsiveness of the website, such as peak traffic periods, overloaded database servers, etc.