Appendix A: Sample Configurations for Deploying Tailspin Surveys to Multiple Data Centers

Retired Content

This content and the technology described is outdated and is no longer being maintained. For more information, see Transient Fault Handling.

patterns & practices Developer Center

On this page:
Option 1 | Service Model | Rules | Option 2 | Service Model | Rules

This appendix contains sample service information and rules definitions for the two alternative architectures for Tailspin’s autoscaling infrastructure described in Chapter 5, "Making Tailspin Surveys More Elastic."

Option 1

Option 1 deploys the management application and the Autoscaling Application Block to the North Central US data center only.

Service Model

<?xml version="1.0" encoding="utf-8"?>
<serviceModel ...>
  <subscriptions>
    <subscription name="Tailspin Surveys Production"
                  subscriptionId="..."
                  certificateThumbprint="..."
                  certificateStoreName="My"
                  certificateStoreLocation="LocalMachine">
      <services>
       <!-- 
         Multiple service definitions, one for each data center that
         Tailspin Surveys is deployed to.
         Note: All share the same wadStorageAccountName values because the 
         diagnostic is collected centrally in this model.
       -->
       <service dnsPrefix="ustailspinsurveys" slot="Production" scalingMode="Scale">
          <roles>
            <role alias="usTailSpinWorkersSurveys"  
              roleName="TailSpin.Workers.Surveys"
              wadStorageAccountName="usTailspin" />
            <role alias="usTailSpinWebSurveyPublic" 
              roleName="TailSpin.Web.Survey.Public" 
              wadStorageAccountName="usTailspin" />
            <role alias="usTailSpinWeb"
              roleName="TailSpin.Web"
              wadStorageAccountName="usTailspin" />
          </roles>
        </service>
       <service dnsPrefix="eutailspinsurveys" slot="Production" scalingMode="Scale">
          <roles>
            <role alias="euTailSpinWorkersSurveys" 
              roleName="TailSpin.Workers.Surveys"
              wadStorageAccountName="euTailspin" />
            <role alias="euTailSpinWebSurveyPublic" 
              roleName="TailSpin.Web.Survey.Public" 
              wadStorageAccountName="euTailspin" />
            <role alias="euTailSpinWeb"
              roleName="TailSpin.Web"
              wadStorageAccountName="euTailspin" />
          </roles>
        </service>
       <service dnsPrefix="astailspinsurveys" slot="Production" scalingMode="Scale">
          <roles>
            <role alias="asTailSpinWorkersSurveys" 
              roleName="TailSpin.Workers.Surveys"
              wadStorageAccountName="asTailspin" />
            <role alias="asTailSpinWebSurveyPublic" 
              roleName="TailSpin.Web.Survey.Public" 
              wadStorageAccountName="asTailspin" />
            <role alias="asTailSpinWeb"
              roleName="TailSpin.Web"
              wadStorageAccountName="asTailspin" />
          </roles>
        </service>
      </services>
      <!--
        Multiple storage accounts, one for each data center that Tailspin Surveys
        is deployed to. Each storage account has its own connection string.
        These queues are used by the Tailspin Surveys application and are
        included here because we want to use rules that monitor the queue lengths.
      -->
      <storageAccounts>
        <storageAccount alias="usTailspin" connectionString="...">
          <queues>
            <queue alias="usTailspinSurveyAnswerStoredQueue" 
              queueName="surveyanswerstored" />
            <queue alias="usTailspinSurveyTransferQueue"
              queueName="surveytransfer" />
          </queues>
        </storageAccount>
        <storageAccount alias="euTailspin" connectionString="...">
          <queues>
            <queue alias="euTailspinSurveyAnswerStoredQueue" 
              queueName="surveyanswerstored" />
            <queue alias="euTailspinSurveyTransferQueue"
              queueName="surveytransfer" />
          </queues>
        </storageAccount>
        <storageAccount alias="asTailspin" connectionString="...">
          <queues>
            <queue alias="asTailspinSurveyAnswerStoredQueue" 
              queueName="surveyanswerstored" />
            <queue alias="asTailspinSurveyTransferQueue"
              queueName="surveytransfer" />
          </queues>
        </storageAccount>
      </storageAccounts>
    </subscription>
  </subscriptions>
  <scaleGroups />
</serviceModel>

Rules

<?xml version="1.0" encoding="utf-16"?>
<rules ...>
  <constraintRules>
    <!--
      An example constraint rule - there are more.
      We need duplicates of the same rule because the utcOffset values are different.
      In some cases it may be possible to use the same rule with an action for each 
      region.
    -->
    <rule name="US WorkerRole reserving instances for midnight survey processing" 
      description="..." enabled="true" rank="5">
      <timetable startDate="2011-10-05" endDate="2012-10-06" startTime="00:01:00" 
         duration="02:00:00" utcOffset="-08:00">
        <daily />
      </timetable>
      <actions>
        <range target="usTailSpinWorkersSurveys" min="3" max="6" />
      </actions>
    </rule>
    <rule name="EU WorkerRole reserving instances for midnight survey processing" 
      description="..." enabled="true" rank="5">
      <timetable startDate="2011-10-05" endDate="2012-10-06" startTime="00:01:00" 
        duration="02:00:00" utcOffset="+00:00">
        <daily />
      </timetable>
      <actions>
        <range target="euTailSpinWorkersSurveys" min="3" max="6" />
      </actions>
    </rule>
    <rule name="ASIA WorkerRole reserving instances for midnight survey processing" 
      description="..." enabled="true" rank="5">
      <timetable startDate="2011-10-05" endDate="2012-10-06" startTime="00:01:00" 
        duration="02:00:00" utcOffset="+09:00">
        <daily />
      </timetable>
      <actions>
        <range target="asTailSpinWorkersSurveys" min="3" max="6" />
      </actions>
    </rule>
  </constraintRules>
  
  
  
  <reactiveRules>
    <!--
      An example reactive rule - there are more.
      We need duplicates of the same rule because we must tie the operand source to 
      the correct target.
    -->
    <rule name="US Heavy demand on public site" description="..." enabled="true">
      <actions>
        <scale target="usTailSpinWebSurveyPublic" by="1" />
      </actions>
      <when>
        <greater operand="usASPNET_requests_rejected" than="5" />
      </when>
      <rank>0</rank>
    </rule>
    <rule name="EU Heavy demand on public site" description="..." enabled="true">
      <actions>
        <scale target="euTailSpinWebSurveyPublic" by="1" />
      </actions>
      <when>
        <greater operand="euASPNET_requests_rejected" than="5" />
      </when>
      <rank>0</rank>
    </rule>
    <rule name="AS Heavy demand on public site" description="..." enabled="true">
      <actions>
        <scale target="asTailSpinWebSurveyPublic" by="1" />
      </actions>
      <when>
        <greater operand="asASPNET_requests_rejected" than="5" />
      </when>
      <rank>0</rank>
    </rule>
  </reactiveRules>

  <operands>
    <!-- Operands for US roles -->
    <performanceCounter alias="usASPNET_requests_rejected" timespan="00:10:00" 
      aggregate="Average" source="usTailSpinWebSurveyPublic" 
      performanceCounterName="\ASP.NET\Requests Rejected" />
    <performanceCounter alias="usCPU_over_20_minutes_for_TailspinWeb" 
      timespan="00:20:00" aggregate="Average" source="usTailSpinWeb" 
      performanceCounterName="\Processor(_Total)\% Processor Time" />
    <performanceCounter alias="usCPU_over_30_minutes" timespan="00:30:00" 
      aggregate="Average" source="usTailSpinWorkersSurveys" 
      performanceCounterName="\Processor(_Total)\% Processor Time" />

    <!-- Operands for EU roles -->
    <performanceCounter alias="euASPNET_requests_rejected" timespan="00:10:00" 
      aggregate="Average" source="euTailSpinWebSurveyPublic" 
      performanceCounterName="\ASP.NET\Requests Rejected" />
    <performanceCounter alias="euCPU_over_20_minutes_for_TailspinWeb" 
      timespan="00:20:00" aggregate="Average" source="euTailSpinWeb" 
      performanceCounterName="\Processor(_Total)\% Processor Time" />
    <performanceCounter alias="euCPU_over_30_minutes" timespan="00:30:00" 
      aggregate="Average" source="euTailSpinWorkersSurveys" 
      performanceCounterName="\Processor(_Total)\% Processor Time" />

    <!-- Operands for Asia roles -->
    <performanceCounter alias="asASPNET_requests_rejected" timespan="00:10:00" 
      aggregate="Average" source="asTailSpinWebSurveyPublic" 
      performanceCounterName="\ASP.NET\Requests Rejected" />
    <performanceCounter alias="asCPU_over_20_minutes_for_TailspinWeb" 
      timespan="00:20:00" aggregate="Average" source="asTailSpinWeb" 
      performanceCounterName="\Processor(_Total)\% Processor Time" />
    <performanceCounter alias="asCPU_over_30_minutes" timespan="00:30:00" 
      aggregate="Average" source="asTailSpinWorkersSurveys" 
      performanceCounterName="\Processor(_Total)\% Processor Time" />

    <!-- Custom operands – require an attribute to specify the hosted service -->
    <activeSurveysOperand alias="usNumberOfSurveysSubmitted" timespan="00:10:00"  
      aggregate="Average" minNumberOfAnswers="0" hostedService="USTailspin"
      xmlns="http://Tailspin/ActiveSurveys" />
    <tenantCountOperand alias="usNumberOfTenants" timespan="00:10:00"  
      aggregate="Average" hostedService="USTailspin"
      xmlns="http://Tailspin/TenantCount" />

    <activeSurveysOperand alias="euNumberOfSurveysSubmitted" timespan="00:10:00"  
      aggregate="Average" minNumberOfAnswers="0" hostedService="EUTailspin"
      xmlns="http://Tailspin/ActiveSurveys" />
    <tenantCountOperand alias="euNumberOfTenants" timespan="00:10:00"  
      aggregate="Average" hostedService="EUTailspin"
      xmlns="http://Tailspin/TenantCount" />

    <activeSurveysOperand alias="asNumberOfSurveysSubmitted" timespan="00:10:00"  
      aggregate="Average" minNumberOfAnswers="0" hostedService="ASTailspin"
      xmlns="http://Tailspin/ActiveSurveys" />
    <tenantCountOperand alias="asNumberOfTenants" timespan="00:10:00"  
      aggregate="Average" hostedService="ASTailspin"
      xmlns="http://Tailspin/TenantCount" />

  </operands>
</rules>

Option 2

Option 2 deploys the management application to the North Central US data center only and the Autoscaling Application Block to each data center. Each data center has its own service model definition and rule set.

Service Model

<?xml version="1.0" encoding="utf-8"?>
<serviceModel ...>
  <subscriptions>
    <subscription name="Tailspin Surveys Production"
                  subscriptionId="..."
                  certificateThumbprint="..."
                  certificateStoreName="My"
                  certificateStoreLocation="LocalMachine">
      <services>
        <!-- 
          Single service definitions.
          Each data center has a copy of this model with the dnsPrefix changed to
          reflect the data center location.
        -->
       <service dnsPrefix="ustailspinsurveys" slot="Production" scalingMode="Scale">
          <roles>
           <role alias="TailSpinWorkersSurveys" roleName="TailSpin.Workers.Surveys" 
              wadStorageAccountName="Tailspin" />
            <role alias="TailSpinWebSurveyPublic" 
              roleName="TailSpin.Web.Survey.Public"
              wadStorageAccountName="Tailspin" />
            <role alias="TailSpinWeb" roleName="TailSpin.Web" 
              wadStorageAccountName="Tailspin" />
          </roles>
        </service>
       </services>
      <!--
        Single storage account, duplicated in each data center.
        Each data center will have a different
        connectionString for its storage account.
      -->
      <storageAccounts>
        <storageAccount alias="Tailspin" connectionString="...">
          <queues>
            <queue alias="TailspinSurveyAnswerStoredQueue" 
              queueName="surveyanswerstored" />
            <queue alias="TailspinSurveyTransferQueue" queueName="surveytransfer" />
          </queues>
        </storageAccount>
      </storageAccounts>
    </subscription>
  </subscriptions>
  <scaleGroups />
</serviceModel>

Rules

<?xml version="1.0" encoding="utf-16"?>
<rules ...>
  <constraintRules>
    <!--
     An example constraint rule - there are more.
     Each region has its own rules file - it must be edited to reflect the different 
     utcOffset values.
    -->
    <rule name="WorkerRole reserving instances for midnight survey processing" description="..." enabled="true" rank="5">
      <timetable startDate="2011-10-05" endDate="2012-10-06" startTime="00:01:00" 
                 duration="02:00:00" utcOffset="-08:00">
        <daily />
      </timetable>
      <actions>
        <range target="TailSpinWorkersSurveys" min="3" max="6" />
      </actions>
    </rule>
  </constraintRules>
  
  
  
  <reactiveRules>
    <!--
      An example reactive rule - there are more.
      Each region can have the same reactive rules, although you may want to change 
      them in each region to reflect different usage patterns.
    -->
    <rule name="Heavy demand on public site" description="..." enabled="true">
      <actions>
        <scale target="TailSpinWebSurveyPublic" by="1" />
      </actions>
      <when>
        <greater operand="ASPNET_requests_rejected" than="5" />
      </when>
      <rank>0</rank>
    </rule>

  </reactiveRules>

  <operands>
    <!-- Operands can be identical for the different regions -->
    <performanceCounter alias="ASPNET_requests_rejected" timespan="00:10:00" 
      aggregate="Average" source="TailSpinWebSurveyPublic" 
      performanceCounterName="\ASP.NET\Requests Rejected" />
    <performanceCounter alias="CPU_over_20_minutes_for_TailspinWeb" 
      timespan="00:20:00" aggregate="Average" source="TailSpinWeb" 
      performanceCounterName="\Processor(_Total)\% Processor Time" />
    <performanceCounter alias="CPU_over_30_minutes" timespan="00:30:00" 
      aggregate="Average" source="TailSpinWorkersSurveys" 
      performanceCounterName="\Processor(_Total)\% Processor Time" />

    <activeSurveysOperand alias="NumberOfSurveysSubmitted" timespan="00:10:00" 
      aggregate="Average" minNumberOfAnswers="0" 
      xmlns="http://Tailspin/ActiveSurveys" />
    <tenantCountOperand alias="NumberOfTenants" timespan="00:10:00" 
      aggregate="Average" xmlns="http://Tailspin/TenantCount" />
  </operands>

</rules>

Next Topic | Previous Topic | Home

Last built: June 7, 2012