From 3258116f8f2a66839d2e568cc5ff3ab37e289c71 Mon Sep 17 00:00:00 2001 From: mole Date: Thu, 23 Oct 2025 12:58:07 +0200 Subject: [PATCH 01/27] Add general docs and SignalR --- .../load-balancing-backoffice.md | 44 ++++++++++++++ ...in-backoffice-load-balanced-environment.md | 59 +++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md create mode 100644 17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md new file mode 100644 index 00000000000..bde4901cdde --- /dev/null +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md @@ -0,0 +1,44 @@ +# Load Balancing the Backoffice + +This article contains specific information about load balancing the Umbraco backoffice, ensure you read the [Load Balancing Overview](./) and relevant articles about general load balancing principles before you begin. + +By default, the Umbraco load balancing setup assumes there are a single backoffice server, and multiple front-end servers, but from version 17 it's also possible to load balance the backoffice, meaning there's no need to differentiate from backoffice servers and front-end servers, however, this requires some additional configuration steps. + +## Server Role Accessor + +Umbraco has the concept of server roles, to differentiate between backoffice servers and front-end servers. Since all servers will be backoffice servers, we need to add a custom `IServerRoleAccessor` to specify this. + +Start by implementing a custom `IServerRoleAccessor` that pins the role as `SchedulingPublisher`: + +```csharp + public class StaticServerAccessor : IServerRoleAccessor +{ + public ServerRole CurrentServerRole => ServerRole.SchedulingPublisher; +} +``` + +You can now register this accessor, either in `Program.cs` or via a Composer: + +```csharp +umbracoBuilder.SetServerRegistrar(new StaticServerAccessor()); +``` + +This will ensure that all servers are treated as backoffice servers. + +## Load balancing Isolated Caches + +One of the issues with load balancing the backoffice is that all servers will have their own isolated caches. This means that if you make a change on one server, it won't be reflected on the other servers until their cache expires. + +To solve this issue a cache versioning mechanism is used, this is similar to optimistic concurrency control, where each server has a version number for its cache. When a server makes a change, it changes the version identifier. The other servers can then check the version identifier before accessing the cache and invalidate their cache if it's out of date. + +This does mean that the server needs to check this version identifier before a cache lookup, so by default this behaviour is disabled as it's only required when load balancing the backoffice. + +You can enable this on the umbraco builder, either in `Program.cs` or via a Composer: + +```csharp +umbracoBuilder.LoadBalanceIsolatedCaches(); +``` + +## SignalR + +The Umbraco Backoffice uses SignalR for multiple things, including real-time updates and notifications. When load balancing the backoffice, it's important to ensure that SignalR is configured correctly. See the [SignalR in a Backoffice Load Balanced Environment](./signalR-in-backoffice-load-balanced-environment.md) document for information regarding this. diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md new file mode 100644 index 00000000000..e92eb502816 --- /dev/null +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md @@ -0,0 +1,59 @@ +# SingleR in a Backoffice Load Balanced Environment +When load balancing the backoffice, we also need to take care of the the client to server communication outside of web requests. +Umbraco uses SignalR to abstract away these types of communication. This also allows us to more easily support load balancing by replacing how the communcation is done by introducing a backplane. + +## Introducing a SignalR Backplane +A SignalR backplane is akin to a loadbalancer for direct client to server web traffic. It keeps track of which client is connected to which server. So that when a client sends a message, it arrives at the right server. It also allows any connected server to send a message to all clients, even those that are not directly connected to it. + +## Choosing the right backplane +Choosing the right backplane comes down to a few things +- Message troughput +- Cost +- What infrastructure you already have in place + +Microsoft has a good list of available backplanes in its [SignalR load balancing article](https://learn.microsoft.com/en-us/aspnet/core/signalr/scale?view=aspnetcore-10.0), including a list of well known [third party offerings](https://learn.microsoft.com/en-us/aspnet/core/signalr/scale?view=aspnetcore-9.0#third-party-signalr-backplane-providers). + +## Code examples +The following code examples show you how you can easily activate SignalR load balancing using an Umbraco composer. +Note: Both Umbraco Core and these composers use `.AddSignalR().` which is ok since the underlying code registers the required services as singletons. + +### Using existing infrastructure +It is possible to use your existing database as a backplane. Do note that if this database is hosted in azure it is not possible to enable Service brokers which will have an impact on message troughput. We do however feel that when you start out with load balancing, it might be enough to cover your needs. +For more information, checkout the [github page](https://github.com/IntelliTect/IntelliTect.AspNetCore.SignalR.SqlServer). +- Add a reference to the MIntelliTect.AspNetCore.SignalR.SqlServer NuGet package +- Add the following composer to your project +```csharp +using Umbraco.Cms.Core.Composing; + +namespace Umbraco.Cms.Web.UI.SignalRLoadBalancing; + +public class SignalRComposer : IComposer +{ + public void Compose(IUmbracoBuilder builder) + { + var connectionString = builder.Config.GetUmbracoConnectionString(); + if (connectionString is null) + { + return; + } + + builder.Services.AddSignalR().AddSqlServer(connectionString); + } +} +``` + +### Azure SignalR Service +- Setup a resource as described in the [microsoft tutorial](https://learn.microsoft.com/en-us/azure/azure-signalr/signalr-quickstart-dotnet-core#create-an-azure-signalr-resource) +- Make sure the connectionstring is setup under the following key: `Azure:SignalR:ConnectionString` +- Add a reference to the Microsoft.Azure.SignalR NuGet package +- Add the following composer to your project +```csharp +using Umbraco.Cms.Core.Composing; + +namespace Umbraco.Cms.Web.UI.SignalRLoadBalancing; + +public class SignalRComposer : IComposer +{ + public void Compose(IUmbracoBuilder builder) => builder.Services.AddSignalR().AddAzureSignalR(); +} +``` From c976614c7d4576bbfcb7a9b31133b01ce0814e02 Mon Sep 17 00:00:00 2001 From: mole Date: Thu, 23 Oct 2025 13:00:17 +0200 Subject: [PATCH 02/27] Fixup SignalR doc --- ...lR-in-backoffice-load-balanced-environment.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md index e92eb502816..7b427b6e78e 100644 --- a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md @@ -1,13 +1,13 @@ -# SingleR in a Backoffice Load Balanced Environment -When load balancing the backoffice, we also need to take care of the the client to server communication outside of web requests. -Umbraco uses SignalR to abstract away these types of communication. This also allows us to more easily support load balancing by replacing how the communcation is done by introducing a backplane. +# SignalR in a Backoffice Load Balanced Environment +When load balancing the backoffice, we also need to take care of the client to server communication outside of web requests. +Umbraco uses SignalR to abstract away these types of communication. This also allows us to more easily support load balancing by replacing how the communication is done by introducing a backplane. ## Introducing a SignalR Backplane -A SignalR backplane is akin to a loadbalancer for direct client to server web traffic. It keeps track of which client is connected to which server. So that when a client sends a message, it arrives at the right server. It also allows any connected server to send a message to all clients, even those that are not directly connected to it. +A SignalR backplane is akin to a load balancer for direct client to server web traffic. It keeps track of which client is connected to which server. So that when a client sends a message, it arrives at the right server. It also allows any connected server to send a message to all clients, even those that are not directly connected to it. ## Choosing the right backplane Choosing the right backplane comes down to a few things -- Message troughput +- Message throughput - Cost - What infrastructure you already have in place @@ -18,9 +18,9 @@ The following code examples show you how you can easily activate SignalR load ba Note: Both Umbraco Core and these composers use `.AddSignalR().` which is ok since the underlying code registers the required services as singletons. ### Using existing infrastructure -It is possible to use your existing database as a backplane. Do note that if this database is hosted in azure it is not possible to enable Service brokers which will have an impact on message troughput. We do however feel that when you start out with load balancing, it might be enough to cover your needs. -For more information, checkout the [github page](https://github.com/IntelliTect/IntelliTect.AspNetCore.SignalR.SqlServer). -- Add a reference to the MIntelliTect.AspNetCore.SignalR.SqlServer NuGet package +It is possible to use your existing database as a backplane. Do note that if this database is hosted in azure it is not possible to enable Service Broker which will have an impact on message throughput. We do however feel that when you start out with load balancing, it might be enough to cover your needs. +For more information, check out the [github page](https://github.com/IntelliTect/IntelliTect.AspNetCore.SignalR.SqlServer). +- Add a reference to the IntelliTect.AspNetCore.SignalR.SqlServer NuGet package - Add the following composer to your project ```csharp using Umbraco.Cms.Core.Composing; From 15eaa326c50c7dd6845521b4da8e176644f85ca5 Mon Sep 17 00:00:00 2001 From: mole Date: Mon, 27 Oct 2025 10:53:23 +0100 Subject: [PATCH 03/27] Add settings documentation --- .../reference/configuration/README.md | 1 + .../configuration/distributedjobssettings.md | 31 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 17/umbraco-cms/reference/configuration/distributedjobssettings.md diff --git a/17/umbraco-cms/reference/configuration/README.md b/17/umbraco-cms/reference/configuration/README.md index ca4f292b6d4..fee3755ccd4 100644 --- a/17/umbraco-cms/reference/configuration/README.md +++ b/17/umbraco-cms/reference/configuration/README.md @@ -120,6 +120,7 @@ A complete list of all the configuration sections included in Umbraco, by defaul * [Connection strings settings](connectionstringssettings.md) * [Content settings](contentsettings.md) * [Debug settings](debugsettings.md) +* [Distributed jobs settings](distributedjobssettings.md) * [Examine settings](examinesettings.md) * [Exception filter settings](exceptionfiltersettings.md) * [Global settings](globalsettings.md) diff --git a/17/umbraco-cms/reference/configuration/distributedjobssettings.md b/17/umbraco-cms/reference/configuration/distributedjobssettings.md new file mode 100644 index 00000000000..e9dcfb4fe1c --- /dev/null +++ b/17/umbraco-cms/reference/configuration/distributedjobssettings.md @@ -0,0 +1,31 @@ +# Distributed jobs settings + +The distributed jobs settings allow you to configure how Umbraco handles distributed background jobs in a load-balanced environment. + +## Configuration +```json +"Umbraco": { + "CMS": { + "DistributedJobs": { + "Period": "00:00:05", + "Delay": "00:01:00" + } + } +} +``` + +## Settings + +### Period + +**Default:** `00:00:05` (5 seconds) + +Specifies how frequently each server checks for distributed background jobs that need to be run. + +A shorter period means jobs are picked up more quickly, but increases the frequency of database queries. A longer period reduces overhead but may introduce delays in job execution. + +### Delay + +**Default:** `00:01:00` (1 minute) + +Specifies how long the server should wait after initial startup before beginning to check for and run distributed background jobs. This startup delay ensures that the application is fully initialized and stable before participating in distributed job processing. From 67ab39de772c29884023f3103dd5dac941c67a45 Mon Sep 17 00:00:00 2001 From: mole Date: Mon, 27 Oct 2025 10:53:38 +0100 Subject: [PATCH 04/27] Add scheduling documentation --- 17/umbraco-cms/SUMMARY.md | 1 + .../load-balancing-backoffice.md | 5 ++ 17/umbraco-cms/reference/scheduling.md | 55 +++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/17/umbraco-cms/SUMMARY.md b/17/umbraco-cms/SUMMARY.md index f43de56b210..84f6ce3b81e 100644 --- a/17/umbraco-cms/SUMMARY.md +++ b/17/umbraco-cms/SUMMARY.md @@ -44,6 +44,7 @@ * [Running Umbraco in Docker](fundamentals/setup/server-setup/running-umbraco-in-docker.md) * [Umbraco in Load Balanced Environments](fundamentals/setup/server-setup/load-balancing/README.md) * [Load Balancing Azure Web Apps](fundamentals/setup/server-setup/load-balancing/azure-web-apps.md) + * [Load Balancing the Backoffice](fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md) * [Standalone File System](fundamentals/setup/server-setup/load-balancing/file-system-replication.md) * [Advanced Techniques With Flexible Load Balancing](fundamentals/setup/server-setup/load-balancing/flexible-advanced.md) * [Logging With Load Balancing](fundamentals/setup/server-setup/load-balancing/logging.md) diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md index bde4901cdde..322f8dfce45 100644 --- a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md @@ -42,3 +42,8 @@ umbracoBuilder.LoadBalanceIsolatedCaches(); ## SignalR The Umbraco Backoffice uses SignalR for multiple things, including real-time updates and notifications. When load balancing the backoffice, it's important to ensure that SignalR is configured correctly. See the [SignalR in a Backoffice Load Balanced Environment](./signalR-in-backoffice-load-balanced-environment.md) document for information regarding this. + + +## Background Jobs + +If you have any custom recurring background jobs that should only run on a single server, you'll need to implement `IDistributedBackgroundJob`, see [Scheduling documentation](../../../../reference/scheduling.md#background-jobs-when-load-balancing-the-backoffice) for more information. diff --git a/17/umbraco-cms/reference/scheduling.md b/17/umbraco-cms/reference/scheduling.md index 97dc57e1de2..99d30e589fa 100644 --- a/17/umbraco-cms/reference/scheduling.md +++ b/17/umbraco-cms/reference/scheduling.md @@ -332,3 +332,58 @@ switch (_serverRoleAccessor.CurrentServerRole) return Task.CompletedTask; // We return Task.CompletedTask to try again as the server role may change! } ``` + +## Background jobs when load balancing the backoffice + +When load balancing the backoffice, all servers will have the `SchedulingPublisher` role. +This means that the approach described above for restricting jobs to specific server roles will not work as intended, since all servers will match the `SchedulingPublisher` role. + +Instead, for jobs that should only run on a single server, you should implement an `IDistrutedBackgroundJob`. + +`IDistributedBackgroundJobs` is separate from `IRecurringBackgroundJob`, and are tracked in the database to ensure that only a single server runs the job at any given time. +This also means that you are not guaranteed what server will run the job, but you are guaranteed that only one server will run it. + +By default, distributed background jobs are checked every 5 seconds, with an initial delay of 1 minute after application startup. These settings can be changed in appsettings, see [Distributed jobs settings](./configuration/distributedjobssettings.md) for more information. + +### Implementing a custom distributed background job + +To implement a custom distributed background job, create a class that implements the `IDistributedBackgroundJob` interface. Just like with `IRecurringBackgroundJob` DI is available in the constructor. + +```csharp +public class MyCustomBackgroundJob : IDistributedBackgroundJob +{ + private readonly ILogger _logger; + public string Name => "MyCustomBackgroundJob"; + + public TimeSpan Period { get; private set; } + + public MyCustomBackgroundJob(ILogger logger) + { + _logger = logger; + Period = TimeSpan.FromSeconds(20); + } + + public Task ExecuteAsync() + { + // Your custom background job logic here + _logger.LogInformation("MyCustomBackgroundJob is executing."); + return Task.CompletedTask; + } +} +``` + +It's required to give your job a unique name via the `Name` property. This is used to track the job in the database. + +The period is specified via the `Period` property, which controls how often the job should be run, in this example it's every 20 seconds. + +It's not required to manually register the job in the database, however you must register it to dependency injection so Umbraco can find it. This can be done with a composer or in `Program.cs` + +```csharp +public class MyComposer : IComposer +{ + public void Compose(IUmbracoBuilder builder) + { + builder.Services.AddSingleton(); + } +} +``` From 0b29068896a5a1a67e1de9753fcf134841f3f2f1 Mon Sep 17 00:00:00 2001 From: mole Date: Mon, 27 Oct 2025 11:01:27 +0100 Subject: [PATCH 05/27] Fix some linting --- .../server-setup/load-balancing/load-balancing-backoffice.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md index 322f8dfce45..a137260f087 100644 --- a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md @@ -2,7 +2,7 @@ This article contains specific information about load balancing the Umbraco backoffice, ensure you read the [Load Balancing Overview](./) and relevant articles about general load balancing principles before you begin. -By default, the Umbraco load balancing setup assumes there are a single backoffice server, and multiple front-end servers, but from version 17 it's also possible to load balance the backoffice, meaning there's no need to differentiate from backoffice servers and front-end servers, however, this requires some additional configuration steps. +By default, the Umbraco load balancing setup assumes there are a single backoffice server, and multiple front-end servers. From version 17 it's possible to load balance the backoffice, meaning there's no need to differentiate from backoffice servers and front-end servers, however, this requires some additional configuration steps. ## Server Role Accessor @@ -33,7 +33,7 @@ To solve this issue a cache versioning mechanism is used, this is similar to opt This does mean that the server needs to check this version identifier before a cache lookup, so by default this behaviour is disabled as it's only required when load balancing the backoffice. -You can enable this on the umbraco builder, either in `Program.cs` or via a Composer: +You can enable this on the Umbraco builder, either in `Program.cs` or via a Composer: ```csharp umbracoBuilder.LoadBalanceIsolatedCaches(); From e1877964e632b443c39aaceef57dd5bfbef31023 Mon Sep 17 00:00:00 2001 From: mole Date: Mon, 27 Oct 2025 11:04:41 +0100 Subject: [PATCH 06/27] Update signalR article --- .../signalR-in-backoffice-load-balanced-environment.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md index 7b427b6e78e..f1200d1fced 100644 --- a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md @@ -1,6 +1,6 @@ # SignalR in a Backoffice Load Balanced Environment When load balancing the backoffice, we also need to take care of the client to server communication outside of web requests. -Umbraco uses SignalR to abstract away these types of communication. This also allows us to more easily support load balancing by replacing how the communication is done by introducing a backplane. +Umbraco uses SignalR to abstract away these types of communication. This also allows us to support load balancing by replacing how the communication is done by introducing a backplane. ## Introducing a SignalR Backplane A SignalR backplane is akin to a load balancer for direct client to server web traffic. It keeps track of which client is connected to which server. So that when a client sends a message, it arrives at the right server. It also allows any connected server to send a message to all clients, even those that are not directly connected to it. @@ -14,11 +14,11 @@ Choosing the right backplane comes down to a few things Microsoft has a good list of available backplanes in its [SignalR load balancing article](https://learn.microsoft.com/en-us/aspnet/core/signalr/scale?view=aspnetcore-10.0), including a list of well known [third party offerings](https://learn.microsoft.com/en-us/aspnet/core/signalr/scale?view=aspnetcore-9.0#third-party-signalr-backplane-providers). ## Code examples -The following code examples show you how you can easily activate SignalR load balancing using an Umbraco composer. +The following code examples show you how you can activate SignalR load balancing using an Umbraco composer. Note: Both Umbraco Core and these composers use `.AddSignalR().` which is ok since the underlying code registers the required services as singletons. ### Using existing infrastructure -It is possible to use your existing database as a backplane. Do note that if this database is hosted in azure it is not possible to enable Service Broker which will have an impact on message throughput. We do however feel that when you start out with load balancing, it might be enough to cover your needs. +It is possible to use your existing database as a backplane. If this database is hosted in azure it is not possible to enable Service Broker which will have an impact on message throughput. We do however feel that when you start out with load balancing, it might be enough to cover your needs. For more information, check out the [github page](https://github.com/IntelliTect/IntelliTect.AspNetCore.SignalR.SqlServer). - Add a reference to the IntelliTect.AspNetCore.SignalR.SqlServer NuGet package - Add the following composer to your project From 5aa185dd1d77ec658f558c940ccf59dacea3c587 Mon Sep 17 00:00:00 2001 From: mole Date: Mon, 27 Oct 2025 12:50:38 +0100 Subject: [PATCH 07/27] Update capitilization --- .../signalR-in-backoffice-load-balanced-environment.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md index f1200d1fced..d423fab9ae0 100644 --- a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md @@ -18,8 +18,8 @@ The following code examples show you how you can activate SignalR load balancing Note: Both Umbraco Core and these composers use `.AddSignalR().` which is ok since the underlying code registers the required services as singletons. ### Using existing infrastructure -It is possible to use your existing database as a backplane. If this database is hosted in azure it is not possible to enable Service Broker which will have an impact on message throughput. We do however feel that when you start out with load balancing, it might be enough to cover your needs. -For more information, check out the [github page](https://github.com/IntelliTect/IntelliTect.AspNetCore.SignalR.SqlServer). +It is possible to use your existing database as a backplane. If this database is hosted in Azure it is not possible to enable Service Broker which will have an impact on message throughput. We do however feel that when you start out with load balancing, it might be enough to cover your needs. +For more information, check out the [Github page](https://github.com/IntelliTect/IntelliTect.AspNetCore.SignalR.SqlServer). - Add a reference to the IntelliTect.AspNetCore.SignalR.SqlServer NuGet package - Add the following composer to your project ```csharp @@ -43,7 +43,7 @@ public class SignalRComposer : IComposer ``` ### Azure SignalR Service -- Setup a resource as described in the [microsoft tutorial](https://learn.microsoft.com/en-us/azure/azure-signalr/signalr-quickstart-dotnet-core#create-an-azure-signalr-resource) +- Setup a resource as described in the [Microsoft tutorial](https://learn.microsoft.com/en-us/azure/azure-signalr/signalr-quickstart-dotnet-core#create-an-azure-signalr-resource) - Make sure the connectionstring is setup under the following key: `Azure:SignalR:ConnectionString` - Add a reference to the Microsoft.Azure.SignalR NuGet package - Add the following composer to your project From a359f91732dcf53bc3fcd7884367a9a0bea2774d Mon Sep 17 00:00:00 2001 From: mole Date: Mon, 27 Oct 2025 13:11:38 +0100 Subject: [PATCH 08/27] Fix sentences --- .../load-balancing/load-balancing-backoffice.md | 10 +++++----- .../signalR-in-backoffice-load-balanced-environment.md | 2 +- 17/umbraco-cms/reference/scheduling.md | 5 ++--- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md index a137260f087..c021bf946f5 100644 --- a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md @@ -1,8 +1,8 @@ # Load Balancing the Backoffice -This article contains specific information about load balancing the Umbraco backoffice, ensure you read the [Load Balancing Overview](./) and relevant articles about general load balancing principles before you begin. +This article contains specific information about load balancing the Umbraco backoffice. Ensure you read the [Load Balancing Overview](./) and relevant articles about general load balancing principles before you begin. -By default, the Umbraco load balancing setup assumes there are a single backoffice server, and multiple front-end servers. From version 17 it's possible to load balance the backoffice, meaning there's no need to differentiate from backoffice servers and front-end servers, however, this requires some additional configuration steps. +By default, the Umbraco load balancing setup assumes there is a single backoffice server and multiple front-end servers. From version 17, it's possible to load balance the backoffice. This means there's no need to differentiate between backoffice servers and front-end servers. However, this requires some additional configuration steps. ## Server Role Accessor @@ -29,9 +29,9 @@ This will ensure that all servers are treated as backoffice servers. One of the issues with load balancing the backoffice is that all servers will have their own isolated caches. This means that if you make a change on one server, it won't be reflected on the other servers until their cache expires. -To solve this issue a cache versioning mechanism is used, this is similar to optimistic concurrency control, where each server has a version number for its cache. When a server makes a change, it changes the version identifier. The other servers can then check the version identifier before accessing the cache and invalidate their cache if it's out of date. +To solve this issue, a cache versioning mechanism is used. This is similar to optimistic concurrency control. Each server has a version number for its cache. When a server makes a change, it updates the version identifier. The other servers can then check the version identifier before accessing the cache. If the cache is out of date, they invalidate it. -This does mean that the server needs to check this version identifier before a cache lookup, so by default this behaviour is disabled as it's only required when load balancing the backoffice. +This does mean that the server needs to check this version identifier before a cache lookup. By default, this behaviour is disabled. It's only required when load balancing the backoffice. You can enable this on the Umbraco builder, either in `Program.cs` or via a Composer: @@ -46,4 +46,4 @@ The Umbraco Backoffice uses SignalR for multiple things, including real-time upd ## Background Jobs -If you have any custom recurring background jobs that should only run on a single server, you'll need to implement `IDistributedBackgroundJob`, see [Scheduling documentation](../../../../reference/scheduling.md#background-jobs-when-load-balancing-the-backoffice) for more information. +If you have custom recurring background jobs that should only run on a single server, you'll need to implement `IDistributedBackgroundJob`. See [Scheduling documentation](../../../../reference/scheduling.md#background-jobs-when-load-balancing-the-backoffice) for more information. diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md index d423fab9ae0..055a8d114e7 100644 --- a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md @@ -19,7 +19,7 @@ Note: Both Umbraco Core and these composers use `.AddSignalR().` which is ok sin ### Using existing infrastructure It is possible to use your existing database as a backplane. If this database is hosted in Azure it is not possible to enable Service Broker which will have an impact on message throughput. We do however feel that when you start out with load balancing, it might be enough to cover your needs. -For more information, check out the [Github page](https://github.com/IntelliTect/IntelliTect.AspNetCore.SignalR.SqlServer). +For more information, check out the [GitHub page](https://github.com/IntelliTect/IntelliTect.AspNetCore.SignalR.SqlServer). - Add a reference to the IntelliTect.AspNetCore.SignalR.SqlServer NuGet package - Add the following composer to your project ```csharp diff --git a/17/umbraco-cms/reference/scheduling.md b/17/umbraco-cms/reference/scheduling.md index 99d30e589fa..8ade212998d 100644 --- a/17/umbraco-cms/reference/scheduling.md +++ b/17/umbraco-cms/reference/scheduling.md @@ -335,8 +335,7 @@ switch (_serverRoleAccessor.CurrentServerRole) ## Background jobs when load balancing the backoffice -When load balancing the backoffice, all servers will have the `SchedulingPublisher` role. -This means that the approach described above for restricting jobs to specific server roles will not work as intended, since all servers will match the `SchedulingPublisher` role. +When load balancing the backoffice, all servers will have the `SchedulingPublisher` role. This means the approach described above for restricting jobs to specific server roles will not work as intended. All servers will match the `SchedulingPublisher` role. Instead, for jobs that should only run on a single server, you should implement an `IDistrutedBackgroundJob`. @@ -347,7 +346,7 @@ By default, distributed background jobs are checked every 5 seconds, with an ini ### Implementing a custom distributed background job -To implement a custom distributed background job, create a class that implements the `IDistributedBackgroundJob` interface. Just like with `IRecurringBackgroundJob` DI is available in the constructor. +To implement a custom distributed background job, create a class that implements the `IDistributedBackgroundJob` interface. Like with `IRecurringBackgroundJob` DI is available in the constructor. ```csharp public class MyCustomBackgroundJob : IDistributedBackgroundJob From 69d8f86e6aec0cdd4e0087f3d6b9e2cf867e8f23 Mon Sep 17 00:00:00 2001 From: Mole Date: Mon, 27 Oct 2025 13:13:59 +0100 Subject: [PATCH 09/27] Apply suggestions from code review Co-authored-by: Andy Butland --- .../signalR-in-backoffice-load-balanced-environment.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md index 055a8d114e7..64bbdb901e9 100644 --- a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md @@ -15,10 +15,13 @@ Microsoft has a good list of available backplanes in its [SignalR load balancing ## Code examples The following code examples show you how you can activate SignalR load balancing using an Umbraco composer. -Note: Both Umbraco Core and these composers use `.AddSignalR().` which is ok since the underlying code registers the required services as singletons. + +{% hint style="info" %} +Both Umbraco and these composers use `.AddSignalR()`. This duplication isn't a concern as the underlying code registers the required services as singletons. +{% endhint %} ### Using existing infrastructure -It is possible to use your existing database as a backplane. If this database is hosted in Azure it is not possible to enable Service Broker which will have an impact on message throughput. We do however feel that when you start out with load balancing, it might be enough to cover your needs. +It is possible to use your existing database as a backplane. If this database is hosted in Azure it is not possible to enable Service Broker which will have an impact on message throughput. Nevertheless, it might be sufficient to cover your needs. For more information, check out the [GitHub page](https://github.com/IntelliTect/IntelliTect.AspNetCore.SignalR.SqlServer). - Add a reference to the IntelliTect.AspNetCore.SignalR.SqlServer NuGet package - Add the following composer to your project From 6b571b5c0958ab46bb70e002fa38eeebf96ca882 Mon Sep 17 00:00:00 2001 From: mole Date: Mon, 27 Oct 2025 13:14:38 +0100 Subject: [PATCH 10/27] Apply suggestions from code review --- 17/umbraco-cms/SUMMARY.md | 1 + .../server-setup/load-balancing/load-balancing-backoffice.md | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/17/umbraco-cms/SUMMARY.md b/17/umbraco-cms/SUMMARY.md index 84f6ce3b81e..026c3cf5645 100644 --- a/17/umbraco-cms/SUMMARY.md +++ b/17/umbraco-cms/SUMMARY.md @@ -45,6 +45,7 @@ * [Umbraco in Load Balanced Environments](fundamentals/setup/server-setup/load-balancing/README.md) * [Load Balancing Azure Web Apps](fundamentals/setup/server-setup/load-balancing/azure-web-apps.md) * [Load Balancing the Backoffice](fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md) + * [SignalR In Load Balanced Environments](fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md) * [Standalone File System](fundamentals/setup/server-setup/load-balancing/file-system-replication.md) * [Advanced Techniques With Flexible Load Balancing](fundamentals/setup/server-setup/load-balancing/flexible-advanced.md) * [Logging With Load Balancing](fundamentals/setup/server-setup/load-balancing/logging.md) diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md index c021bf946f5..f908777809a 100644 --- a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md @@ -25,9 +25,9 @@ umbracoBuilder.SetServerRegistrar(new StaticServerAccessor()); This will ensure that all servers are treated as backoffice servers. -## Load balancing Isolated Caches +## Load balancing Repository Caches -One of the issues with load balancing the backoffice is that all servers will have their own isolated caches. This means that if you make a change on one server, it won't be reflected on the other servers until their cache expires. +One of the issues with load balancing the backoffice is that all servers will have their own repository caches. This means that if you make a change on one server, it won't be reflected on the other servers until their cache expires. To solve this issue, a cache versioning mechanism is used. This is similar to optimistic concurrency control. Each server has a version number for its cache. When a server makes a change, it updates the version identifier. The other servers can then check the version identifier before accessing the cache. If the cache is out of date, they invalidate it. From edf87a4e7d1e99fc7d12833a0b78d46e1fd0aab3 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 28 Oct 2025 09:20:47 +0100 Subject: [PATCH 11/27] Added Distributed jobs settings article entry to Summary.md file --- 17/umbraco-cms/SUMMARY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/17/umbraco-cms/SUMMARY.md b/17/umbraco-cms/SUMMARY.md index 026c3cf5645..dbe35163595 100644 --- a/17/umbraco-cms/SUMMARY.md +++ b/17/umbraco-cms/SUMMARY.md @@ -288,6 +288,7 @@ * [Content Settings](reference/configuration/contentsettings.md) * [Data Types Settings](reference/configuration/datatypes.md) * [Debug settings](reference/configuration/debugsettings.md) + * [Distributed jobs settings](reference/configuration/distributedjobssettings.md) * [Examine settings](reference/configuration/examinesettings.md) * [Exception filter settings](reference/configuration/exceptionfiltersettings.md) * [FileSystemProviders Configuration](reference/configuration/filesystemproviders.md) From a387438582b52ddfd65111ad1f4ce63781267968 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 28 Oct 2025 09:29:43 +0100 Subject: [PATCH 12/27] Update 17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md --- .../server-setup/load-balancing/load-balancing-backoffice.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md index f908777809a..82635d0348d 100644 --- a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md @@ -6,7 +6,7 @@ By default, the Umbraco load balancing setup assumes there is a single backoffic ## Server Role Accessor -Umbraco has the concept of server roles, to differentiate between backoffice servers and front-end servers. Since all servers will be backoffice servers, we need to add a custom `IServerRoleAccessor` to specify this. +Umbraco has the concept of server roles to differentiate between backoffice servers and front-end servers. Since all servers will be backoffice servers, we need to add a custom `IServerRoleAccessor` to specify this. Start by implementing a custom `IServerRoleAccessor` that pins the role as `SchedulingPublisher`: From add879265e954540df97634e24e400cba4e021be Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 28 Oct 2025 09:29:53 +0100 Subject: [PATCH 13/27] Update 17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md --- .../server-setup/load-balancing/load-balancing-backoffice.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md index 82635d0348d..6600e2fd94d 100644 --- a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md @@ -17,7 +17,7 @@ Start by implementing a custom `IServerRoleAccessor` that pins the role as `Sche } ``` -You can now register this accessor, either in `Program.cs` or via a Composer: +You can now register this accessor either in `Program.cs` or via a Composer: ```csharp umbracoBuilder.SetServerRegistrar(new StaticServerAccessor()); From f36fb86d6244b2c2372649046ef98198b7789bfa Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 28 Oct 2025 09:30:04 +0100 Subject: [PATCH 14/27] Update 17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md --- .../server-setup/load-balancing/load-balancing-backoffice.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md index 6600e2fd94d..8b38437e5d9 100644 --- a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md @@ -25,7 +25,7 @@ umbracoBuilder.SetServerRegistrar(new StaticServerAccessor()); This will ensure that all servers are treated as backoffice servers. -## Load balancing Repository Caches +## Load Balancing Repository Caches One of the issues with load balancing the backoffice is that all servers will have their own repository caches. This means that if you make a change on one server, it won't be reflected on the other servers until their cache expires. From d7debe5fb929f160bfd5533251f7492531aa9339 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 28 Oct 2025 09:30:22 +0100 Subject: [PATCH 15/27] Update 17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md --- .../server-setup/load-balancing/load-balancing-backoffice.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md index 8b38437e5d9..e02d747d289 100644 --- a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/load-balancing-backoffice.md @@ -31,7 +31,7 @@ One of the issues with load balancing the backoffice is that all servers will ha To solve this issue, a cache versioning mechanism is used. This is similar to optimistic concurrency control. Each server has a version number for its cache. When a server makes a change, it updates the version identifier. The other servers can then check the version identifier before accessing the cache. If the cache is out of date, they invalidate it. -This does mean that the server needs to check this version identifier before a cache lookup. By default, this behaviour is disabled. It's only required when load balancing the backoffice. +This means the server needs to check the version identifier before a cache lookup. By default, this behavior is disabled. It's only required when load balancing the backoffice. You can enable this on the Umbraco builder, either in `Program.cs` or via a Composer: From 848213602b1b55dfecabf4d57bb3708fabc3497d Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 28 Oct 2025 09:30:33 +0100 Subject: [PATCH 16/27] Update 17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md --- .../signalR-in-backoffice-load-balanced-environment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md index 64bbdb901e9..0852471319b 100644 --- a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md @@ -1,5 +1,5 @@ # SignalR in a Backoffice Load Balanced Environment -When load balancing the backoffice, we also need to take care of the client to server communication outside of web requests. +When load balancing the backoffice, we also need to take care of the client-to-server communication outside of web requests. Umbraco uses SignalR to abstract away these types of communication. This also allows us to support load balancing by replacing how the communication is done by introducing a backplane. ## Introducing a SignalR Backplane From 41bf3c57e57ccc4429d9f2749bdac550268e0852 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 28 Oct 2025 09:30:48 +0100 Subject: [PATCH 17/27] Update 17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md --- .../signalR-in-backoffice-load-balanced-environment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md index 0852471319b..3c2eb85dcee 100644 --- a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md @@ -3,7 +3,7 @@ When load balancing the backoffice, we also need to take care of the client-to-s Umbraco uses SignalR to abstract away these types of communication. This also allows us to support load balancing by replacing how the communication is done by introducing a backplane. ## Introducing a SignalR Backplane -A SignalR backplane is akin to a load balancer for direct client to server web traffic. It keeps track of which client is connected to which server. So that when a client sends a message, it arrives at the right server. It also allows any connected server to send a message to all clients, even those that are not directly connected to it. +A SignalR backplane is akin to a load balancer for direct client-to-server web traffic. It keeps track of which client is connected to which server. So that when a client sends a message, it arrives at the right server. It also allows any connected server to send a message to all clients, even those that are not directly connected to it. ## Choosing the right backplane Choosing the right backplane comes down to a few things From 78c68beff77a8f8c9ae1a38adef355724ca36bcb Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 28 Oct 2025 09:30:59 +0100 Subject: [PATCH 18/27] Update 17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md --- .../signalR-in-backoffice-load-balanced-environment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md index 3c2eb85dcee..d069c7c3e3e 100644 --- a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md @@ -6,7 +6,7 @@ Umbraco uses SignalR to abstract away these types of communication. This also al A SignalR backplane is akin to a load balancer for direct client-to-server web traffic. It keeps track of which client is connected to which server. So that when a client sends a message, it arrives at the right server. It also allows any connected server to send a message to all clients, even those that are not directly connected to it. ## Choosing the right backplane -Choosing the right backplane comes down to a few things +Choosing the right backplane comes down to a few factors: - Message throughput - Cost - What infrastructure you already have in place From 3becae2447d2ecf8ff804b946d458b4d2f9c359c Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 28 Oct 2025 09:31:11 +0100 Subject: [PATCH 19/27] Update 17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md --- .../signalR-in-backoffice-load-balanced-environment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md index d069c7c3e3e..7f19aa7a621 100644 --- a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md @@ -23,7 +23,7 @@ Both Umbraco and these composers use `.AddSignalR()`. This duplication isn't a ### Using existing infrastructure It is possible to use your existing database as a backplane. If this database is hosted in Azure it is not possible to enable Service Broker which will have an impact on message throughput. Nevertheless, it might be sufficient to cover your needs. For more information, check out the [GitHub page](https://github.com/IntelliTect/IntelliTect.AspNetCore.SignalR.SqlServer). -- Add a reference to the IntelliTect.AspNetCore.SignalR.SqlServer NuGet package +- Add a reference to the `IntelliTect.AspNetCore.SignalR.SqlServer` NuGet package. - Add the following composer to your project ```csharp using Umbraco.Cms.Core.Composing; From 630cc8e80c84cbd7b4c8707ab11bdf9cea3adb0f Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 28 Oct 2025 09:31:22 +0100 Subject: [PATCH 20/27] Update 17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md --- .../signalR-in-backoffice-load-balanced-environment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md index 7f19aa7a621..7c95c85fd46 100644 --- a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md @@ -14,7 +14,7 @@ Choosing the right backplane comes down to a few factors: Microsoft has a good list of available backplanes in its [SignalR load balancing article](https://learn.microsoft.com/en-us/aspnet/core/signalr/scale?view=aspnetcore-10.0), including a list of well known [third party offerings](https://learn.microsoft.com/en-us/aspnet/core/signalr/scale?view=aspnetcore-9.0#third-party-signalr-backplane-providers). ## Code examples -The following code examples show you how you can activate SignalR load balancing using an Umbraco composer. +The following code examples show how you can activate SignalR load balancing using an Umbraco composer. {% hint style="info" %} Both Umbraco and these composers use `.AddSignalR()`. This duplication isn't a concern as the underlying code registers the required services as singletons. From f758cfdf7ecff792b7af237be3a3cdfc8f9989f9 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 28 Oct 2025 09:31:35 +0100 Subject: [PATCH 21/27] Update 17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md --- .../signalR-in-backoffice-load-balanced-environment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md index 7c95c85fd46..32ab92a8184 100644 --- a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md @@ -24,7 +24,7 @@ Both Umbraco and these composers use `.AddSignalR()`. This duplication isn't a It is possible to use your existing database as a backplane. If this database is hosted in Azure it is not possible to enable Service Broker which will have an impact on message throughput. Nevertheless, it might be sufficient to cover your needs. For more information, check out the [GitHub page](https://github.com/IntelliTect/IntelliTect.AspNetCore.SignalR.SqlServer). - Add a reference to the `IntelliTect.AspNetCore.SignalR.SqlServer` NuGet package. -- Add the following composer to your project +- Add the following composer to your project: ```csharp using Umbraco.Cms.Core.Composing; From 5feb2fefb430615dbc20710c36469f89076986b8 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 28 Oct 2025 09:32:16 +0100 Subject: [PATCH 22/27] Update 17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md --- .../signalR-in-backoffice-load-balanced-environment.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md index 32ab92a8184..b937ccecb90 100644 --- a/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md +++ b/17/umbraco-cms/fundamentals/setup/server-setup/load-balancing/signalR-in-backoffice-load-balanced-environment.md @@ -46,10 +46,10 @@ public class SignalRComposer : IComposer ``` ### Azure SignalR Service -- Setup a resource as described in the [Microsoft tutorial](https://learn.microsoft.com/en-us/azure/azure-signalr/signalr-quickstart-dotnet-core#create-an-azure-signalr-resource) -- Make sure the connectionstring is setup under the following key: `Azure:SignalR:ConnectionString` -- Add a reference to the Microsoft.Azure.SignalR NuGet package -- Add the following composer to your project +- Set up a resource as described in the [Microsoft tutorial](https://learn.microsoft.com/en-us/azure/azure-signalr/signalr-quickstart-dotnet-core#create-an-azure-signalr-resource). +- Make sure the `connectionstring` is set up under the following key: `Azure:SignalR:ConnectionString`. +- Add a reference to `Microsoft.Azure.SignalR` NuGet package. +- Add the following composer to your project: ```csharp using Umbraco.Cms.Core.Composing; From 201786f10f9e92d0bd53de56b1ff17b14e8c8af4 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 28 Oct 2025 09:32:28 +0100 Subject: [PATCH 23/27] Update 17/umbraco-cms/reference/scheduling.md --- 17/umbraco-cms/reference/scheduling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/reference/scheduling.md b/17/umbraco-cms/reference/scheduling.md index 8ade212998d..1d557bfa9b8 100644 --- a/17/umbraco-cms/reference/scheduling.md +++ b/17/umbraco-cms/reference/scheduling.md @@ -337,7 +337,7 @@ switch (_serverRoleAccessor.CurrentServerRole) When load balancing the backoffice, all servers will have the `SchedulingPublisher` role. This means the approach described above for restricting jobs to specific server roles will not work as intended. All servers will match the `SchedulingPublisher` role. -Instead, for jobs that should only run on a single server, you should implement an `IDistrutedBackgroundJob`. +Instead, for jobs that should only run on a single server, you should implement an `IDistributedBackgroundJob`. `IDistributedBackgroundJobs` is separate from `IRecurringBackgroundJob`, and are tracked in the database to ensure that only a single server runs the job at any given time. This also means that you are not guaranteed what server will run the job, but you are guaranteed that only one server will run it. From 8409fea443b79d19f6a6f49bfea439a8e1db2812 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 28 Oct 2025 09:32:38 +0100 Subject: [PATCH 24/27] Update 17/umbraco-cms/reference/scheduling.md --- 17/umbraco-cms/reference/scheduling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/reference/scheduling.md b/17/umbraco-cms/reference/scheduling.md index 1d557bfa9b8..fac20023337 100644 --- a/17/umbraco-cms/reference/scheduling.md +++ b/17/umbraco-cms/reference/scheduling.md @@ -339,7 +339,7 @@ When load balancing the backoffice, all servers will have the `SchedulingPublish Instead, for jobs that should only run on a single server, you should implement an `IDistributedBackgroundJob`. -`IDistributedBackgroundJobs` is separate from `IRecurringBackgroundJob`, and are tracked in the database to ensure that only a single server runs the job at any given time. +`IDistributedBackgroundJob` is separate from `IRecurringBackgroundJob`, and is tracked in the database to ensure that only a single server runs the job at any given time. This also means that you are not guaranteed what server will run the job, but you are guaranteed that only one server will run it. By default, distributed background jobs are checked every 5 seconds, with an initial delay of 1 minute after application startup. These settings can be changed in appsettings, see [Distributed jobs settings](./configuration/distributedjobssettings.md) for more information. From 8258d7b7181fc689a6ce46b23b6cba1a77e307ac Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 28 Oct 2025 09:32:46 +0100 Subject: [PATCH 25/27] Update 17/umbraco-cms/reference/scheduling.md --- 17/umbraco-cms/reference/scheduling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/reference/scheduling.md b/17/umbraco-cms/reference/scheduling.md index fac20023337..04f17f08ee3 100644 --- a/17/umbraco-cms/reference/scheduling.md +++ b/17/umbraco-cms/reference/scheduling.md @@ -373,7 +373,7 @@ public class MyCustomBackgroundJob : IDistributedBackgroundJob It's required to give your job a unique name via the `Name` property. This is used to track the job in the database. -The period is specified via the `Period` property, which controls how often the job should be run, in this example it's every 20 seconds. +The period is specified via the `Period` property, which controls how often the job should run. In this example, it runs every 20 seconds. It's not required to manually register the job in the database, however you must register it to dependency injection so Umbraco can find it. This can be done with a composer or in `Program.cs` From e4c31094e420028aeae62a99ea9f92f276be233c Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 28 Oct 2025 09:32:55 +0100 Subject: [PATCH 26/27] Update 17/umbraco-cms/reference/scheduling.md --- 17/umbraco-cms/reference/scheduling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/reference/scheduling.md b/17/umbraco-cms/reference/scheduling.md index 04f17f08ee3..f026bfaac0d 100644 --- a/17/umbraco-cms/reference/scheduling.md +++ b/17/umbraco-cms/reference/scheduling.md @@ -346,7 +346,7 @@ By default, distributed background jobs are checked every 5 seconds, with an ini ### Implementing a custom distributed background job -To implement a custom distributed background job, create a class that implements the `IDistributedBackgroundJob` interface. Like with `IRecurringBackgroundJob` DI is available in the constructor. +To implement a custom distributed background job, create a class that implements the `IDistributedBackgroundJob` interface. As with `IRecurringBackgroundJob`, dependency injection (DI) is available in the constructor. ```csharp public class MyCustomBackgroundJob : IDistributedBackgroundJob From 37566a9530a51ec8e4aa62614ff407e0036ee0b1 Mon Sep 17 00:00:00 2001 From: Esha Noronha <82437098+eshanrnh@users.noreply.github.com> Date: Tue, 28 Oct 2025 09:33:04 +0100 Subject: [PATCH 27/27] Update 17/umbraco-cms/reference/scheduling.md --- 17/umbraco-cms/reference/scheduling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/17/umbraco-cms/reference/scheduling.md b/17/umbraco-cms/reference/scheduling.md index f026bfaac0d..75d0428d3b0 100644 --- a/17/umbraco-cms/reference/scheduling.md +++ b/17/umbraco-cms/reference/scheduling.md @@ -375,7 +375,7 @@ It's required to give your job a unique name via the `Name` property. This is us The period is specified via the `Period` property, which controls how often the job should run. In this example, it runs every 20 seconds. -It's not required to manually register the job in the database, however you must register it to dependency injection so Umbraco can find it. This can be done with a composer or in `Program.cs` +It's not required to manually register the job in the database, however, you must register it to DI so Umbraco can find it. This can be done with a composer or in `Program.cs` ```csharp public class MyComposer : IComposer