gpt4 book ai didi

azure - .net 7 隔离的 Azure 函数依赖注入(inject)在部署时失败(在本地工作)

转载 作者:行者123 更新时间:2023-12-03 06:07:45 28 4
gpt4 key购买 nike

编辑::已使用显示实际服务的扩展方法更新了代码片段

我有一个Web api项目和一个独立的函数项目。两者几乎都使用相同的 DI,以至于我为 DI 加载提取了一些扩展方法。

我的函数是由服务总线消息触发的。如果我在本地调试并向总线发送消息,我可以 100% 处理它。如果我部署该函数然后向总线发送消息,那么它会因 DependencyInjection 错误而终止,无法实例化我的类。

这是我的消息监听函数。

    public class ProcessingAnalyseDocumentsConsumer {

private readonly ILogger<ProcessingAnalyseDocumentsConsumer> _logger;
private readonly FormRecogniserService _formRecogniserService;
private readonly ReprocessEncounterService _reprocessEncounterService;
private readonly DataContext _context;

public ProcessingAnalyseDocumentsConsumer(
ILogger<ProcessingAnalyseDocumentsConsumer> logger,
FormRecogniserService formRecogniserService,
ReprocessEncounterService reprocessEncounterService,
DataContext context) {
_logger = logger;
_formRecogniserService = formRecogniserService;
_reprocessEncounterService = reprocessEncounterService;
_context = context;
}

[Function("ProcessingAnalyseDocumentsConsumer")]
public async Task RunAsync(
[ServiceBusTrigger(Constants.QUEUES_PROCESSING_ANALYSIS_DOCUMENTS, Connection = "ServiceBusConnection")]
ReprocessSingleDoc message) {

_logger.LogInformation($"C# ServiceBus queue trigger function processed message: {JsonConvert.SerializeObject(message)}");

var item = _context.LocationCities.FirstOrDefault();
_logger.LogInformation($"Found item in db: {JsonConvert.SerializeObject(item)}");

}
}

我的函数的 Program.cs 如下所示

    var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.ConfigureServices(async (hostContext, services) => {
var configuration = hostContext.Configuration;
var connectionString = configuration["DefaultConnection"];
var env = hostContext.HostingEnvironment;

services.AddDbContext<DataContext>(dbContextOptions =>
dbContextOptions
.UseLazyLoadingProxies()
.UseSqlServer(
connectionString,
b => b.MigrationsAssembly("WEBAPIPROJECTASSEMBLY"))
);

if (!env.IsDevelopment()) {

services.AddAzureClients(azureClientFactoryBuilder => {
azureClientFactoryBuilder.AddSecretClient(configuration.GetSection("KeyVault"));
});

Console.WriteLine("adding azure vault");
services.AddSingleton<IKeyVaultService, KeyVaultService>();
}
else {
Console.WriteLine("adding debug vault");
services.AddSingleton<IKeyVaultService, DebugKeyVaultService>();
}

await services.AddSensitiveServicesAsync(); //extension methods to add services
services.AddHttpContextAccessor(); //make http context available
services.ServiceDependencies(); //extension methods to add services
});

await host.Build().RunAsync();

以下是正在调用的扩展方法。

    public static async Task<IServiceCollection> AddSensitiveServicesAsync(this IServiceCollection services) {

var serviceProvider = services.BuildServiceProvider();
var keyVault = serviceProvider.GetService<IKeyVaultService>();

if (keyVault == null) {
throw new NullReferenceException(nameof(keyVault));
}

await services.AddBlobStorage(keyVault);
await services.AddFormRecogniserService(keyVault);
return services;
}

public static async Task<IServiceCollection> AddBlobStorage(
this IServiceCollection services,
IKeyVaultService keyVault) {

var blobStorageConnectionString = await keyVault.GetSecret("blob-storage-connection");
services.AddTransient(t => new BlobStorageService(blobStorageConnectionString));
return services;
}

public static async Task<IServiceCollection> AddFormRecogniserService(
this IServiceCollection services,
IKeyVaultService keyVault) {

var secret_key = await keyVault.GetSecret("form-recogniser-key");
var secret_endpoint = await keyVault.GetSecret("form-recogniser-endpoint");

var serviceProvider = services.BuildServiceProvider();
var blobStorage = serviceProvider.GetService<BlobStorageService>();

if (blobStorage == null) {
throw new NullReferenceException(nameof(blobStorage));
}

services.AddTransient(t => new FormRecogniserService(secret_key, secret_endpoint, blobStorage));
return services;
}

唯一复杂的事情是我创建了一个用于调试的调试 keystore 并进行了环境切换 - 但这在本地有效,当我删除它时 - 一切仍然中断。我的 blob 存储服务和表单识别器服务也是使用从 keyvault 检索到的 secret 构建的,因此它们是异步的。但我认为这不会引起任何问题 - 它在本地和我的其他项目中都有效。

无论我注入(inject)的第一个自定义服务是什么,Azure 上的依赖注入(inject)总是失败。我改变了服务,调换了它们等等,无论我要求什么,它都没有启动。如果我从构造函数中删除任何自定义服务并只保留记录器,一切都会正常工作。调试时,自定义服务在本地 webapi 项目、azure 以及本地函数项目中 100% 工作。

Result: Failure Exception: System.InvalidOperationException: Unable to resolve service for type 'medimore_azure.FormRecogniserService' while attempting to activate 'medimore_azure_functions.Messaging.ProcessingAnalyseDocumentsConsumer'. at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider) at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters) at Microsoft.Azure.Functions.Worker.DefaultFunctionActivator.CreateInstance(Type instanceType, FunctionContext context) in D:\a_work\1\s\src\DotNetWorker.Core\Invocation\DefaultFunctionActivator.cs:line 23 at Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionInvoker2.CreateInstance(FunctionContext context) in D:\a\_work\1\s\src\DotNetWorker.Core\Invocation\DefaultFunctionInvoker.cs:line 26 at Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor.ExecuteAsync(FunctionContext context) in D:\a\_work\1\s\src\DotNetWorker.Core\Invocation\DefaultFunctionExecutor.cs:line 30 at Microsoft.Azure.Functions.Worker.OutputBindings.OutputBindingsMiddleware.Invoke(FunctionContext context, FunctionExecutionDelegate next) in D:\a\_work\1\s\src\DotNetWorker.Core\OutputBindings\OutputBindingsMiddleware.cs:line 13 at Microsoft.Azure.Functions.Worker.FunctionsApplication.InvokeFunctionAsync(FunctionContext context) in D:\a\_work\1\s\src\DotNetWorker.Core\FunctionsApplication.cs:line 77 at Microsoft.Azure.Functions.Worker.Handlers.InvocationHandler.InvokeAsync(InvocationRequest request) in D:\a\_work\1\s\src\DotNetWorker.Grpc\Handlers\InvocationHandler.cs:line 88 Stack: at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider) at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters) at Microsoft.Azure.Functions.Worker.DefaultFunctionActivator.CreateInstance(Type instanceType, FunctionContext context) in D:\a\_work\1\s\src\DotNetWorker.Core\Invocation\DefaultFunctionActivator.cs:line 23 at Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionInvoker2.CreateInstance(FunctionContext context) in D:\a_work\1\s\src\DotNetWorker.Core\Invocation\DefaultFunctionInvoker.cs:line 26 at Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor.ExecuteAsync(FunctionContext context) in D:\a_work\1\s\src\DotNetWorker.Core\Invocation\DefaultFunctionExecutor.cs:line 30 at Microsoft.Azure.Functions.Worker.OutputBindings.OutputBindingsMiddleware.Invoke(FunctionContext context, FunctionExecutionDelegate next) in D:\a_work\1\s\src\DotNetWorker.Core\OutputBindings\OutputBindingsMiddleware.cs:line 13 at Microsoft.Azure.Functions.Worker.FunctionsApplication.InvokeFunctionAsync(FunctionContext context) in D:\a_work\1\s\src\DotNetWorker.Core\FunctionsApplication.cs:line 77 at Microsoft.Azure.Functions.Worker.Handlers.InvocationHandler.InvokeAsync(InvocationRequest request) in D:\a_work\1\s\src\DotNetWorker.Grpc\Handlers\InvocationHandler.cs:line 88

最佳答案

正如 @Steven 所说,“在配置容器的过程中调用 BuildServiceProvider 通常不是一个好主意”。它可以在本地运行,但在部署时会崩溃。重构了很多配置部分,因为我删除了 BuildServiceProvider 调用,所以它按预期工作。

关于azure - .net 7 隔离的 Azure 函数依赖注入(inject)在部署时失败(在本地工作),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77151093/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com