Caucho Technology
  • resin 4.0
  • resin clustering


    As traffic increases beyond a single server, Resin's clustering lets you add new machines to handle the load and simultaneously improves uptime and reliability by failing over requests from a downed or maintenance server to a backup transparently.

    Persistent Sessions

    A session needs to stay on the same JVM that started it. Otherwise, each JVM would only see every second or third request and get confused.

    To make sure that sessions stay on the same JVM, Resin encodes the cookie with the host number. In the previous example, the hosts would generate cookies like:

    INDEXCOOKIE PREFIX
    1axxx
    2bxxx
    3cxxx

    On the web-tier, Resin will decode the cookie and send it to the appropriate host. So bacX8ZwooOz would go to app-b.

    In the infrequent case that app-b fails, Resin will send the request to app-a. The user might lose the session but that's a minor problem compared to showing a connection failure error.

    The following example is a typical configuration for a distributed server using an external hardware load-balancer, i.e. where each Resin is acting as the HTTP server. Each server will be started as -server a or -server b to grab its specific configuration.

    In this example, sessions will only be stored when the server shuts down, either for maintenance or with a new version of the server. This is the most lightweight configuration, and doesn't affect performance significantly. If the hardware or the JVM crashes, however, the sessions will be lost. (If you want to save sessions for hardware or JVM crashes, remove the <save-only-on-shutdown/> flag.)

    resin.xml
    <resin xmlns="http://caucho.com/ns/resin">
    <cluster id="app-tier">
      <server-default>
        <http port='80'/>
      </server-default>
    
      <server id='app-a' address='192.168.0.1'/>
      <server id='app-b' address='192.168.0.2'/>
      <server id='app-c' address='192.168.0.3'/>
    
      <web-app-default>
        <!-- enable tcp-store for all hosts/web-apps -->
        <session-config>
          <use-persistent-store/>
          <save-only-on-shutdown/>
        </session-config>
      </web-app-default>
    
      ...
    </cluster>
    </resin>
    

    Choosing a backend server

    Requests can be made to specific servers in the app-tier. The web-tier uses the value of the jsessionid to maintain sticky sessions. You can include an explicit jsessionid to force the web-tier to use a particular server in the app-tier.

    Resin uses the first character of the jsessionid to identify the backend server to use, starting with 'a' as the first backend server. If wwww.example.com resolves to your web-tier, then you can use:

    1. http://www.example.com/proxooladmin;jsessionid=abc
    2. http://www.example.com/proxooladmin;jsessionid=bcd
    3. http://www.example.com/proxooladmin;jsessionid=cde
    4. http://www.example.com/proxooladmin;jsessionid=def
    5. http://www.example.com/proxooladmin;jsessionid=efg
    6. etc.

    File Based

    For single-server configurations, the "cluster" store saves session data on disk, allowing for recovery after system restart or during development.

    Sessions are stored as files in the resin-data directory. When the session changes, the updates will be written to the file. After Resin loads an Application, it will load the stored sessions.

    Distributed Sessions

    Distributed sessions are intrinsically more complicated than single-server sessions. Single-server session can be implemented as a simple memory-based Hashtable. Distributed sessions must communicate between machines to ensure the session state remains consistent.

    Load balancing with multiple machines either uses sticky sessions or symmetrical sessions. Sticky sessions put more intelligence on the load balancer, and symmetrical sessions puts more intelligence on the JVMs. The choice of which to use depends on what kind of hardware you have, how many machines you're using and how you use sessions.

    Distributed sessions can use a database as a backing store, or they can distribute the backup among all the servers using TCP.

    Symmetrical Sessions

    Symmetrical sessions happen with dumb load balancers like DNS round-robin. A single session may bounce from machine A to machine B and back to machine B. For JDBC sessions, the symmetrical session case needs the always-load-session attribute described below. Each request must load the most up-to-date version of the session.

    Distributed sessions in a symmetrical environment are required to make sessions work at all. Otherwise the state will end up spread across the JVMs. However, because each request must update its session information, it is less efficient than sticky sessions.

    Sticky Sessions

    Sticky sessions require more intelligence on the load-balancer, but are easier for the JVM. Once a session starts, the load-balancer will always send it to the same JVM. Resin's load balancing, for example, encodes the session id as 'aaaXXX' and 'baaXXX'. The 'aaa' session will always go to JVM-a and 'baa' will always go to JVM-b.

    Distributed sessions with a sticky session environment add reliability. If JVM-a goes down, JVM-b can pick up the session without the user noticing any change. In addition, distributed sticky sessions are more efficient. The distributor only needs to update sessions when they change. So if you update the session once when the user logs in, the distributed sessions can be very efficient.

    always-load-session

    Symmetrical sessions must use the 'always-load-session' flag to update each session data on each request. always-load-session is only needed for jdbc-store sessions. tcp-store sessions use a more-sophisticated protocol that eliminates the need for always-load-session, so tcp-store ignores the always-load-session flag.

    The always-load-session attribute forces sessions to check the store for each request. By default, sessions are only loaded from persistent store when they are created. In a configuration with multiple symmetric web servers, sessions can be loaded on each request to ensure consistency.

    always-save-session

    By default, Resin only saves session data when you add new values to the session object, i.e. if the request calls setAttribute. This may be insufficient when storing large objects. For example, if you change an internal field of a large object, Resin will not automatically detect that change and will not save the session object.

    With always-save-session Resin will always write the session to the store at the end of each request. Although this is less efficient, it guarantees that updates will get stored in the backup after each request.

    Cluster Sessions

    The distributed cluster stores the sessions across the cluster servers. In some configurations, the cluster store may be more efficient than the database store, in others the database store will be more efficient.

    With cluster sessions, each session has an owning JVM and a backup JVM. The session is always stored in both the owning JVM and the backup JVM.

    The cluster store is configured in the in the <cluster>. It uses the <server> hosts in the <cluster> to distribute the sessions. The session store is enabled in the <session-config> with the <use-persistent-store>.

    <resin xmlns="http://caucho.com/ns/resin">
      ...
    
      <cluster id="app-tier">
        <server id="app-a" host="192.168.0.1" port="6802"/>
        <server id="app-b" host="192.168.0.2" port="6802"/>
    
        ...
      </cluster>
    </resin>
    

    The configuration is enabled in the web-app.

    <web-app xmlns="http://caucho.com/ns/resin">
      <session-config>
        <use-persistent-store="true"/>
      </session-config>
    </web-app>
    

    The <server> are treated as a cluster of server. Each server uses the other servers as a backup. When the session changes, the updates will be sent to the backup server. When the server starts, it looks up old sessions in the other servers to update its own version of the persistent store.

    Symmetric load-balanced servers
    <resin xmlns="http://caucho.com/ns/resin">
    <cluster id="app-tier">
    
      <server-default>
        <http port='80'/>
      </server-default>
    
      <server id="app-a" address="192.168.2.10" port="6802"/>
      <server id="app-b" address="192.168.2.11" port="6803"/>
    
      <host id=''>
      <web-app id=''>
    
      <session-config>
        <use-persistent-store="true"/>
      </session-config>
    
      </web-app>
      </host>
    </cluster>
    </resin>
    

    Clustered Distributed Sessions

    Resin's cluster protocol for distributed sessions can is an alternative to JDBC-based distributed sessions. In some configurations, the cluster-stored sessions will be more efficient than JDBC-based sessions. Because sessions are always duplicated on separate servers, cluster sessions do not have a single point of failure. As the number of servers increases, JDBC-based sessions can start overloading the backing database. With clustered sessions, each additional server shares the backup load, so the main scalability issue reduces to network bandwidth. Like the JDBC-based sessions, the cluster store sessions uses sticky-session caching to avoid unnecessary network traffic.

    Configuration

    The cluster configuration must tell each host the servers in the cluster and it must enable the persistent in the session configuration with use-persistent-store. Because session configuration is specific to a virtual host and a web-application, each web-app needs use-persistent-store enabled individually. The web-app-default tag can be used to enable distributed sessions across an entire site.

    resin.xml fragment
    <resin xmlns="http://caucho.com/ns/resin">
      ...
      
      <cluster id="app-tier">
    
        <server id="app-a" host="192.168.0.1"/>
        <server id="app-b" host="192.168.0.2"/>
        <server id="app-c" host="192.168.0.3"/>
        <server id="app-d" host="192.168.0.4"/>
    
        ...
        <host id="">
        <web-app id='myapp'>
          ...
          <session-config>
            <use-persistent-store/>
          </session-config>
        </web-app>
        </host>
      </cluster>
    </resin>
    

    Usually, hosts will share the same resin.xml. Each host will be started with a different -server xx to select the correct block. The startup will look like:

    Starting Server C
    resin-4.0.x> java -jar lib/resin.jar -conf conf/resin.xml -server c start
    

    always-save-session

    Resin's distributed sessions needs to know when a session has changed in order to save the new session value. Although Resin can detect when an application calls HttpSession.setAttribute, it can't tell if an internal session value has changed. The following Counter class shows the issue:

    Counter.java
    package test;
    
    public class Counter implements java.io.Serializable {
      private int _count;
    
      public int nextCount() { return _count++; }
    }
    

    Assuming a copy of the Counter is saved as a session attribute, Resin doesn't know if the application has called nextCount. If it can't detect a change, Resin will not backup the new session, unless always-save-session is set. When always-save-session is true, Resin will back up the session on every request.

    ...
    <web-app id="/foo">
    ...
    <session-config>
      <use-persistent-store/>
      <always-save-session/>
    </session-config>
    ...
    </web-app>
    

    Serialization

    Resin's distributed sessions relies on Hessian serialization to save and restore sessions. Application object must implement java.io.Serializable for distributed sessions to work.

    Protocol Examples

    Session Request

    To see how cluster sessions work, consider a case where the load balancer sends the request to a random host. Server C owns the session but the load balancer gives the request to Server A. In the following figure, the request modifies the session so it must be saved as well as loaded.

    The session id encodes the owning host. The example session id, ca8MbyA, decodes to an server index of 3, mapping to Server C. Resin determines the backup host from the cookie as well. Server A must know the owning host for every cookie so it can communicate with the owning srun. The example configuration defines all the sruns Server A needs to know about. If Server C is unavailable, Server A can use its configuration knowledge to use Server D as a backup for ca8MbyA instead..

    When the request first accesses the session, Server A asks Server C for the serialized session data (2:load). Since Server A doesn't cache the session data, it must ask Server C for an update on each request. For requests that only read the session, this TCP load is the only extra overhead, i.e. they can skip 3-5. The always-save-session flag, in contrast, will always force a write.

    At the end of the request, Server A writes any session updates to Server C (3:store). If always-save-session is false and the session doesn't change, this step can be skipped. Server A sends the new serialized session contents to Server C. Server C saves the session on its local disk (4:save) and saves a backup to Server D (5:backup).

    Sticky Session Request

    Smart load balancers that implement sticky sessions can improve cluster performance. In the previous request, Resin's cluster sessions maintain consistency for dumb load balancers or twisted clients like the AOL browsers. The cost is the additional network traffic for 2:load and 3:store. Smart load-balancers can avoid the network traffic of 2 and 3.

    Server C decodes the session id, caaMbyA. Since it owns the session, Server C gives the session to the servlet with no work and no network traffic. For a read-only request, there's zero overhead for cluster sessions. So even a semi-intelligent load balancer will gain a performance advantage. Normal browsers will have zero overhead, and bogus AOL browsers will have the non-sticky session overhead.

    A session write saves the new serialized session to disk (2:save) and to Server D (3:backup). always-save-session will determine if Resin can take advantage of read-only sessions or must save the session on each request.

    Disk copy

    Resin stores a disk copy of the session information, in the location specified by the path. The disk copy serves two purposes. The first is that it allows Resin to keep session information for a large number of sessions. An efficient memory cache keeps the most active sessions in memory and the disk holds all of the sessions without requiring large amounts of memory. The second purpose of the disk copy is that the sessions are recovered from disk when the server is restarted.

    Failover

    Since the session always has a current copy on two servers, the load balancer can direct requests to the next server in the ring. The backup server is always ready to take control. The failover will succeed even for dumb load balancers, as in the non-sticky-session case, because the srun hosts will use the backup as the new owning server.

    In the example, either Server C or Server D can stop and the sessions will use the backup. Of course, the failover will work for scheduled downtime as well as server crashes. A site could upgrade one server at a time with no observable downtime.

    Recovery

    When Server C restarts, possibly with an upgraded version of Resin, it needs to use the most up-to-date version of the session; its file-saved session will probably be obsolete. When a "new" session arrives, Server C loads the saved session from both the file and from Server D. It will use the newest session as the current value. Once it's loaded the "new" session, it will remain consistent as if the server had never stopped.

    No Distributed Locking

    Resin's cluster sessions does not lock sessions. For browser-based sessions, only one request will execute at a time. Since browser sessions have no concurrently, there's no need for distributed locking. However, it's a good idea to be aware of the lack of distributed locking.

    Overview

    Adding a dynamic server to a cluster is a simple two-step process:

    1. Register the dynamic server with a triad server via JMX.
    2. Start the new dynamic server using the registration in the previous step.

    Preliminaries

    Before adding a dynamic server, you must:

    • Set up and start a cluster with a triad, e.g.
      Example: conf/resin.xml
      <resin xmlns="http://caucho.com/ns/resin">
      
      <cluster id="app-tier">
        ...
        <server id="triad-a" address="234.56.78.90" port="6800"/>
        <server id="triad-b" address="34.56.78.90" port="6800"/>
        <server id="triad-c" address="45.67.89.12" port="6800"/>
      
    • Install at least one admin password, usually in admin-users.xml
    • Enable the RemoteAdminService for the cluster, e.g.
      <resin xmlns="http://caucho.com/ns/resin">
      
      <cluster id="app-tier">
        ...
        <admin:RemoteAdminService xmlns:admin="urn:java:com.caucho.admin"/>
        ...
      
    • Enable the dynamic servers for the cluster, e.g.
      <resin xmlns="http://caucho.com/ns/resin">
      
      <cluster id="app-tier">
        ...
        <dynamic-server-enable>true</dynamic-server-enable>
        ...
      

    Check the main Clustering section for more information on this topic.

    Registering a dynamic server

    For the first step of registration, you can use a JMX tool like jconsole or simply use the Resin administration web console. We'll show how to do the latter method here. For registration, you'll specify three values:

    web-app deployment options
    NAMEDESCRIPTION
    Server idSymbolic identifier of the new dynamic server. This is also specified when starting the new server.
    IPThe IP address of the new dynamic server. May also be host name.
    PortThe server port of the new dynamic server. Usually 6800.

    With these three values, browse to the Resin administration application's "cluster" tab. If you have enabled dynamic servers for your cluster, you should see a form allowing you to register the server in the "Cluster Overview" table.

    Once you have entered the values and added the server, it should show up in the table as a dead server because we haven't started it yet. The dynamic server's registration will be propagated to all the servers in the cluster.

    Starting a dynamic server

    Now that we've registered the dynamic server, we can start it and have it join the cluster. In order for the new server to be recognized and accepted by the triad, it needs to start with the same resin.xml that the triad is using, the name of the cluster it is joining, and the values entered in the registration step. These can all be specified on the command line when starting the server:

    dynamic-server> java -jar $RESIN_HOME/lib/resin.jar -conf /etc/resin/resin.xml \
                         -dynamic-server app-tier:123.45.67.89:6800 start
    

    Specifying the configuration file allows the new server to configure itself using the <server-default> options, to find the triad servers of the cluster it is joining, and to authenticate using the administration logins. This command starts the server, which immediately contacts the triad to join the cluster. Once it has successfully joined, the "Cluster" tab of the administration application should look like this:

    See Also

    • See the index for a list of all the tags.
    • See Web Application configuration for web.xml (Servlet) configuration.
    • See Server tags for ports, threads, and JVM configuration.
    • See Resource configuration for resources: classloader, databases, connectors, and resources.
    • See Log configuration for access log configuration, java.util.logging, and stdout/stderr logging.

    <access-log>

    <access-log> configures a HTTP access log for all virtual hosts in the cluster. See access-log in the <host> tag for more information.

    <cache>

    child of cluster

    <cache> configures the proxy cache (requires Resin Professional). The proxy cache improves performance by caching the output of servlets, jsp and php pages. For database-heavy pages, this caching can improve performance and reduce database load by several orders of magnitude.

    The proxy cache uses a combination of a memory cache and a disk-based cache to save large amounts of data with little overhead.

    Management of the proxy cache uses the ProxyCacheMXBean.

    <cache> Attributes
    ATTRIBUTEDESCRIPTIONDEFAULT
    pathPath to the persistent cache files.cache/
    disk-sizeMaximum size of the cache saved on disk.1024M
    enableEnables the proxy cache.true
    enable-rangeEnables support for the HTTP Range header.true
    entriesMaximum number of pages stored in the cache.8192
    max-entry-sizeLargest page size allowed in the cache.1M
    memory-sizeMaximum heap memory used to cache blocks.8M
    rewrite-vary-as-privateRewrite Vary headers as Cache-Control: private to avoid browser and proxy-cache bugs (particularly IE).false
    <cache> schema
    element cache {
      disk-size?
      & enable?
      & enable-range?
      & entries?
      & path?
      & max-entry-size?
      & memory-size?
      & rewrite-vary-as-private?
    }
    
    Example: enabling proxy cache
    <resin xmlns="http://caucho.com/ns/resin">
        <cluster id="web-tier">
            <cache entries="16384" disk-size="2G" memory-size="256M"/>
    
            <server id="a" address="192.168.0.10"/>
    
            <host host-name="www.foo.com">
        </cluster>
    </resin>
    

    <cluster>

    child of resin

    <cluster> configures a set of identically-configured servers. The cluster typically configures a set of <server>s, each with some ports, and a set of virtual <host>s.

    Only one <cluster> is active in any on server. At runtime, the <cluster> is selected by the <server> with id matching the -server-id on the command line.

    <cluster> Attributes
    ATTRIBUTEDESCRIPTIONDEFAULT
    idThe cluster identifier.required
    access-logAn access-log shared for all virtual hosts.
    cacheProxy cache for HTTP-cacheable results.
    connection-error-pageIIS error page to use when isapi_srun to Resin connection fails
    ear-defaultdefault values for deployed ear files
    error-pageCustom error-page when virtual-hosts fail to match
    hostConfigures a virtual host
    host-defaultConfigures defaults to apply to all virtual hosts
    host-deployAutomatic host deployment based on a deployment directory
    ignore-client-disconnectIgnores socket exceptions thrown because browser clients have prematurely disconnectedfalse
    invocation-cache-sizeSize of the system-wide URL to servlet invocation mapping cache16384
    invocation-cache-max-url-lengthMaximum URL length saved in the invocation cache256
    machineConfiguration for grouping <server> onto physical machines
    persistent-storeConfigures the distributed/persistent store
    pingPeriodic checking of server URLs to verify server activity
    redeploy-mode"automatic" or "manual"automatic
    resin:chooseConditional configuration based on EL expressions
    resin:importImports a custom cluster.xml files for a configuration management
    resin:ifConditional configuration based on EL expressions
    rewrite-dispatchrewrites and dispatches URLs using regular expressions, similar to mod_rewrite
    root-directoryThe root filesystem directory for the cluster${resin.root}
    serverConfigures JVM instances (servers). Each cluster needs at least one server
    server-defaultConfigures defaults for all server instances
    server-headerConfigures the HTTP "Server: Resin/xxx" headerResin/Version
    session-cookieConfigures the servlet cookie nameJSESSIONID
    session-sticky-disableDisables sticky-sessions on the load balancerfalse
    url-character-encodingConfigures the character encoding for URLsutf-8
    url-length-maxConfigures the maximum length of an allowed URL8192
    web-app-defaultConfigures defaults to apply to all web-apps in the cluster
    <cluster> schema
    element cluster {
      attribute id { string }
      & environment resources
      & access-log?
      & cache?
      & connection-error-page?
      & ear-default*
      & error-page*
      & host*
      & host-default*
      & host-deploy*
      & ignore-client-disconnect?
      & invocation-cache-size?
      & invocation-cache-max-url-length?
      & machine*
      & persistent-store?
      & ping*
      & redeploy-mode?
      & resin:choose*
      & resin:import*
      & resin:if*
      & rewrite-dispatch?
      & root-directory?
      & server*
      & server-default*
      & server-header?
      & session-cookie?
      & session-sticky-disable?
      & url-character-encoding?
      & url-length-max?
      & web-app-default*
    }
    
    Example: cluster-default
    <resin xmlns="http://caucho.com/ns/resin">
        <cluster id="web-tier">
            <server-default>
                <http port="8080"/>
            </server-default>
    
            <server id="a" address="192.168.0.10"/>
            <server id="b" address="192.168.0.11"/>
    
            <host host-name="www.foo.com">
              ...
            </host>
        </cluster>
    </resin>
    

    rewrite-vary-as-private

    Because not all browsers understand the Vary header, Resin can rewrite Vary to a Cache-Control: private. This rewriting will cache the page with the Vary in Resin's proxy cache, and also cache the page in the browser. Any other proxy caches, however, will not be able to cache the page.

    The underlying issue is a limitation of browsers such as IE. When IE sees a Vary header it doesn't understand, it marks the page as uncacheable. Since IE only understands "Vary: User-Agent", this would mean IE would refuse to cache gzipped pages or "Vary: Cookie" pages.

    With the <rewrite-vary-as-private> tag, IE will cache the page since it's rewritten as "Cache-Control: private" with no Vary at all. Resin will continue to cache the page as normal.

    <cluster-default>

    child of resin

    <cluster-default> defines default cluster configuration for all clusters in the <resin> server.

    Example: cluster-default
    <resin xmlns="http://caucho.com/ns/resin">
        <cluster-default>
            <cache entries="16384" memory-size="64M"/>
        </cluster-default>
    
        <cluster id="web-tier">
            ...
        </cluster>
    
        <cluster id="app-tier">
            ...
        </cluster>
    </resin>
    

    <connection-error-page>

    child of cluster

    <connection-error-page> specifies an error page to be used by IIS when it can't contact an app-tier Resin. This directive only applies to IIS.

    connection-error-page
    element connection-error-page {
      string
    }
    

    <development-mode-error-page>

    child of cluster

    <development-mode-error-page> enables browser error reporting with extra information. Because it can expose internal data, it is not generally recommended in production systems. (The information is generally coped to the log.

    <ear-default>

    child of cluster

    <ear-default> configures defaults for .ear resource, i.e. enterprise applications.

    <error-page>

    child of cluster

    <error-page> defines a web page to be displayed when an error occurs outside of a virtual host or web-app. Note, this is not a default error-page, i.e. if an error occurs inside a <host> or <web-app>, the error-page for that host or web-app will be used instead.

    See webapp: error-page.

    <error-page> schema
    element error-page {
      (error-code | exception-type)?
      & location?
    }
    

    <host>

    child of cluster

    <host> configures a virtual host. Virtual hosts must be configured explicitly.

    <host> attributes
    ATTRIBUTEDESCRIPTIONDEFAULT
    idprimary host namenone
    regexpRegular expression based host matchingnone
    host-nameCanonical host namenone
    host-aliasAliases matching the same hostnone
    secure-host-nameHost to use for a redirect to SSLnone
    root-directoryRoot directory for host filesparent directory
    startup-mode'automatic', 'lazy', or 'manual', see Startup and Redeploy Modeautomatic
    Example: explicit host
    <host host-name="www.foo.com">
      <host-alias>foo.com</host-alias>
      <host-alias>web.foo.com</host-alias>
    
      <root-directory>/opt/www/www.foo.com</root-directory>
    
      <web-app id="/" document-directory="webapps/ROOT">
        
      </web-app>
      ...
    </host>
    
    Example: regexp host
    <host regexp="([^.]+)\.foo\.com">
      <host-name>${host.regexp[1]}.foo.com</host-name>
    
      <root-directory>/var/www/hosts/www.${host.regexp[1]}.com</root-directory>
    
      ...
    </host>
    

    It is recommended that any <host> using a regexp include a <host-name> to set the canonical name for the host.

    <host-default>

    child of cluster

    Defaults for a virtual host.

    The host-default can contain any of the host configuration tags. It will be used as defaults for any virtual host.

    <host-deploy>

    child of cluster

    Configures a deploy directory for virtual host.

    The host-deploy will add an EL variable ${name}, referring to the name of the host jar file.

    ATTRIBUTEDESCRIPTIONDEFAULT
    pathpath to the deploy directoryrequired
    expand-pathpath to the expansion directorypath
    host-defaultdefaults for the expanded host
    host-namethe host name to match${name}

    <ignore-client-disconnect>

    child of cluster
    default true

    ignore-client-disconnect configures whether Resin should ignore disconnection exceptions from the client, or if it should send those exceptions to the application.

    <ignore-client-disconnect> schema
    element ignore-client-disconnect {
      r_boolean-Type
    }
    

    <invocation-cache-size>

    child of cluster
    default 8192

    Configures the number of entries in the invocation cache. The invocation cache is used to store pre-calculated servlet and filter chains from the URLs. It's also used as the basis for proxy caching.

    <invocation-cache-size> schema
    element invocation-cache-size {
      r_int-Type
    }
    

    <invocation-cache-max-url-length>

    child of cluster
    default 256

    Configures the longest entry cacheable in the invocation cache. It is used to avoid certain types of denial-of-service attacks.

    <invocation-cache-max-url-length> schema
    element invocation-cache-max-url-length {
      r_int-Type
    }
    

    <max-uri-length>

    child of cluster
    default 1024

    Sets limit on longest URIs that can be served by Resin.

    <max-uri-length> schema
    element max-uri-length {
      r_int-Type
    }
    

    <persistent-store>

    child of cluster

    Defines the cluster-aware persistent store used for sharing distributed sessions. The allowed types are "jdbc", "cluster" and "file". The "file" type is only recommended in single-server configurations.

    The <persistent-store> configuration is in the <server> level because it needs to share update information across the active cluster and the <cluster> definition is at the <server> level. Sessions activate the persistent store with the <use-persistent-store> tag of the <session-config>.

    See Persistent sessions for more details.

    <persistent-store> Attributes
    ATTRIBUTEDESCRIPTIONDEFAULT
    initinitialization parameters for the persistent-store
    typecluster, jdbc, or filerequired
    <persistent-store> schema
    element persistent-store {
      type
      & init?
    }
    

    cluster store

    The cluster store shares copies of the sessions on multiple servers. The original server is used as the primary, and is always more efficient than the backup servers. In general, the cluster store is preferred because it is more scalable, and with the "triplicate" attribute, the most reliable..

    cluster tags
    ATTRIBUTEDESCRIPTIONDEFAULT
    always-loadAlways load the valuefalse
    always-saveAlways save the valuefalse
    max-idle-timeHow long idle objects are stored (session-timeout will invalidate items earlier)24h
    pathDirectory to store the objectsrequired
    save-backupSaves backup copies of all distributed objects (3.2.0).true
    triplicateSaves three copies of all distributed objects (3.2.0).false
    wait-for-acknowledgeRequires the sending server to wait for all acks.false
    cluster schema
    element persistent-store {
      type { "cluster "}
    
      element init {
        always-load?
        & always-save?
        & max-idle-time?
        & triplicate?
        & wait-for-acknowledge?
      }
    }
    
    Example: cluster store
    <resin xmlns="http://caucho.com/ns/resin">
    <cluster>
      <server id="a" address="192.168.0.1" port="6800"/>
      <server id="b" address="192.168.0.2" port="6800"/>
    
      <persistent-store type="cluster">
        <init>
          <triplicate>true</triplicate>
        </init>
      </persistent-store>
    
      <web-app-default>
        <session-config use-persistent-store="true"/>
      </web-app-default>
    </cluster>
    </resin>
    

    jdbc store

    The JDBC store saves sessions in a JDBC database. Often, this will be a dedicated database to avoid overloading the main database.

    jdbc store Attributes
    ATTRIBUTEDESCRIPTIONDEFAULT
    always-loadAlways load the valuefalse
    always-saveAlways save the valuefalse
    blob-typeSchema type to store valuesfrom JDBC meta info
    data-sourceThe JDBC data sourcerequired
    table-nameDatabase tablepersistent_session
    max-idle-timeHow long idle objects are stored24h
    Example: jdbc-store
    <resin xmlns="http://caucho.com/ns/resin">
    <cluster>
      <server id="a" address="192.168.0.1" port="6800"/>
      <server id="b" address="192.168.0.2" port="6800"/>
    
      <persistent-store type="jdbc">
        <init>
          <data-source>jdbc/session</data-source>
    
          <max-idle-time>24h</max-idle-time>
        </init>
      </persistent-store>
    
      <web-app-default>
        <session-config use-persistent-store="true"/>
      </web-app-default>
    </cluster>
    </resin>
    

    file store

    The file store is a persistent store for development and testing or for single servers. Since it is not aware of the clusters, it cannot implement true distributed objects.

    file tags
    ATTRIBUTEDESCRIPTIONDEFAULT
    always-loadAlways load the valuefalse
    always-saveAlways save the valuefalse
    max-idle-timeHow long idle objects are stored24h
    pathDirectory to store the sessionsrequired

    <ping>

    child of cluster

    Starts a thread that periodically makes a request to the server, and restarts Resin if it fails. This facility is used to increase server reliability - if there is a problem with the server (perhaps from a deadlock or an exhaustion of resources), the server is restarted.

    A failure occurs if a request to the url returns an HTTP status that is not 200.

    Since the local process is restarted, it does not make sense to specify a url that does not get serviced by the instance of Resin that has the ping configuration. Most configurations use url's that specify 'localhost' as the host.

    This pinging only catches some problems because it's running in the same process as Resin itself. If the entire JDK freezes, this thread will freeze as well. Assuming the JDK doesn't freeze, the PingThread will catch errors like deadlocks.

    <ping> Attributes
    ATTRIBUTEDESCRIPTIONDEFAULT
    urlA url to ping.required
    sleep-timeTime to wait between pings. The first ping is always 15m after the server starts, this is for subsequent pings.15m
    try-countIf a ping fails, number of times to retry before giving up and restartingrequired
    retry-timetime between retries1s
    socket-timeouttime to wait for server to start responding to the tcp connection before giving up10s
    Example: resin.xml - simple usage of server ping
    <resin xmlns="http://caucho.com/ns/resin"
           xmlns:resin="http://caucho.com/ns/resin/core">
        <cluster id="app-tier">
            <ping url="http://localhost/"/>
            ...
        </cluster>
    </resin>
    
    Example: resin.xml - configured usage of server ping
    <resin xmlns="http://caucho.com/ns/resin"
           xmlns:resin="http://caucho.com/ns/resin/core">
        ...
        <cluster id="app-tier">
            <ping>
                <url>http://localhost:8080/index.jsp</url>
                <url>http://localhost:8080/webapp/index.jsp</url>
                <url>http://virtualhost/index.jsp</url>
                <url>http://localhost:443/index.jsp</url>
    
                <sleep-time>5m</sleep-time>
                <try-count>5</try-count>
        
                <!-- a very busy server -->
                <socket-timeout>30s</socket-timeout>
            </ping>
          ...
        </cluster>
    </resin>
    

    The class that corresponds to <ping> is PingThread.

    Mail notification when ping fails

    A refinement of the ping facility sends an email when the server is restarted.

    resin.xml - mail notification when ping fails
    <resin xmlns="http://caucho.com/ns/resin"
           xmlns:resin="http://caucho.com/ns/resin/core">
      ...
      <cluster id="web-tier">
        <ping resin:type="com.caucho.server.admin.PingMailer">
          <url>http://localhost:8080/index.jsp</url>
          <url>http://localhost:8080/webapp/index.jsp</url>
    
          <mail-to>fred@hogwarts.com</mail-to>
          <mail-from>resin@hogwarts.com</mail-from>
          <mail-subject>Resin ping has failed for server ${'${'}server.name}</mail-subject>
        </ping>
        ...
      </server>
    </resin>
    

    The default behaviour for sending mail is to contact a SMTP server at host 127.0.0.1 (the localhost) on port 25. System properties are used to configure a different SMTP server.

    resin.xml - smtp server configuration
      <system-property mail.smtp.host="127.0.0.1"/>
      <system-property mail.smtp.port="25"/>
    

    Resource Tags

    child of cluster

    All Environment tags are available to the <cluster>. For example, resources like <database>.

    Example: cluster environment
    <resin xmlns="http://caucho.com/ns/resin">
        <cluster id="app-tier">
            <database jndi-name="jdbc/test">
                <driver type="org.postgresql.Driver">
                    <url>jdbc:postgresql://localhost/test</url>
                    <user>caucho</user>
                </driver>
            </database>
    
            <server id="a" ...>
              ...
    
            <host host-name="www.foo.com">
              ...
        </cluster>
    </resin>
    

    <rewrite-dispatch>

    child of cluster

    <rewrite-dispatch> defines a set of rewriting rules for dispatching and forwarding URLs. Applications can use these rules to redirect old URLs to their new replacements.

    See rewrite-dispatch for more details.

    rewrite-dispatch
    <resin xmlns="http://caucho.com/ns/resin">
        <cluster id="web-tier">
    
            <rewrite-dispatch>
                <redirect regexp="^http://www.foo.com"
                          target="http://bar.com/foo"/>
            </rewrite-dispatch>
      
        </cluster>
    </resin>
    

    <root-directory>

    child of cluster
    default The root-directory of the <resin> tag.

    <root-directory> configures the root directory for files within the cluster. All paths in the <cluster> will be relative to the root directory.

    <root-directory> schema
    element root-directory {
      r_path-Type
    }
    
    Example: cluster root-directory
    <resin xmlns="http://caucho.com/ns/resin">
        <cluster id="app-tier">
            <root-directory>/var/www/app-tier</root-directory>
    
            <server id="a" ...>
    
            <host host-name="www.foo.com">
        </cluster>
    </resin>
    

    <server>

    child of cluster

    The <server> tag configures a JVM instance in the cluster. Each <server> is uniquely identified by its id attribute. The id will match the -server-id command line argument.

    See the full server configuration for more details of the <server> tag and its children.

    The current server is managed with a ServerMXBean. The ObjectName is resin:type=Server.

    Peer servers are managed with ServerConnectorMXBean. The ObjectName is resin:type=ServerConnector,name=server-id.

    <server> Attributes
    ATTRIBUTEDESCRIPTIONDEFAULT
    addressIP address of the cluster port127.0.0.1
    bind-ports-after-startIf true, listen to the ports only after all initialization has completed, allowing load-balance failover.true
    cluster-portConfigures the cluster port in detail, allowing for customization of timeouts, etc.
    group-nameUsed by the watchdog to switch setgid before starting the Resin JVM instance for security.
    httpAdds a HTTP port (see port tags)
    idUnique server identifierrequired
    java-exeThe specific Java executable for the watchdog to launch the JVMjava
    jvm-argAdds a JVM argument when the watchdog launches Resin.
    jvm-classpathAdds a JVM classpath when the watchdog launches Resin.
    keepalive-connection-time-maxThe total time a connection can be used for requests and keepalives10min
    keepalive-maxThe maximum keepalives enabled at one time.128
    keepalive-select-enableEnables epoll/select for keepalive requests to reduce threads (unix only)true
    keepalive-timeoutTimeout for a keepalive to wait for a new request15s
    load-balance-connect-timeoutHow long the load-balancer should wait for a connection to this server5s
    load-balance-idle-timeHow long the load balancer can keep an idle socket open to this server (see keepalive-timeout)keepalive-time - 2s
    load-balance-recover-timeHow long the load balancer should treat this server as dead after a failure before retrying15s
    load-balance-socket-timeouttimeout for the load balancer reading/writing to this server65s
    load-balance-warmup-timeWarmup time for the load-balancer to throttle requests before sending the full load60s
    load-balance-weightrelative weight used by the load balancer to send traffic to this server100
    memory-free-minminimum memory allowed for the JVM before Resin forces a restart1M
    pingConfigures a periodic ping of the server to force restarts when non-responsive
    portConfigures the cluster port (shortcut for <cluster-port>)6800
    protocolAdds a custom socket protocol, e.g. for IIOP or SNMP.
    shutdown-wait-maxThe maximum of time to wait for a graceful Resin shutdown before forcing a close60s
    socket-timeoutThe read/write timeout for the socket65s
    thread-maxThe maximum number of threads managed by Resin (JVM threads will be larger because of non-Resin threads)4096
    thread-executor-thread-maxLimits the threads allocated to application ScheduledExecutors from Resin
    thread-idle-maxMaximum number of idle threads in the thread pool10
    thread-idle-minMinimum number of idle threads in the thread pool5
    user-nameThe setuid user-name for the watchdog when launching Resin for Unix security.
    watchdog-jvm-argAdditional JVM arguments when launching the watchdog manager
    watchdog-portThe port for the watchdog-manager to listen for start/stop/status requests6700
    <server> schema
    element server {
      attribute id { string }
      & address?
      & bind-ports-after-start?
      & cluster-port*
      & group-name?
      & http*
      & java-exe?
      & jvm-arg?
      & jvm-classpath?
      & keepalive-connection-time-max?
      & keepalive-max?
      & keepalive-select-enable?
      & keepalive-timeout?
      & load-balance-connect-timeout?
      & load-balance-idle-time?
      & load-balance-recover-time?
      & load-balance-socket-timeout?
      & load-balance-warmup-time?
      & load-balance-weight?
      & memory-free-min?
      & ping?
      & port?
      & protocol?
      & shutdown-wait-max?
      & socket-timeout?
      & thread-max?
      & thread-executor-task-max?
      & thread-idle-max?
      & thread-idle-min?
      & user-name?
      & watchdog-jvm-arg*
      & watchdog-port?
    }
    
    Example: server
    <resin xmlns="http://caucho.com/ns/resin">
        <cluster id="web-tier">
            <server id="a" address="192.168.0.10" port="6800">
              <http port="8080"/>
            </server>
    
            <server id="b" address="192.168.0.11" port="6800">
              <http port="8080"/>
            </server>
    
            <server id="c" address="192.168.0.12" port="6800">
              <http port="8080"/>
            </server>
    
            <host id="">
              ...
        </cluster>
    </resin>
    

    <server-default>

    child of cluster

    Defines default values for all <server> instances. See <server> configuration for more details.

    Example: server
    <resin xmlns="http://caucho.com/ns/resin">
        <cluster id="web-tier">
            <server-default>
                <server-port>6800</server-port>
    
                <http port="8080"/>
            </server-default>
    
            <server id="a" address="192.168.0.10"/>
            <server id="b" address="192.168.0.11"/>
            <server id="c" address="192.168.0.12"/>
    
            <host id="">
              ...
        </cluster>
    </resin>
    

    <server-header>

    child of cluster
    default Resin/3.1.x

    Configures the HTTP Server: header which Resin sends back to any HTTP client.

    <server-header> schema
    element server-header {
      string
    }
    
    server-header
    <resin xmlns="http://caucho.com/ns/resin">
        <cluster id="web-tier">
            <server-header>MyServer/1.0</server-header>
        </cluster>
    </resin>
    

    <session-cookie>

    child of cluster
    default JSESSIONID

    Configures the cookie used for servlet sessions.

    <session-cookie> schema
    element session-cookie {
      string
    }
    

    <session-sticky-disable>

    child of cluster
    default false

    Disables sticky sessions from the load balancer.

    <session-sticky-disable> schema
    element session-sticky-disable {
      r_boolean-Type
    }
    

    <session-url-prefix>

    child of cluster
    default ;jsessionid=

    Configures the URL prefix used for session rewriting.

    Note Session rewriting is discouraged as a potential security issue.
    <session-cookie> schema
    element session-cookie {
      string
    }
    

    <ssl-session-cookie>

    child of cluster
    default value of session-cookie

    Defines an alternative session cookie to be used for a SSL connection. Having two separate cookies increases security.

    <session-cookie> schema
    element ssl-session-cookie {
      string
    }
    
    Example: ssl-session-cookie
    <resin xmlns="http://caucho.com/ns/resin">
        <cluster id="web-tier">
            <ssl-session-cookie>SSLJSESSIONID</ssl-session-cookie>
            ...
        </cluster>
    </resin>
    

    <url-character-encoding>

    child of cluster
    default UTF-8

    Defines the character encoding for decoding URLs.

    The HTTP specification does not define the character-encoding for URLs, so the server must make assumptions about the encoding.

    <url-character-encoding> schema
    element url-character-encoding {
      string
    }
    

    <web-app-default>

    child of cluster

    <web-app-default> defines default values for any web-app in the cluster.

    Example: web-app-default
    <resin xmlns="http://caucho.com/ns/resin">
        <cluster id="app-tier">
    
            <web-app-default>
                <servlet servlet-name="resin-php"
                         servlet-class="com.caucho.quercus.servlet.QuercusServlet"/>
    
                <servlet-mapping url-pattern="*.php"
                                 servlet-name="resin-php"/>
            </web-app-default>
    
            <host id="">
              ...
        </cluster>
    </resin>
    

    Copyright © 1998-2010 Caucho Technology, Inc. All rights reserved.
    Resin ® is a registered trademark, and Quercustm, Ambertm, and Hessiantm are trademarks of Caucho Technology.