Azure Function V3 依赖注入生命周期问题
Azure Function V3 Dependency Injection Lifetime Question
我正在使用 Azure Functions v3 和 DI。我有一个服务,我在 StartUp.cs 中设置了短暂的生命周期(使用:builder.Services.AddTransient<ICoreApiClient>(s => coreApiService);
),然后注入我的 Azure 函数 class。 Azure Function 是存储队列触发器函数。
我希望对于每条队列消息,我都会得到一个单独的“coreApiService”实例,但当多条消息同时放入队列时,我似乎共享一个实例。
我期望为每次调用或“运行”获得一个单独的实例是不正确的吗?
我 运行 遇到的问题是“_coreApiClient”似乎在 运行 方法的多次调用之间共享,因此当我在其中设置属性时(例如“客户 ID”或“API 密钥”等),我对一条消息有效并且应该保留该消息的处理随着它开始处理下一条消息而改变。
是我做错了还是我没有正确理解生命周期?
这是我的启动代码:
public class Startup: FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddLogging();
var loggingService = new HttpLoggingService(Environment.GetEnvironmentVariable("LoggingURL"), 0, "ABC.Integrations");
builder.Services.AddTransient<ILoggingService>(s => loggingService);
int CoreApiTimeout = 60; //Environment.GetEnvironmentVariable("CoreApiTimeout")
var coreApiService = new CoreApiClient(Environment.GetEnvironmentVariable("CoreApiKey"),string.Empty, CoreApiTimeout,Environment.GetEnvironmentVariable("CoreApiBaseUrl"));
builder.Services.AddTransient<ICoreApiClient>(s => coreApiService);
}
}
还有我的 Azure 函数 class:
public class TaskRouter
{
private readonly ICoreApiClient _coreApiClient;
private readonly ILoggingService _upgLogger;
private readonly ILogger<TaskRouter> _log;
public TaskRouter(ICoreApiClient coreApiClient, ILoggingService upgLogger, ILogger<TaskRouter> log)
{
_coreApiClient = coreApiClient;
_upgLogger = upgLogger;
_log = log;
}
[FunctionName("RouteTask")]
[ExponentialBackoffRetry(5, "00:00:04", "00:03:00")]
public async Task Run([QueueTrigger("task-scheduler", Connection = "")]
string queueItem)
{
//Call Appropriate Function to start task
var taskMsg = JsonConvert.DeserializeObject<TaskMessage>(queueItem);
_coreApiClient.SetId(taskMsg.TaskNumber);
//DO SOME WORK HERE
Console.Log(_coreApiClient.GetId); //Will be different b/c this was set by the next message
}
}
虽然客户端在容器中注册为瞬态,但它实际上是一个单例,因为在 Startup 中创建的实例是每次调用注入时唯一返回的实例 ICoreApiClient
.
将实例创建移动到工厂委托中,使其成为一个实际的临时注册,以便每次 ICoreApiClient
必须从服务提供商那里解析时都会初始化一个新实例。
//...
builder.Services.AddTransient<ICoreApiClient>(s =>
new CoreApiClient(Environment.GetEnvironmentVariable("CoreApiKey"), string.Empty, CoreApiTimeout, Environment.GetEnvironmentVariable("CoreApiBaseUrl"))
);
//...
我正在使用 Azure Functions v3 和 DI。我有一个服务,我在 StartUp.cs 中设置了短暂的生命周期(使用:builder.Services.AddTransient<ICoreApiClient>(s => coreApiService);
),然后注入我的 Azure 函数 class。 Azure Function 是存储队列触发器函数。
我希望对于每条队列消息,我都会得到一个单独的“coreApiService”实例,但当多条消息同时放入队列时,我似乎共享一个实例。
我期望为每次调用或“运行”获得一个单独的实例是不正确的吗? 我 运行 遇到的问题是“_coreApiClient”似乎在 运行 方法的多次调用之间共享,因此当我在其中设置属性时(例如“客户 ID”或“API 密钥”等),我对一条消息有效并且应该保留该消息的处理随着它开始处理下一条消息而改变。
是我做错了还是我没有正确理解生命周期?
这是我的启动代码:
public class Startup: FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddLogging();
var loggingService = new HttpLoggingService(Environment.GetEnvironmentVariable("LoggingURL"), 0, "ABC.Integrations");
builder.Services.AddTransient<ILoggingService>(s => loggingService);
int CoreApiTimeout = 60; //Environment.GetEnvironmentVariable("CoreApiTimeout")
var coreApiService = new CoreApiClient(Environment.GetEnvironmentVariable("CoreApiKey"),string.Empty, CoreApiTimeout,Environment.GetEnvironmentVariable("CoreApiBaseUrl"));
builder.Services.AddTransient<ICoreApiClient>(s => coreApiService);
}
}
还有我的 Azure 函数 class:
public class TaskRouter
{
private readonly ICoreApiClient _coreApiClient;
private readonly ILoggingService _upgLogger;
private readonly ILogger<TaskRouter> _log;
public TaskRouter(ICoreApiClient coreApiClient, ILoggingService upgLogger, ILogger<TaskRouter> log)
{
_coreApiClient = coreApiClient;
_upgLogger = upgLogger;
_log = log;
}
[FunctionName("RouteTask")]
[ExponentialBackoffRetry(5, "00:00:04", "00:03:00")]
public async Task Run([QueueTrigger("task-scheduler", Connection = "")]
string queueItem)
{
//Call Appropriate Function to start task
var taskMsg = JsonConvert.DeserializeObject<TaskMessage>(queueItem);
_coreApiClient.SetId(taskMsg.TaskNumber);
//DO SOME WORK HERE
Console.Log(_coreApiClient.GetId); //Will be different b/c this was set by the next message
}
}
虽然客户端在容器中注册为瞬态,但它实际上是一个单例,因为在 Startup 中创建的实例是每次调用注入时唯一返回的实例 ICoreApiClient
.
将实例创建移动到工厂委托中,使其成为一个实际的临时注册,以便每次 ICoreApiClient
必须从服务提供商那里解析时都会初始化一个新实例。
//...
builder.Services.AddTransient<ICoreApiClient>(s =>
new CoreApiClient(Environment.GetEnvironmentVariable("CoreApiKey"), string.Empty, CoreApiTimeout, Environment.GetEnvironmentVariable("CoreApiBaseUrl"))
);
//...