X

Best Practices from Oracle Development's A‑Team

Sites Page Caching, Remote SatelliteServer, Round-Trips and render tags

Dolf Dijkstra
Cloud Solutions Architect

As many of you know SatelliteServer comes in two variants: Co-Resident SatelliteServer and Remote SatelliteServer. In this blog I will explain how they differ from a Page Caching perspective, and how that related to ContentServer (Sites) Page Caching.

There are also two page fragment caching models in Sites, one is called ContentServer page cache and the other SatelliteServer pagelet cache.

When you are using Satellite Server (either remote or co-res), a web page (html) is composed out of pagelets. In a rare case this is only one pagelet, in many it are multiple pagelets per page. A pagelet is a data structure with an ordered list of mulitple text (html) fragements and mulitple references to other pagelets. Think of it as ServerSideIncludes. As pagelets can point to other pagelets you can build a nesting structure. This is normally hidden from you. The exposure you have is through the <render:calltemplate> tag and other render tags. If you are interested in the internal structure of a page, call this page on the ContentServer servlet and add the parameter ft_ss=true on the url, for instance http://localhost:9080/cs/ContentServer?c=Page&childpagename=MyLayout&cid=1374098080774&d=&pagename=MyWrapper&ft_ss=true. This returns the raw response from ContentServer to SatelliteServer and you can see the text blocks mixed with the nested pagelet calls.

Pagelets can be either cached or uncached. An uncached pagelet will be executed on ContentServer. A cached pagelet will be executed once on ContentServer and then cached on SatelliteServer *and* ContentServer to be used by many requests to serve pages to many visitors.

Now if you want to create fragments on your page that are unique to a visitor, such a pagelet needs to be uncached, for instance to display the logged in username, or to display the value of a session variable. If you want to interact with backend systems for a specific user/transaction you would need to do that in an uncached pagelet. In many cases update interactions are done in an unached wrapper pagelet. For instance the FirstSiteII sample site is using this to set the current locale for the user after he switched to another preferred language.

As I said you can many pagelets per page. In general the more pagelets (cached or uncached) you have per page the harder SatelliteServer needs to work and as a consequence your throughput and response times will suffer. It should now also be clear that having multiple uncached pagelets on a page is in general not optimal, as for each uncached pagelet for each request this pagelet needs to be requested from ContentServer. This is especially true when Remote SatelliteServer is deployed as each request for a pagelet is a HTTP request from SatelliteServer to ContentServer. In cases where your website/application requires many uncached pagelets it is very likely that you will get better throughput and reponse times when you use Co-Resident SatelliteServer as opposed to Remote Satellite Server.

With Remote SatelliteServer each not (yet) cached pagelet is a HTTP request from Remote SatelliteServer to ContentServer, for Co-Resident SatelliteServer this is all done in JVM.

There are several techniques to reduce the number of pagelets per page.

  • Have less uncached pagelets per page by changing you Template design. This usually requires redesign work, with associated costs. A switch from Remote to Co-Res Satellite Server might save the day if such a redesign is not possible; either technically or financially.
  • Reduce the number of cached pagelets by combining (inlining) them. A high number of pagelets usually happens when each <render:calltemplate> call is using the default style attribute value (pagelet). A consequence of this is that each call to a Tempate on a page is a new pagelet. The reduction of pagelets can be done in two ways: inlining the render:calltemplate calls either as element calls (style=element) or as ContentServer page fragments (style=embedded).

For explanation purposes assume that the web page has the following structure. A webpage is structured with a LayoutTemplate, with calls to TopNav, LeftNav, MainContent and Footer. The MainContent Template shows a list of 5 articles. The MainTemplate calls 5 ArticleTeaser Templates with the cid of each article. If you would not have considered the style attribute of the <render:calltemplate> call, you would have easily 10 pagelets (Layout + Top + Left + Main + 5 Articles + Footer) , plus a pagelet for each link (anchor, image etc), This can easily be hundreds of pagelets per page.

The Element style is the easiest to explain and also the straight forward. If a Template call is done this way the output of that Template is directly inlined with the current pagelet. You can compare this with a <jsp:include> call. When using this inlining technique there will be one pagelet cached on Satellite Server and one (the same one) on ContentServer. In our example: if you would call the MainContent from Layout with style=element then the Layout and the MainContent pagelets would collapse to one, reducing the number of pagelets with one. This also has a side effect: each time when the pagelet needs to be rendered, for instance after a publish, all the included Templates on that Tempate will need to be executed also. So, if you would inline the MainContent from Layout with style=element, each time when the Layout pagelet needs to be rendered the MainContent also needs to be rendered. I hope that you can see than it is usually a good idea to call Link Templates with style=element as this will quickly reduce the number of pagelets per page.

The other inlining variant is embedded. The difference with style=element is that the <render:calltemplate> call is resulting in a cached fragment on ContentServer. It is as a <jsp:include> where the included fragment is cached itself and is inlined in the response. This in case where the Layout pagelet needs to be re-rendered the MainContent would not. The render:calltemplate tag is accessing the ContentServer page cache  to retrieve the (cached) output from the MainContent Template call. This is most usefull when you need to render a list of Templates, whereby each included Template is relatively expensive to render. In our case the Template calls from the MainContent to the 5 articles would be the perfect use case. The 5 Article have probably a different life cycle than the MainContent asset. For instance if the MainContent asset is a static Recommendation with 5 assets in its list, then each time the Recommendation is changed and published would force the MainContent Template/pagelet to be re-rendered but the 5 Article Templates don't.

Now there is another aspect of caching you need to consider. That is the total number of items in the cache, both for ContentServer and SatelliteServer page cache. This is limited. Thus you also want to make sure that you don't have too many page fragments cached on ContentServer either. You would need to monitor your caches to understand if they are too becoming big and if changing the inlining style would reduce the number of items in cache to a more optimal value. Another issue with the total number of page fragements and pagelets in cache is that the cache keys are incorrect and that arguments are passed to templates that are not needed to change the behaviour of the Template. Only variables that are needed to render the Template should be passed, not accidentially others as this will result in two different pagelets with exactly the same content.

Besides the 3 different inlining styles you would also need to consider the caching style of each Template. This is especially important if you change from a cached to an uncached pagelet or vice versa. The table below explains the different scenarios.

style
current pagelet called pagelet pagelet embedded element
cached cached new pagelet, likely not optimal Inlined, likely to be optimal if c/cid change from current to called pagelet  Inlined, likely to be optimal if c/cid are the same from current to called pagelet
cached uncached new pagelet, optimal inlined, caused the  current pagelet to be uncached! inlined, target caching ignored > target would be cached
uncached cached new pagelet, optimal inlined, likely not optimal inlined, target caching ignored
uncached uncached new pagelet, not optimal, style=element is better inlined uncached fragement, not optimal due to overhead of pagelet call inlined, optimal

You also would need to consider expiration time of a pagelet when using embedded. A embedded fragment in a pagelet will get the same expiration as that from the current pagelet. If you had set a shorter expiration on the included pagelet then that embedded fragment would be longer cached than expected.

Now you may ask yourself: why would I break up my page in pagelets? There are several reasons.

  • Pagelets can be reused on other pages. For instance the Top, LeftNav and Footer are likely candidates to be reused on many pages. It is also likely that these will not be Templates but SiteEntries, and called with the appropriate render tags. This has both a memory and a processing reduction advantage over caching whole pages.
  • Reuse over time due to different compositional dependencies. With Sites, each pagelet and ContentServer page cache fragment knows which assets are used when rendering the page. This information is used during publishing to clean up the cache for the published assets. This means that if a pagelet is rendered with 2 assets, only those two assets can cause the pagelet to be invalidated. If 200 assets are used whilst rendering that pagelet, any of those 200 can cause the pagelet to be invalidated. This means that it is more likely that this pagelet will be uncached with the corresponding need to re-render. If you find that pagelets get flushed too often and they are expensive to re-render, you may want to split them, considering all off the above. There is a special compositional dependency called unknowndeps that would cause a pagelet to always be invalidated upon publish.
  • It allows to switch between cached and uncached fragments on a page. Maybe you want to show something in the MainContent that is personalized, so you can configure Layout and the articles to be cached, and the MainContent to be uncached. With just ContentServer page caching this is not possible.

REMEMBER:

  • The default style=pagelet from render:calltemplate tag is far from optimal in every case. With less pagelets per page you will get better repsonse times and throughput.
  • If you have uncached pagelets on a page, Co-Resident SatelliteServer is likely to give better responsetimes than Remote SatelliteServer.
  • When tuning constantly ask the question: is the application CPU or memory bound. How can I take that bottleneck away.

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha