Edge Side Includes (ESI)

Traditionally web applications were meant to serve static content, wherein the server generated an HTML response to the client’s request (typically HTTP) and sent it back to the client. The response was then rendered on user’s screen (browser window) by the client (browser). In order to increase user-perceived performance, such static content was cached at the edge of Internet so that it could be served faster. Content Delivery Networks (CDNs) have been used commercially for such purposes.
As the web-application ecosystem evolved, rich-internet applications and mashups got popular. Rich-Internet applications meant that data (a web page) served by the server is dynamic i.e. it is a function of the state of client’s request (logged in user, cookies, session variables etc). Though web page of such an application is dynamic as a whole, certain fragments (sections) of the page are still static given the current state of the application. CDN’s can’t be used in such scenarios as it assumes the cached entity to be static as a whole. It can’t separately cache fragments of a cached entity and assemble them back (based on the state of client’s request and application logic) before serving the client’s request.
Edge Side Includes (ESI) is a W3C acknowledged standard which supports fragment assembly model and can be extended to cache dynamic web pages on the edges of Internet just like CDNs are used to cache static content. It provides semantics on how to assemble dynamic content at the edge, when to cache content, when to expire content etc. In this article I’ll describe the concepts of ESI, a java implementation of ESI processor and how to develop and deploy ESI enabled application.
download
Figure 1: Facebook Home Page Fragments

Fragmentation of a Web-Page

In a modern day web application, a web page is modularised as divs, which can be considered as fragments of the web page. A Facebook user’s home page consists of several fragments, highlighted in red rectangular boxes (see Figure 1). A keen observation of these boxes would reveal that the static-ness of data contained in the boxes varies. For e.g. data of the left most vertical box data (menu bar, #1) would not change in probably few months, while the data of bottom right box (friends list, #4) would change in probably few days. The data of rectangular box (news feed, #2) would change in probably few seconds, while the data of  rectangular box (ads, #3) would change in probably few minutes. Also the content (data and layout) of one fragment is independent of the other. ESI seeks to harness these properties of web-page fragments in order to improve user-perceived latency of a web-page.

Perceived Performance Improvement

Performance improvement is achieved in following ways:
  •     By parallelising the generation of individual fragments.
  •     By interleaving page generation and page rendering.
  •     By caching the fragments.
Generating the fragments in parallel (by harnessing multiple cores of an application server) reduces the generation time of a web-page to maximum fragment generation time among all fragments. By careful modularisation, generation time of a web-page can be brought down significantly.
Interleaving page generation and page rendering means the client (browser) does not have to wait for the server to complete it’s page generation, it can render the page fragment while the server is still busy generation other fragments. This is achieved by Chunked encoding  method of transfer supported in HTTP 1.1 and higher, which allows the server to ignore the header value and divide the response result from HTTP into a series of chunk, and then transfer each chunk of the result.
Caching fragments is advantageous in two ways:
  • Network latency to carry the fragment payload from application server to client is significantly reduced as the fragment is served from an edge-server.
  • Application server does not have to re-generate fragments within fragment lifetime and thereby freeing up compute resources of application server which in turn reduces effective fragment generation time.
ESI Architecture
Figure 2: ESI Architecture

ESI Architecture

A Typical ESI deployment would contain an ESI processor (deployed at the Edges of Internet) which intercept requests from client and requests one or more web servers for web-page fragments. On receipt of a fragment it parses the fragment, processes the contained  (if any) esi tags and streams the output back to the client. The caching properties and url mapping is stored in configuration files of  ESI Processor.
The ESI processor can be seen as proxy-server which not only redirects incoming client requests but also processes and caches the responses coming from the actual servers before responding to the client.

ESI Elements

Edge Side Includes (ESI) is a simple markup language used to define Webpage components for dynamic assembly and delivery of Web Applications at the edges of the Internet. ESI being a mark-up language, it’s elements are XML in an ESI-specific XML Namespace which can be embedded in common web document formats such as HTML and XML-based server-side processing languages. ESI processor parses all elements but do no process elements outside ESI namespace. Processing also includes striping out the ESI tags from the output.
ESI:Include
The include element specifies a fragment for assembly and allows for three optionally specified behaviours. It’s an employ element and does not have a closing tag. For example:
<esi:include src=”URI” alt=“URI” onerror=“continue” ttl=50/>
The include statement tells the ESI processor to fetch the fragment specified by the src attribute. The URI value can be an absolute path (http://www.example.com/1.html) or a relative path (/1.html), relative URLs are resolved using the parent page URI.  The ttl attribute, if present, tells the ESI processor to cache the fragment for specified seconds. If its not present this fragment is never cached. The alt attribute specifies the alternate URI to fetch the fragment in case src is not found.
If an ESI processor can’t fetch either the src or the alt, it returns a HTTP status code greater than 400 with an error message, unless the onerror attribute is present. If it’s value is set to ‘continue’, ESI processor deletes the include element silently.
ESI: vars
The var element is used to define markup with ESI variable outside ESI block. No fragment is fetched here but just variable substitution. For example:
 
<img src=http://www.example.com/$(HTTP_COOKIE{type})/hello.gif”/ >
ESI: choose | when | otherwise
This element is analogous to switch statement of Java, used to perform logic based on expressions. For example:
       <esi:when test=“$(HTTP_COOKIE{group})==’Advanced'”>
               <esi:include src=http://www.example.com/advanced.html&#8221;/>
      
       <esi:when test=“$(HTTP_COOKIE{group})==’Basic User'”>
              <esi:include src=http://www.example.com/basic.html&#8221;/>
      
      
              <esi:include src=http://www.example.com/new_user.html&#8221;/>
     
ESI: try | attempt | except
This element is used for exception handling, analogous to try-catch of Java. The markup inside the attempt block is executed, which if throws an error the markup inside except block is executed. For example:

<esi:comment text=“Include an ad”/>

               <esi:include src=http://www.example.com/ad1.html&#8221;/>
<esi:comment

text=“Just write some HTML instead”/>
<a href=http://www.akamai.com>www.example.com

ESI Variables

ESI supports the following read-only variables based on the client’s HTTP request line and headers:

ESI Variables
Variable Name
HTTP Header
Substructure Type
Example
HTTP_ACCEPT_LANGUAGE
Accept-Language
list
da, en-gb, en
HTTP_COOKIE
Cookie
dictionary
id=571; visits=42
HTTP_HOST
Host
esi.xyz.com
HTTP_REFERER
Referer
HTTP_USER_AGENT
User-Agent
dictionary (special)
Mozilla; MSIE 5.5
QUERY_STRING
dictionary
first=Robin&last=Roberts

Variable names are always upper case, it is referenced by surrounding the name with parenthesis with a dollar ($) sign. For example – $(HTTP_HOST)

ESI Expressions

Conditional elements use expressions (in their test attributes) to determine how to apply the contained elements. Expressions consist of operators, variables and literals and evaluate to true or false. Following operators are supported:

Operators
Operator
Type
==, !=, <, >, <=, >=
comparison
!
unary negation
&
logical and
|
logical or


For more detailed ESI specifications refer – http://www.w3.org/TR/esi-lang. In the next blog, I will discuss the open-source java implementation of an ESI processor and an example of a web-application developed using the ESI processor library.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s