Terracotta

Terracotta

As of CAS 3.3, a sample Terracotta configuration file is included in the etc/terracotta directory of the CAS distribution.

https://github.com/Jasig/cas/blob/master/etc/terracotta/sample-terracotta-config.xml

This above linked sample Terracotta config file appears to be missing some important config options. Please take a look at this JIRA bug report by Raymond Walker for more details and the recommended config file. Also find the recommended config file lower in this page.

https://issues.jasig.org/browse/CAS-750

See this webcast (12/8/10) by Raymond Walker from Northern Arizona University who successfully clusters CAS with Terracotta.

           http://www.slideshare.net/JasigCAS/naucasterracotta 

Here are the slides of the presentation in pdf format, but the webcast is still recommended for potential implementers as there is some good conversation around the technology.

                    Raymond Walker CAS Terracotta Clustering Presentation PDF

      

    Recommended tc-config.xml file for Terracotta to cluster CAS.

<?xml version="1.0" encoding="UTF-8"?>
<tc:tc-config xsi:schemaLocation="http://www.terracotta.org/schema/terracotta-4.xsd" xmlns:tc="http://www.terracotta.org/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <!-- NAU sample Terracotta Configuration for CAS -->

    <tc-properties>
      <!-- Network Active/Passive for failover from Active to Passive  -->
      <!-- The Nodes keeps tabs on each other to failover from Active to Passive -->
      <!-- http://www.terracotta.org/documentation/ga/product-documentation-16.html#50462727_19590 -->
      <!-- L2 - L2 -->
      <!-- Max Time = (ping.idletime) + socketConnectCount * [(ping.interval * ping.probes) + (socketConnectTimeout * ping.interval)] -->
      <!-- 5000 + 5[ (3 * 1000) + (2 * 1000) ] = 5000 + 25000 = 30000 ms -->
      <!-- The health checker declares the node dead in 25 seconds -->
      <property name="l2.healthcheck.l2.ping.enabled"         value="true" />
      <property name="l2.healthcheck.l2.ping.idletime"        value="5000"  />
      <property name="l2.healthcheck.l2.ping.interval"        value="1000"  />
      <property name="l2.healthcheck.l2.ping.probes"          value="3"     />
      <property name="l2.healthcheck.l2.socketConnect"        value="true"  />
      <property name="l2.healthcheck.l2.socketConnectTimeout" value="2"     />
      <property name="l2.healthcheck.l2.socketConnectCount"   value="5"     />

      <!-- Terracotta-Server and Client-JVMs correspondences -->
      <!-- L2 - L1  L2 Terracotta Server L1 Client -->
      <!-- 5000 + 5[ (3 * 1000) + (2 * 1000) ] =5000 + 25000 = 30000 ms -->
      <!-- Terracotta server keeping tabs on client i.e. apache/tomcat shibboleth -->
      <!-- The health checker declares the client dead in 25 seconds -->
      <!-- Max Time = (ping.idletime) + socketConnectCount * [(ping.interval * ping.probes) + (socketConnectTimeout * ping.interval)] -->
      <property name="l2.healthcheck.l1.ping.enabled"         value="true"  />
      <property name="l2.healthcheck.l1.ping.idletime"        value="5000"  />
      <property name="l2.healthcheck.l1.ping.interval"        value="1000"  />
      <property name="l2.healthcheck.l1.ping.probes"          value="3"     />
      <property name="l2.healthcheck.l1.socketConnect"        value="true " />
      <property name="l2.healthcheck.l1.socketConnectTimeout" value="2"     />
      <property name="l2.healthcheck.l1.socketConnectCount"   value="5"     />

      <!-- Client-JVMs and Terracotta Server correspondences -->
      <!-- L1 - L2  L2 Terracotta Server L1 Client -->
      <!-- 5000 + 5[ (3 * 1000) + (2 * 1000) ] =5000 + 25000 = 30000 ms -->
      <!-- Client server keeping tabs on Terracotta Servers -->
      <!-- The health checker declares the client dead in 25 seconds -->
      <!-- Max Time = (ping.idletime) + socketConnectCount * [(ping.interval * ping.probes) + (socketConnectTimeout * ping.interval)] -->
      <property name="l1.healthcheck.l2.ping.enabled"         value="true"  />
      <property name="l1.healthcheck.l2.ping.idletime"        value="5000"  />
      <property name="l1.healthcheck.l2.ping.interval"        value="1000"  />
      <property name="l1.healthcheck.l2.ping.probes"          value="3"     />
      <property name="l1.healthcheck.l2.socketConnect"        value="true"  />
      <property name="l1.healthcheck.l2.socketConnectTimeout" value="2"     />
      <property name="l1.healthcheck.l2.socketConnectCount"   value="5"     />
        
      <property name="l2.nha.tcgroupcomm.reconnect.enabled" value="true" />
      <property name="l2.nha.tcgroupcomm.reconnect.timeout" value="15000" />
      <property name="l2.l1reconnect.enabled" value="true" />
      <property name="l2.l1reconnect.timeout.millis" value="15000" />
    </tc-properties>

    <servers>
        <!-- Replicate server entry for all nodes running cas/terracotta -->
        <server name="test1" host="XXX" bind="IP">
            <dso-port>9510</dso-port>
            <jmx-port>9520</jmx-port>
            <data>cluster/data</data>
            <logs>cluster/logs</logs>
            <dso>
              <persistence>
                <mode>permanent-store</mode>
              </persistence>
            </dso>
        </server>
        <!-- High Availability for multiple servers (used in DEV & TEST ENVs) -->  
        <ha>
            <mode>networked-active-passive</mode>
            <networked-active-passive>
                <election-time></election-time>
            </networked-active-passive>
        </ha>
    </servers>

    <clients>
        <logs>/cluster/clients</logs>

        <!-- Tomcat module is dependent on tomcat version
             Spring webflow and security also necessary -->
        <modules>
            <module name="tim-vector" version="2.6.3" group-id="org.terracotta.modules"/>
            <module name="tim-tomcat-5.5"/>
            <module name="tim-spring-webflow-2.0"/>
            <module name="tim-spring-security-2.0"/>
        </modules>
    </clients>

    <application>
        <dso>
            <web-applications>
                <web-application>cas</web-application>
            </web-applications>
            <roots>
                <!-- Defined Shared Roots -->
                <root>
                    <!--The In-Memory Ticket Registry-->
                    <field-name>org.jasig.cas.ticket.registry.DefaultTicketRegistry.cache</field-name>
                </root>
                <root>
                    <!--The registered Services  -->
                    <field-name>org.jasig.cas.services.DefaultServicesManagerImpl.services</field-name>
                </root>
            </roots>

            <locks>
                <!--Locks for the shared Tickets-->
                <named-lock>
                    <method-expression>* org.jasig.cas.ticket.registry.DefaultTicketRegistry.*(..)</method-expression>
                    <lock-level>write</lock-level>
                    <lock-name>ticketRegistryLock</lock-name>
                </named-lock>
                <named-lock>
                    <method-expression>* org.jasig.cas.ticket.AbstractTicket.updateState(..)</method-expression>
                    <lock-level>write</lock-level>
                    <lock-name>ticketWriteLock</lock-name>
                </named-lock>
                <named-lock>
                    <method-expression>* org.jasig.cas.ticket.AbstractTicket.*(..)</method-expression>
                    <lock-level>read</lock-level>
                    <lock-name>ticketReadLock</lock-name>
                </named-lock>
                <named-lock>
                    <method-expression>* org.jasig.cas.CentralAuthenticationServiceImpl.*(..)</method-expression>
                    <lock-level>write</lock-level>
                    <lock-name>casWriteLock</lock-name>
                </named-lock>
                <named-lock>
                    <method-expression>* org.jasig.cas.ticket.TicketGrantingTicketImpl.grantServiceTicket(..)
                    </method-expression>
                    <lock-level>write</lock-level>
                    <lock-name>tgtWriteLock2</lock-name>
                </named-lock>
                <named-lock>
                    <method-expression>* org.jasig.cas.ticket.TicketGrantingTicketImpl.expire(..)</method-expression>
                    <lock-level>write</lock-level>
                    <lock-name>tgtWriteLock2</lock-name>
                </named-lock>
               <named-lock>
                   <method-expression>* org.jasig.cas.ticket.ServiceTicketImpl.grantTicketGrantingTicket(..)
                   </method-expression>
                   <lock-level>write</lock-level>
                   <lock-name>tgtWriteLock2</lock-name>
               </named-lock>

                <!-- Service Registry Distribution Locks -->
                <named-lock>
                    <method-expression>* org.jasig.cas.services.DefaultServicesManagerImpl.findServiceBy(..)
                    </method-expression>
                    <lock-level>read</lock-level>
                    <lock-name>serviceFindReadLock</lock-name>
                </named-lock>
                <named-lock>
                    <method-expression>* org.jasig.cas.services.DefaultServicesManagerImpl.getAllServices(..)
                    </method-expression>
                    <lock-level>read</lock-level>
                    <lock-name>serviceReadLock</lock-name>
                </named-lock>
                <named-lock>
                    <method-expression>* org.jasig.cas.services.DefaultServicesManagerImpl.*(..)</method-expression>
                    <lock-level>write</lock-level>
                    <lock-name>serviceWriteLock</lock-name>
                </named-lock>
                <named-lock>
                    <method-expression>* org.jasig.cas.web.flow.GenerateServiceTicketAction.doExecute(..)
                    </method-expression>
                    <lock-level>write</lock-level>
                    <lock-name>stActionWriteLock</lock-name>
                </named-lock>
            </locks>

            <instrumented-classes>
                <include>
                    <class-expression>org.jasig.cas.ticket.*</class-expression>
                </include>
                <include>
                    <class-expression>org.jasig.cas.ticket.support.*</class-expression>
                </include>
                <include>
                    <class-expression>org.jasig.cas.authentication.principal.*</class-expression>
                </include>
                <include>
                    <class-expression>org.jasig.cas.util.*</class-expression>
                </include>
                <include>
                    <class-expression>org.jasig.cas.authentication.*</class-expression>
                </include>
                <include>
                    <class-expression>org.jasig.cas.services.RegisteredServiceImpl</class-expression>
                </include>
            </instrumented-classes>

        </dso>
    </application>

</tc:tc-config>