在不同的部署插槽中使用TimerTriggered Azure Webjob

时间:2020-09-28 11:44:39

标签: c# azure asp.net-core azure-webjobs

我有一个运行在5个不同部署插槽(Dev,UAT,登台,Prelive-1,Prelive-2)中的azure应用程序服务的网站,每个插槽都包含一个计时器触发的.NET Core 2.2中编写的azure webjob(正确放置)在App_Data中的正确位置)。每个Webjob都包含一个appsettings.json文件,该文件具有要命中的不同URL。

Webjob每5分钟运行一次,并从appsettings中命中url,但是当我检查azure见解(正确配置)中的日志时,我看到只有一个部署插槽正在运行(首次部署的90%)插槽-“ DEV”之一)。我想让所有的webjob在所有部署插槽中运行。

另一个问题,假设我重新启动任何部署插槽,例如Prelive-1然后立即执行webjob,5分钟后没有执行。

仍然可以使它们一次或一个接一个地运行,但是我只想让所有部署位置每5分钟运行一次webjob。

下面是我的Program.cs

public class Program
{
    public static async Task Main()
    {
        HostBuilder hostBuilder = new HostBuilder();
        hostBuilder.ConfigureWebJobs(builder =>
        {
            builder.AddAzureStorageCoreServices();
            builder.AddAzureStorage();
            builder.AddTimers();
        })
        .ConfigureAppConfiguration((hostContext, configurationBuilder) =>
        { 
            configurationBuilder.AddJsonFile($"appsettings.json", optional: false, reloadOnChange: false);
        })
        .ConfigureLogging((context, loggingBuilder) =>
        {
            string instrumentationKey = context.Configuration["APPINSIGHTS_INSTRUMENTATIONKEY"];
            if (!string.IsNullOrEmpty(instrumentationKey))
                loggingBuilder.AddApplicationInsightsWebJobs(logBuilder => logBuilder.InstrumentationKey = instrumentationKey);
        })
        .ConfigureServices(services =>
        {
            services.AddHttpClient();
        })
        .UseConsoleLifetime();



        using (var host = hostBuilder.Build())
        {
            await host.RunAsync();
        }
    }

Function.cs

public class Function1
{
    const string CheckPendingFulfillmentsUrlConfigKey = "CheckPendingFulfillmentsUrl";
    const string WebJobTimerExpression = "0 */5 * * * *";



    readonly IHttpClientFactory httpClientFactory;
    readonly ILogger<Function1> logger;
    readonly string CheckPendingFulfillmentsUrl;



    public Function1(IHttpClientFactory HttpClientFactory, ILogger<Function1> Logger, IConfiguration config)
    {
        httpClientFactory = HttpClientFactory;
        logger = Logger;
        CheckPendingFulfillmentsUrl = config[CheckPendingFulfillmentsUrlConfigKey];
    }



    public async Task TriggerCheckPendingFulfillments([TimerTrigger(WebJobTimerExpression, RunOnStartup = false)] TimerInfo timerInfo, CancellationToken cancellationToken)
    {
        using (var httpClient = httpClientFactory.CreateClient())
        {
            if (!string.IsNullOrEmpty(CheckPendingFulfillmentsUrl))
            {
                try
                {
                    Console.WriteLine("Calling the url " + CheckPendingFulfillmentsUrl);
                    await httpClient.GetAsync(CheckPendingFulfillmentsUrl);
                }
                catch(Exception Ex)
                {
                    Console.WriteLine("Error -- "+ Ex.Message);
                }
                logger.LogInformation(string.Format(Properties.Resources.Info_CheckPendingFulfillmentsTriggered, CheckPendingFulfillmentsUrl));
            }
        }
    }
}

2 个答案:

答案 0 :(得分:0)

创建新广告位时,您将获得一个新的App services(slot)

enter image description here

这意味着无论您创建多少个插槽,它们都将是独立的。 webjob的执行应彼此独立,并且都将运行。

这是我的Web应用产品版位。 enter image description here

创建一个名为Test1的新插槽。我相信执行webjob与TRAFFIC %无关。

这是我的test1插槽。

enter image description here

下面是我的Test1运行输出。

enter image description here

故障排除:

  1. 创建一个类似于我的测试代码的演示网络作业。

enter image description here

  1. 修改Settings.job文件。

enter image description here

  1. 检查日志。

Test1插槽。

enter image description here

Production插槽。

enter image description here

结论:

  1. 每个插槽都等同于全新的应用程序服务。

  2. webjob的执行不会互相干扰,而是会执行。 (不受流量百分比的干扰)

  3. 插槽的本质应用于在开发环境和生产环境之间进行切换以进行热部署。

  4. 如果要单独执行webjob或一起执行webjob,则可以通过配置文件或读取数据库值来执行它。

示例:

在webjob的配置文件中,当前Webjob的名称为test1。 其他的是test2test3

假设将时间触发的时间设置为1分钟,则可以每分钟读取一次数据库中名为Table_ExecutionSchedule的表。当程序读取诸如test1-start之类的特定指令时,该程序将执行特定的业务功能。否则,请跳过此触发条件。

答案 1 :(得分:0)

这可能是因为所有这些Webjob使用相同的存储空间。

来自documentation

在后台, TimerTrigger 使用WebJobs SDK的 Singleton 功能来确保 在任何给定时间仅运行触发函数的单个实例。 JobHost启动时,对于您的每个TimerTrigger功能,都会使用一个Blob租约(单例锁)。这种分散的锁确保了您的调度功能在任何时候都只在运行一个实例。如果当前未租用该函数的Blob,则该函数将获取租约并立即按计划开始运行。 如果无法获取Blob租约,通常意味着该功能的另一个实例正在运行,因此该功能不在当前主机中启动。这种情况下,主机将继续定期检查看看它能否获得租赁。这是一种“恢复”模式,以确保在稳定状态下运行时,如果一个实例发生故障,另一个实例会通知并在另一个实例停止的地方继续工作。

所以有两种可能性:

  • 具有单独的存储帐户:如果您在每个环境(dev / staging / prod)中都有一个存储帐户,则很有意义

  • 指定JobHostConfiguration类的HosId属性:

var config = new JobHostConfiguration();
config.HostId = "dev|staging|prod";
相关问题