【问题标题】:Azure Function V3 Dependency Injection Lifetime QuestionAzure Function V3 依赖注入生命周期问题
【发布时间】:2021-05-30 09:42:09
【问题描述】:

我正在使用 Azure Functions v3 和 DI。我在 StartUp.cs 中设置了一个具有短暂生命周期的服务(使用:builder.Services.AddTransient<ICoreApiClient>(s => coreApiService);),然后注入到我的 Azure Function 类中。 Azure Function 是一个存储队列触发函数。

我希望对于每条队列消息,我都会获得一个单独的“coreApiService”实例,但当多条消息同时放入队列时,我似乎共享一个实例。

我期望为每个调用或“运行”获得一个单独的实例是否不正确? 我遇到的问题是“_coreApiClient”似乎在 Run 方法的多个调用之间共享,因此我在其中设置了我有效的属性(如“客户 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 Function 类:

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
        }
   }

【问题讨论】:

    标签: dependency-injection azure-functions azure-function-app


    【解决方案1】:

    尽管客户端在容器中注册为瞬态,但它实际上是一个单例,因为在 Startup 中创建的实例是每次调用注入 ICoreApiClient 时唯一返回的实例。

    将实例创建移到工厂委托中,使其成为实际的临时注册,以便每次必须从服务提供者解析ICoreApiClient 时都会初始化一个新实例。

    //...
    
    builder.Services.AddTransient<ICoreApiClient>(s => 
        new CoreApiClient(Environment.GetEnvironmentVariable("CoreApiKey"), string.Empty, CoreApiTimeout, Environment.GetEnvironmentVariable("CoreApiBaseUrl"))
    );
    
    //...
    

    【讨论】:

    • 啊,非常感谢 - 这就是问题所在。非常合乎逻辑,事后看来很明显,但我看了几个小时并没有意识到这一点。谢谢!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-07
    • 2017-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多