⚙️ Installation & Configuration
Load Balancing
📖 Docs

Load Balancing and Deployment Scenarios

Exam Area: Content Area 2 – Installation, Operation & Configuration (20%)
Reference: https://docs.developers.optimizely.com/content-management-system/docs/deploying-to-windows-servers


1. Load Balancing in Optimizely CMS

When deploying to multiple servers/instances, you must handle:


2. Load Balanced Configuration

// Startup.cs
// Requires shared cache and event provider configuration

// 1. Shared cache via Redis
builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = Configuration.GetConnectionString("Redis");
});

// 2. Azure Event Provider (for multi-instance events)
builder.Services.AddAzureServiceBusEventProvider(options =>
{
    options.ConnectionString = Configuration["ServiceBus"];
    options.TopicName = "cms-events";
});

3. Deployment Scenarios

Scenario 1: Single Server

Internet → IIS → CMS App → SQL Server
                         → File System (BLOB)

Scenario 2: Load Balanced

Internet → Load Balancer → Server 1 (CMS)
                        → Server 2 (CMS)
                        ↓
                    SQL Server (Shared)
                    Azure Blob Storage (Shared)
                    Redis Cache (Shared)

Scenario 3: DXP Cloud

Internet → Azure Front Door (CDN) → Azure App Service
                                 → Azure SQL Database
                                 → Azure Blob Storage
                                 → Redis Cache

4. IIS Configuration (Windows Server)

web.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <handlers>
        <add name="aspNetCore" path="*" verb="*" 
             modules="AspNetCoreModuleV2" 
             resourceType="Unspecified" />
      </handlers>
      <aspNetCore processPath="dotnet" 
                  arguments=".\MyOptimizelySite.dll"
                  stdoutLogEnabled="false"
                  stdoutLogFile=".\logs\stdout"
                  hostingModel="inprocess" />
    </system.webServer>
  </location>
</configuration>

5. Sticky Sessions vs Stateless

Optimizely CMS does not require Sticky Sessions if:

With Session State:

// If using sessions, a distributed session store is required
builder.Services.AddDistributedMemoryCache(); // DEV only

// Production: Use Redis
builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = "redis-connection-string";
});
builder.Services.AddSession();

6. Health Checks

// Add health checks
builder.Services.AddHealthChecks()
    .AddSqlServer(connectionString)
    .AddCheck<CmsHealthCheck>("cms");

app.MapHealthChecks("/health");

7. Deployment Steps (Windows IIS)

  1. Build the application:

    dotnet publish -c Release -o ./publish
    
  2. Copy files to the server

  3. Configure IIS:

    • Application Pool: .NET CLR → No Managed Code
    • Application Pool Identity
    • HTTPS bindings
  4. Database Connection String in appsettings.Production.json

  5. Run database migrations (if manual)


8. Application Restart and Warmup

<!-- web.config - Pre-warmup -->
<system.webServer>
  <applicationInitialization doAppInitAfterRestart="true">
    <add initializationPage="/" />
  </applicationInitialization>
</system.webServer>

Review Questions

  1. When load balancing, what must the cache be shared through? (Redis or distributed cache)
  2. What is used for event routing in multi-instance deployments? (Azure Service Bus or Redis)
  3. Which .NET CLR version should the IIS Application Pool use for .NET Core? (No Managed Code)
  4. What is the dotnet publish command used for? (Build and publish output for deployment)
  5. What is used for shared BLOB storage in the cloud? (Azure Blob Storage)