U4-10150 Process load balancing instructions on a background thread instead of a request thread

This commit is contained in:
Shannon
2017-10-31 15:11:45 +11:00
parent 2fdd1c0bd2
commit 0038d173a2
3 changed files with 63 additions and 18 deletions

View File

@@ -205,7 +205,7 @@ namespace Umbraco.Core.Sync
/// <summary>
/// Synchronize the server (throttled).
/// </summary>
protected void Sync()
protected internal void Sync()
{
lock (_locko)
{

View File

@@ -9,6 +9,7 @@ using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Sync;
using Umbraco.Web.Routing;
using Umbraco.Core.Logging;
using Umbraco.Web.Scheduling;
namespace Umbraco.Web
{
@@ -22,7 +23,31 @@ namespace Umbraco.Web
{
public BatchedDatabaseServerMessenger(ApplicationContext appContext, bool enableDistCalls, DatabaseServerMessengerOptions options)
: base(appContext, enableDistCalls, options)
{ }
{
Scheduler.Initializing += Scheduler_Initializing;
}
/// <summary>
/// Occurs when the scheduler initializes all scheduling activity when the app is ready
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Scheduler_Initializing(object sender, List<IBackgroundTask> e)
{
//if the current resolver is 'this' then we will start the scheduling
var isMessenger = ServerMessengerResolver.HasCurrent && ReferenceEquals(ServerMessengerResolver.Current.Messenger, this);
if (isMessenger)
{
//start the background task runner for processing instructions
const int delayMilliseconds = 60000;
var instructionProcessingRunner = new BackgroundTaskRunner<IBackgroundTask>("InstructionProcessing", ApplicationContext.ProfilingLogger.Logger);
var instructionProcessingTask = new InstructionProcessing(instructionProcessingRunner, this, delayMilliseconds, Options.ThrottleSeconds * 1000);
instructionProcessingRunner.TryAdd(instructionProcessingTask);
e.Add(instructionProcessingTask);
}
}
// invoked by BatchedDatabaseServerMessengerStartup which is an ApplicationEventHandler
// with default "ShouldExecute", so that method will run if app IsConfigured and database
@@ -30,7 +55,6 @@ namespace Umbraco.Web
internal void Startup()
{
UmbracoModule.EndRequest += UmbracoModule_EndRequest;
UmbracoModule.RouteAttempt += UmbracoModule_RouteAttempt;
if (ApplicationContext.DatabaseContext.CanConnect == false)
{
@@ -43,20 +67,31 @@ namespace Umbraco.Web
}
}
private void UmbracoModule_RouteAttempt(object sender, RoutableAttemptEventArgs e)
/// <summary>
/// This will process cache instructions on a background thread and will run every 5 seconds (or whatever is defined in the <see cref="DatabaseServerMessengerOptions.ThrottleSeconds"/>)
/// </summary>
private class InstructionProcessing : RecurringTaskBase
{
// as long as umbraco is ready & configured, sync
switch (e.Outcome)
private readonly DatabaseServerMessenger _messenger;
public InstructionProcessing(IBackgroundTaskRunner<RecurringTaskBase> runner,
DatabaseServerMessenger messenger,
int delayMilliseconds, int periodMilliseconds)
: base(runner, delayMilliseconds, periodMilliseconds)
{
case EnsureRoutableOutcome.IsRoutable:
case EnsureRoutableOutcome.NotDocumentRequest:
case EnsureRoutableOutcome.NoContent:
Sync();
break;
//case EnsureRoutableOutcome.NotReady:
//case EnsureRoutableOutcome.NotConfigured:
//default:
// break;
_messenger = messenger;
}
public override bool PerformRun()
{
_messenger.Sync();
//return true to repeat
return true;
}
public override bool IsAsync
{
get { return false; }
}
}

View File

@@ -74,7 +74,7 @@ namespace Umbraco.Web.Scheduling
new KeepAlive(_keepAliveRunner, delayMilliseconds, 300000, e.UmbracoContext.Application),
new ScheduledPublishing(_publishingRunner, delayMilliseconds, 60000, e.UmbracoContext.Application, settings),
new ScheduledTasks(_tasksRunner, delayMilliseconds, 60000, e.UmbracoContext.Application, settings),
new LogScrubber(_scrubberRunner, delayMilliseconds, LogScrubber.GetLogScrubbingInterval(settings), e.UmbracoContext.Application, settings),
new LogScrubber(_scrubberRunner, delayMilliseconds, LogScrubber.GetLogScrubbingInterval(settings), e.UmbracoContext.Application, settings)
};
if (healthCheckConfig.NotificationSettings.Enabled)
@@ -118,8 +118,18 @@ namespace Umbraco.Web.Scheduling
_healthCheckRunner.TryAdd(tasks[4]);
}
OnInitializing(tasks);
return tasks.ToArray();
});
}
public static event EventHandler<List<IBackgroundTask>> Initializing;
private static void OnInitializing(List<IBackgroundTask> e)
{
var handler = Initializing;
if (handler != null) handler(null, e);
}
}
}