Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • William Pedrick 6 posts 96 karma points
    19 days ago
    William Pedrick
    0

    Load Balancing in Azure Web Apps with Umbraco 11

    We are looking to use the load balancing function in Azure Web Apps with our Umbraco 11 system and wanted to see if anyone else in the forum had previously done this.

    My understanding from the following 2 articles is:

    https://docs.umbraco.com/umbraco-cms/fundamentals/setup/server-setup/load-balancing/azure-web-apps

    https://docs.umbraco.com/umbraco-cms/fundamentals/setup/server-setup/load-balancing/flexible-advanced#explicit-schedulingpublisher-server

    1 - We have to setup 2 branches of code (instead of just 1), e.g.

    Master - Administrator

    Master - Public Facing

    2 - We edit the lines in the appsettings.json file on 'Master - Public Facing' branch to:

    " ""Examine"": { ""LuceneDirectoryFactory"": ""TempFileSystemDirectoryFactory"""

    3 - Create a couple of small classes that implement IServerRoleAccessor one for each of the different server roles:

    "public class SchedulingPublisherServerRoleAccessor : IServerRoleAccessor { public ServerRole CurrentServerRole => ServerRole.SchedulingPublisher; }"

    "public class SubscriberServerRoleAccessor : IServerRoleAccessor { public ServerRole CurrentServerRole => ServerRole.Subscriber; }"

    4 - Replace the default IServerRoleAccessor for the your custom registrars. You'll can do this by using the SetServerRegistrar() extension method on IUmbracoBuilder from a Composer or directly in your startup.cs.

    "// This should be executed on your single SchedulingPublisher server builder.SetServerRegistrar

    "// This should be executed on your Subscriber servers builder.SetServerRegistrar

    I am trying to learn how this works, so that I am able to understand the deployment process; is anyone able to provide (I am not a developer, so have very limited knowledge) any more simplified step-by-step instructions regarding steps 3 and 4, so that I can make these changes in the code myself?

  • Owain Jones 34 posts 235 karma points MVP 3x c-trib
    6 days ago
    Owain Jones
    1

    Hi William,

    I usually use an environment variable to toggle the server role:

     public class MyComposer : IComposer
     {
          private readonly string _serverRole;
    
          public Composer()
          {
               var serverRole = Environment.GetEnvironmentVariable("UMBRACO_SERVER_ROLE");
    
               if (serverRole.IsNullOrWhiteSpace() == false)
               {
                    _serverRole = serverRole;
               }
          }
    
          public void Compose(IUmbracoBuilder builder)
          {
               // Explicitly set Server Role
               if (_serverRole.InvariantEquals("SchedulingPublisher"))
               {
                    builder.SetServerRegistrar<SchedulingPublisherServerRoleAccessor>();
               }
               else if (_serverRole.InvariantEquals("Subscriber"))
               {
                    builder.SetServerRegistrar<SubscriberServerRoleAccessor>();
               }
               else if (_serverRole.InvariantEquals("Single"))
               {
                    builder.SetServerRegistrar<SingleServerRoleAccessor>();
               }
          }
     }
    
     public class SchedulingPublisherServerRoleAccessor : IServerRoleAccessor
     {
          public ServerRole CurrentServerRole => ServerRole.SchedulingPublisher;
     }
    
     public class SubscriberServerRoleAccessor : IServerRoleAccessor
     {
          public ServerRole CurrentServerRole => ServerRole.Subscriber;
     }
    

    This class can be placed at the root of your project (alongside the appsettings.json files is fine).

    The UMBRACO_SERVER_ROLE environment variable can then be set via the Web App's app settings in Azure, via the Configuration tab. (Set to SchedulingPublisher for the backoffice app, and Subscriber for the frontends)

    Much easier than having 2 separate branches, as it removes the possibility of a merge accidentally changing the role to something else.

    But if you do need to use 2 separate branches, then you can use the same code, but just remove the if statements and env variable code. e.g:

     public class MyComposer : IComposer
     {
          public void Compose(IUmbracoBuilder builder)
          {
               // Explicitly set Server Role as Scheduling Publisher
               builder.SetServerRegistrar<SchedulingPublisherServerRoleAccessor>();
          }
     }
    
     public class SchedulingPublisherServerRoleAccessor : IServerRoleAccessor
     {
          public ServerRole CurrentServerRole => ServerRole.SchedulingPublisher;
     }
    

    Hope that helps!

  • William Pedrick 6 posts 96 karma points
    5 days ago
    William Pedrick
    0

    Thank you Owain, that makes total sense to set the role in the Azure configuration as opposed to having 2 branches of code.

    Apologies for my ignorance (I only understand the basics of how Umbraco works), but essentially I could create a file with solely the code above, place it in the root folder and it would set the roles - as long as I add the configuration in Azure?

    What would the file name need to be called?

    Would it need to be referenced anywhere else?

    Presumably, we would always need at least 1 'Subscriber' Web App, in order for the site to work, e.g. we couldn't have 1 'SchedulingPublisher' Web App and then only turn on 'Subscriber' Web Apps as and when we needed the extra load?

    ... and the 2 types, e.g. 'SchedulingPublisher' and 'Subscriber' would need to be on different App Service Plans in order to get the benefit?

  • Owain Jones 34 posts 235 karma points MVP 3x c-trib
    5 days ago
    Owain Jones
    100

    Apologies for my ignorance (I only understand the basics of how Umbraco works), but essentially I could create a file with solely the code above, place it in the root folder and it would set the roles - as long as I add the configuration in Azure?

    No worries! That's correct :)

    Here's a screenshot of one of my projects: Screenshot of my project file structure in Visual Studio

    What would the file name need to be called?

    The file can be named anything, I usually use Composer.cs for my project's main composer.

    Would it need to be referenced anywhere else?

    Nope, as the class extends the IComposer interface, Umbraco should pick it up automatically during boot.

    Here's the docs on composers: https://docs.umbraco.com/umbraco-cms/implementation/composing

    Presumably, we would always need at least 1 'Subscriber' Web App, in order for the site to work, e.g. we couldn't have 1 'SchedulingPublisher' Web App and then only turn on 'Subscriber' Web Apps as and when we needed the extra load?

    I think it would work fine with just a Scheduled Publisher, as all the Server Role does is change how Umbraco handles scheduled tasks, e.g.:

    • SchedulingPublisher
      • Responsible for executing scheduled tasks, e.g. scheduled publishing and unpublishing.
      • This is the one your content editors should use to edit content.
      • Ideally, this should only be used by your content editors but can also serve frontend requests.
    • Subscriber
      • Does not run any scheduled tasks.
      • Should not be used by your content editors.
      • More performant for frontend requests.
      • According to the docs, has Read Only access to the database (I am in doubt if this is actually true, as I had a client's content editor, mistakenly use a frontend app to edit content for almost a year, and nothing bad happened)
    • Single
      • Basically the same as SchedulingPublisher, but only used in a single app, non-load balanced, environments. (I don't know what the technical differences are)

    By default, Umbraco delegates these roles automatically, but as you know, it's recommended to do this manually in a load-balanced environment.

    So in theory, yes you could serve your frontend traffic with your backoffice editing app (the SchedulingPublisher), but it is recommended to keep the editing app and public frontends separate for the best performance. So, I would say, only do this if hosting costs are an issue.

    ... and the 2 types, e.g. 'SchedulingPublisher' and 'Subscriber' would need to be on different App Service Plans in order to get the benefit?

    That would depend on how much traffic you're expecting, but for my clients, we always put the editing app and the frontends on their own separate app service plans for maximum performance.

  • William Pedrick 6 posts 96 karma points
    5 days ago
    William Pedrick
    0

    Thank you for your clear breakdown.

    When we deploy the LoadBalancer.cs file with this code, it is providing 6 errors in the logs:

    "C:\home\site\repository\PROJECTFOLDER\COMPANY.Web.csproj" (default target) (1:7) -> (CoreCompile target) -> C:\home\site\repository\PROJECTFOLDER\LoadBalancer.cs(1,28): error CS0246: The type or namespace name 'IComposer' could not be found (are you missing a using directive or an assembly reference?) [C:\home\site\repository\PROJECTFOLDER\COMPANY.Web.csproj] C:\home\site\repository\PROJECTFOLDER\LoadBalancer.cs(5,14): error CS1520: Method must have a return type [C:\home\site\repository\PROJECTFOLDER\COMPANY.Web.csproj] C:\home\site\repository\PROJECTFOLDER\LoadBalancer.cs(33,55): error CS0246: The type or namespace name 'IServerRoleAccessor' could not be found (are you missing a using directive or an assembly reference?) [C:\home\site\repository\PROJECTFOLDER\COMPANY.Web.csproj] C:\home\site\repository\PROJECTFOLDER\LoadBalancer.cs(35,14): error CS0246: The type or namespace name 'ServerRole' could not be found (are you missing a using directive or an assembly reference?) [C:\home\site\repository\PROJECTFOLDER\COMPANY.Web.csproj] C:\home\site\repository\PROJECTFOLDER\LoadBalancer.cs(38,46): error CS0246: The type or namespace name 'IServerRoleAccessor' could not be found (are you missing a using directive or an assembly reference?) [C:\home\site\repository\PROJECTFOLDER\COMPANY.Web.csproj] C:\home\site\repository\PROJECTFOLDER\LoadBalancer.cs(40,14): error CS0246: The type or namespace name 'ServerRole' could not be found (are you missing a using directive or an assembly reference?) [C:\home\site\repository\PROJECTFOLDER\COMPANY.Web.csproj]

  • Owain Jones 34 posts 235 karma points MVP 3x c-trib
    5 days ago
    Owain Jones
    0

    Hi William,

    You'll need to add the following usings, to the top of the LoadBalancer.cs file, to load the required assemblies:

    using Umbraco.Cms.Core.Composing;
    using Umbraco.Cms.Core.Sync;
    using Umbraco.Cms.Infrastructure.DependencyInjection;
    

    I believe these are all you'll need, but your IDE should tell you if you need any others :)

  • William Pedrick 6 posts 96 karma points
    4 days ago
    William Pedrick
    0

    Thanks Owain. I have added these to the top of the 'LoadBalancer.cs' file, but it is still giving a deployment error.

    I am not sure if it is the done thing on the forum (so apologies if not) but could I pay for your time, to jump on a call and see if you would be able to point me in the right direction of where it is failing?

Please Sign in or register to post replies

Write your reply to:

Draft