旧的做事方式看起来如此:
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
中的那个
其次,更重要的是,我在哪里指定blob存储连接字符串?在上面的例子中,它是存储在cfg.DocumentDatabase.BlobStorageServer
中的设置
谢谢
官方样本可在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();
所以,在盯着webjob SDK的源代码后,我找到了一个kludge。好吧,我认为这是一个混乱。它工作,我现在可以使用新的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)));
webjobs SDK专门寻找名为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方法的ZERO文档。
在WebSDK 3中,作业是通过appsettings.json
文件配置的,就像它对ASP.NET Core一样。
你可以看到一个例子on the official Github repo,但我还将在下面添加一个更完整的例子。
在appsettings.development.json
中,通过ConnectionStrings["AzureWebJobsStorage"]
属性将其配置为使用本地存储:
{
"ConnectionStrings": {
"AzureWebJobsDashboard": "UseDevelopmentStorage=true",
"AzureWebJobsStorage": "UseDevelopmentStorage=true"
}
}
在appsettings.json
中,将其配置为prod:
{
"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();
}
}
}
万一有人遇到与使用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}"];
}
}