tapestry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Tapestry > Performance and Clustering
Date Sat, 19 Jan 2013 16:59:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/2042/9/12/_/styles/combined.css?spaceKey=TAPESTRY&amp;forWysiwyg=true"
type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="https://cwiki.apache.org/confluence/display/TAPESTRY/Performance+and+Clustering">Performance
and Clustering</a></h2>
    <h4>Page  <b>added</b> by             <a href="https://cwiki.apache.org/confluence/display/~bobharner">Bob
Harner</a>
    </h4>
         <br/>
    <div class="notificationGreySide">
         <h1><a name="PerformanceandClustering-PerformanceandClustering"></a>Performance
and Clustering</h1>

<p>Tapestry has a great performance story to tell. It's designed to take advantage of
the speed of the modern JVM: no reflection, built to support a high level of concurrency without
contention, and clean, lightweight code paths. In addition, there is built-in integrated GZIP
content compression, far-future expires headears on static resources, JavaScript and CSS merging,
JavaScript minification, and an intentionally lightweight use of the HTTPSession. The result
is a blistering fast framework. See <a href="http://tapestry.apache.org/2011/06/13/tapestrys-performance-tested.html"
class="external-link" rel="nofollow">Tapestry's Performance Tested</a> for some objective
numbers.</p>

<h2><a name="PerformanceandClustering-PerformanceTips"></a>Performance Tips</h2>

<p>Even with all that Tapestry does for you, to really get top performance you'll need
to be sure you're not hamstringing Tapestry. As a start, use the following checklist:</p>

<ul>
	<li>Ensure (really be sure) that Production Mode is turned on in production.</li>
	<li>Minimize the use of the HTTPSession (see below), especially if you're using clustering.</li>
	<li>Ensure that your static resources (images, CSS, JavaScript) are being cached by
the browser
	<ul>
		<li>Use the <em>asset</em> or <em>context</em> binding prefix
for all links to static resources (images, CSS, JavaScript).</li>
		<li>Make sure that your firewall, proxy server, load balancer, front-end web servers,
and app servers all allow caching of static resources.</li>
		<li>Ensure "cache-control" and "vary" HTTP headers are set correctly for your static
resources</li>
		<li>Use a client-based tool (like Firebug) to examine the requests that your browser
makes as you navigate through the site. You should <em>not</em> see repeated requests
for static resources.</li>
	</ul>
	</li>
	<li>Consider using a <a href="http://en.wikipedia.org/wiki/Content_delivery_network"
class="external-link" rel="nofollow">Content Delivery Network</a> for static parts
of your site.</li>
</ul>


<p>After all of the above issues are addressed, if you still have performance problems,
they probably aren't related to Tapestry.</p>

<h2><a name="PerformanceandClustering-ClusteringversusStickySessions"></a>Clustering
versus Sticky Sessions</h2>

<p>For web applications, <b>clustering</b> is a load-balancing technique
in which multiple application servers are set up to behave as one big server. Generally this
requires replicating HttpSession data across the servers, to ensure that a user's web interactions
will continue without interruption regardless of which server handles the next request. Session
replication achieves very high reliability, but it incurs an extra performance cost (due to
the serializing and deserializing of session data and the extra network traffic required).</p>

<p>In contrast, <b>Sticky Sessions</b> (also called <em>session persistence</em>
or <em>sticky persistence</em>) is a load balancing technique in which each session
is assigned to a particular server for the duration of the session. This approach doesn't
require copying HTTPSession data between servers, so it's very scalable. But if a server goes
down, all of its sessions are lost.</p>

<p>In general, the sticky sessions approach is the way to go when possible (that is,
when performance is more important than session survival).  It represents a much more efficient
use of resources ... you are scaling <b>out</b> not <b>up</b>, which
is always cheaper. It also means that you don't have to be a careful about what goes into
the HTTPSession.</p>

<p><em>For details on setting up clustering and sticky sessions, see the documentation
of whatever load balancer you are using.</em></p>

<h2><a name="PerformanceandClustering-Clustering"></a>Clustering</h2>

<p>Tapestry is designed to be "a good citizen" of an application server that supports
clustering.  It is careful about what it writes into the HttpSession.  The framework understands
that the server that receives a request may not be the same one that rendered the page initially;
this knowlege affects many code paths, and it guides the approach Tapestry takes to caching
page and component properties.</p>

<p>Your part is to properly manage the objects put into the HttpSession (via @SessionAttribute,
@SessionState or @Persist; see <a href="/confluence/display/TAPESTRY/Session+Storage" title="Session
Storage">Session Storage</a>):</p>

<ul>
	<li>Don't store anything in the session that you don't have to. Principally this means
to minimize the use of @Persist (see <a href="/confluence/display/TAPESTRY/Using+Select+With+a+List"
title="Using Select With a List">Using Select With a List</a>, storing IDs rather
than whole entities.</li>
	<li>Where possible, persist only objects that are immutable (i.e., String, or a primitive
or wrapper type).</li>
	<li>Only put <em>serializable</em> objects into the session.</li>
	<li>Make use of the @ImmutableSessionPersistedObject annotation and OptimizedSessionPersistedObject
interface (both described below).</li>
</ul>


<p>Again, Tapestry is a good citizen, but from the application server's point of view,
it's just another servlet application.  The heavy lifting here is application server specific.</p>

<h2><a name="PerformanceandClustering-ClusteringIssues"></a>Clustering Issues</h2>

<p>The Servlet API was designed with the intention that there would be only a modest
amount of server-side state, and that the stored values would be individual numbers and strings,
and thus, immutable.</p>

<p>However, many web applications do not use the HttpSession this way, instead storing
large, mutable objects in the session. This is not a problem for single servers, but in a
cluster, anything stored in the session must be serialized to a bytestream and distributed
to other servers within the cluster, and restored there.</p>

<p>Most application servers perform that serialization and distribution whenever HttpSession.setAttribute()
is called. This creates a data consistency problem for mutable objects, because if you read
a mutable session object, change its state, but <em>don't</em> invoke setAttribute(),
the changes will be isolated to just a single server in the cluster.</p>

<p>Tapestry attempts to solve this: any session-persisted object that is read during
a request will be re-stored back into the HttpSession at the end of the request. This ensures
that changed internal state of those mutable objects is properly replicated around the cluster.</p>

<p>But while this solution solves the data consistency problem, it does so at the expense
of performance, since all of those calls to setAttribute() result in extra session data being
replicated needlessly if the internal state of the mutable object hasn't changed.</p>

<p>Tapestry has solutions to this, too:</p>

<h3><a name="PerformanceandClustering-@ImmutableSessionPersistedObjectAnnotation"></a>@ImmutableSessionPersistedObject
Annotation</h3>

<p>Tapestry knows that Java's String, Number and Boolean classes are immutable. Immutable
objects do not require a re-store into the session.</p>

<p>You can mark your own session objects as immutable (and thus not requiring session
replication) using the <a href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/ImmutableSessionPersistedObject.html"
class="external-link" rel="nofollow">ImmutableSessionPersistedObject</a> annotation.</p>

<h3><a name="PerformanceandClustering-OptimizedSessionPersistedObjectInterface"></a>OptimizedSessionPersistedObject
Interface</h3>

<p>The <a href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/OptimizedSessionPersistedObject"
class="external-link" rel="nofollow">OptimizedSessionPersistedObject</a> interface
allows an object to control this behavior. An object with this interface can track when its
mutable state changes. Typically, you should extend from the <a href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/BaseOptimizedSessionPersistedObject.html"
class="external-link" rel="nofollow">BaseOptimizedSessionPersistedObject</a> base
class.</p>

<h3><a name="PerformanceandClustering-SessionPersistedObjectAnalyzerService"></a>SessionPersistedObjectAnalyzer
Service</h3>

<p>The <a href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/SessionPersistedObjectAnalyzer.html"
class="external-link" rel="nofollow">SessionPersistedObjectAnalyzer</a> service is
ultimately responsible for determining whether a session persisted object is dirty or not
(dirty meaning in need of a restore into the session). This is an extensible service where
new strategies, for new classes, can be introduced.</p>
    </div>
    <div id="commentsSection" class="wiki-content pageSection">
       <div style="float: right;">
            <a href="https://cwiki.apache.org/confluence/users/viewnotifications.action"
class="grey">Change Notification Preferences</a>
       </div>
       <a href="https://cwiki.apache.org/confluence/display/TAPESTRY/Performance+and+Clustering">View
Online</a>
           </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message