Azure WebJobs SDK 3, пытающийся добавить BlobTrigger и связанную строку подключения - PullRequest
0 голосов
/ 06 ноября 2018

Старый способ ведения дел выглядел так:

        var jobConfig = new JobHostConfiguration(cfg.DocumentDatabase.BlobStorageServer)
        {
            NameResolver = new Support.BlobNameResolver(_env)
        };
        jobConfig.Queues.MaxPollingInterval = TimeSpan.FromSeconds(_pollSeconds);

        _wjHost = new JobHost(jobConfig);

Я пытаюсь перевести это на новый путь в 3.0, и вот как далеко я продвинулся:

        _wjHost = new HostBuilder().ConfigureWebJobs(b =>
        {
            b.AddAzureStorage(x =>
            {
                x.MaxPollingInterval = TimeSpan.FromSeconds(_pollSeconds);
            });
        }).ConfigureServices(s =>
        {
            s.AddSingleton<INameResolver, Support.BlobNameResolver>(_ => new Support.BlobNameResolver(_env));
            s.Configure<QueuesOptions>(o =>
            {
                o.MaxPollingInterval = TimeSpan.FromSeconds(_pollSeconds);
            });
        }).Build();

Во-первых, я не знаю, какой MaxPollingInterval подходит для использования ... поэтому я установил оба. Я предполагаю, что не должен использовать тот в AddBlobStorage

Во-вторых, и что более важно, где я могу указать строку подключения к хранилищу больших двоичных объектов? В приведенном выше случае эта настройка сохраняется в cfg.DocumentDatabase.BlobStorageServer

Спасибо

Ответы [ 4 ]

0 голосов
/ 12 апреля 2019

На всякий случай, если кто-то попал в ту же ситуацию, с которой я столкнулся при разрешении имени очереди при использовании QueueTrigger:

Вы должны использовать пакет «Microsoft.Extensions.DependencyInjection» для работы приведенного ниже кода.

static void Main(string[] args)
    {
        var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
        Console.WriteLine($"Current Environment : {(string.IsNullOrEmpty(environment) ? "Development" : environment)}");

        var config = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{environment}.json", optional: true, reloadOnChange: true)
            .AddEnvironmentVariables()
            .Build();

        var builder = new HostBuilder();
        builder.UseEnvironment("Development");
        builder.ConfigureLogging((context, b) =>
        {
            b.AddConsole();
        });

        builder.ConfigureWebJobs(b =>
        {

            b.AddAzureStorageCoreServices();
            b.AddAzureStorage();
            // b.AddTimers();

            b.AddServiceBus(c =>
            {
                c.ConnectionString = "[Your Connection String]";
            });
        }).ConfigureServices((context, services)=>
        {
            services.AddSingleton<INameResolver>(new QueueNameResolver(config));
        });

        var host = builder.Build();


        using (host)
        {
            host.Run();
        }
    }

public class QueueNameResolver : INameResolver
{
    private readonly IConfiguration _configuration;
    public QueueNameResolver(IConfiguration configuration)
    {
        _configuration = configuration;
    }
    public string Resolve(string name)
    {
        return _configuration[$"AppSettings:{name}"];
    }
}
0 голосов
/ 21 ноября 2018

Официальный образец доступен на WebJob Github

В своих функциях вы можете передать имя ключа строки подключения, используемого в appsettings.json

например:

public void ProcessBlob([BlobTrigger("blobPath", Connection = "AzureWebJobsBlobConnection")] string blob)

«AzureWebJobsBlobConnection» настраивается в appsettings.json следующим образом: { "Logging": { ... }, "AzureWebJobsBlobConnection": "...", }

И не забудьте добавить конфигурацию в program.cs:

var builder = new HostBuilder()
            .ConfigureAppConfiguration((builderContext, cb) =>
            {
                IHostingEnvironment env = builderContext.HostingEnvironment;

                cb.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
            })
            .ConfigureWebJobs(b =>
            {
                b.AddAzureStorage(o => 
                {
                    o.MaxDequeueCount = 1;
                })
                .AddServiceBus(c =>
                {
                    c.MessageHandlerOptions.MaxConcurrentCalls = 1;
                });
            })
            .ConfigureLogging((webHostBuilder, loggingBuilder) =>
            {
                loggingBuilder.AddConsole();
                loggingBuilder.AddDebug();
            })
            .ConfigureServices((hb, sc) =>
            {
                string connectionString = hb.Configuration.GetConnectionString("DefaultConnection");

                sc.AddScoped<Functions, Functions>();
                ...
            });

        builder.RunConsoleAsync().GetAwaiter().GetResult();
0 голосов
/ 15 января 2019

В WebSDK 3 задание настраивается с помощью файла appsettings.json, так же, как это делается для ASP.NET Core.

Вы можете увидеть пример на официальном репозитории Github , но я также добавлю более полный пример ниже.

В appsettings.development.json настройте его для использования локального хранилища через свойство ConnectionStrings["AzureWebJobsStorage"]:

{
  "ConnectionStrings": {
    "AzureWebJobsDashboard": "UseDevelopmentStorage=true",
    "AzureWebJobsStorage": "UseDevelopmentStorage=true"
  }
}

А в appsettings.json настройте его для прод:

{
  "ConnectionStrings": {
    "AzureWebJobsDashboard": "DefaultEndpointsProtocol=https;AccountName=name;AccountKey=key",
    "AzureWebJobsStorage": "DefaultEndpointsProtocol=https;AccountName=name;AccountKey=key"
  }
}

Моя полная Program.cs выглядит так (с комментариями):

public class Program
{
    public static async Task Main(string[] args)
    {
        var builder = new HostBuilder();

        // allows us to read the configuration file from current directory
        // (remember to copy those files to the OutputDirectory in VS)
        builder.UseContentRoot(Directory.GetCurrentDirectory());

        // configure things like batch size, service bus, etc..
        builder.ConfigureWebJobs(b =>
        {
            b
            .AddAzureStorageCoreServices()
            .AddAzureStorage(options =>
            {
                options.BatchSize = 1;
                options.MaxDequeueCount = 1;
            })
            ;
        });

        // this step allows the env variable to be read BEFORE the rest of the configuration
        // => this is useful to configure the hosting environment in debug, by setting the 
        // ENVIRONMENT variable in VS
        builder.ConfigureHostConfiguration(config =>
        {
            config.AddEnvironmentVariables();
        });

        // reads the configuration from json file
        builder.ConfigureAppConfiguration((context, config) =>
        {
            var env = context.HostingEnvironment;

            // Adding command line as a configuration source
            config
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);

            config.AddEnvironmentVariables();
            if (args != null)
                config.AddCommandLine(args);
        });

        // configure logging (you can use the config here, via context.Configuration)
        builder.ConfigureLogging((context, loggingBuilder) =>
        {
            loggingBuilder.AddConfiguration(context.Configuration.GetSection("Logging"));
            loggingBuilder.AddConsole();

            // If this key exists in any config, use it to enable App Insights
            var appInsightsKey = context.Configuration["APPINSIGHTS_INSTRUMENTATIONKEY"];
            if (!string.IsNullOrEmpty(appInsightsKey))
            {
                loggingBuilder.AddApplicationInsights(o => o.InstrumentationKey = appInsightsKey);
            }
        });

        // inject dependencies via DI
        builder.ConfigureServices((context, services) =>
        {
            services.AddSingleton<INameResolver>(new QueueNameResolver("test"));

            services.AddDbContextPool<DbContext>(options =>
                options.UseSqlServer(context.Configuration.GetConnectionString("DbContext"))
            );
        });

        // finalize host config
        builder.UseConsoleLifetime();

        var host = builder.Build();
        using (host)
        {
            await host.RunAsync();
        }
    }
}
0 голосов
/ 06 ноября 2018

Итак, посмотрев на исходный код SDK для веб-задания, я нашел клудж. Ну, я думаю, что это клудж. Это работает, и теперь я могу использовать новый 3.0 SDK.

Я публикую это здесь, в основном потому, что боюсь, что нет другого способа сделать это, используя мои собственные файлы конфигурации.

Если это не так, пожалуйста, дайте мне знать, и я удалю этот ответ.

Итак, мой код теперь выглядит так:

    _wjHost = new HostBuilder().ConfigureWebJobs(b =>
    {
        b.AddAzureStorage(x =>
        {
            x.MaxPollingInterval = TimeSpan.FromSeconds(_pollSeconds);
        });
    }).ConfigureServices(s =>
    {
        s.AddSingleton(new StorageAccountProvider(new BlobStorageConfiguration(cfg.DocumentDatabase.BlobStorageServer)));
        s.AddSingleton<INameResolver, Support.BlobNameResolver>(_ => new Support.BlobNameResolver(_env));
        s.Configure<QueuesOptions>(o =>
        {
            o.MaxPollingInterval = TimeSpan.FromSeconds(_pollSeconds);
        });
    }).Build();

Строка, которую я добавил, была s.AddSingleton(new StorageAccountProvider(new BlobStorageConfiguration(cfg.DocumentDatabase.BlobStorageServer)));

SDK webjobs специально ищет ключ с именем Storage. Поэтому я должен был реализовать IConfiguration и сделать это следующим образом:

private sealed class BlobStorageConfiguration : IConfiguration
{
    private readonly string _bsConnString;
    public BlobStorageConfiguration(string connString)
    {
        _bsConnString = connString;
    }

    public string this[string key]
    {
        get => key == "Storage" ? _bsConnString : null;
        set { }
    }

    public IEnumerable<IConfigurationSection> GetChildren() => null;
    public IChangeToken GetReloadToken() => null;
    public IConfigurationSection GetSection(string key) => null;
}

и теперь курок срабатывает просто отлично. Не красиво Но есть нулевая документация по новым методам IHost.

...