Azure Functions高负载下DryIOC超时:调整超时与获取异常详情
问题
我的Azure Functions在低负载下运行正常,但高负载时频繁触发DryIOC超时(非必现),异常信息如下:
---> Microsoft.Azure.WebJobs.Script.Workers.Rpc.RpcException: Result: Failure Exception: DryIoc.ContainerException: code: Error.WaitForScopedServiceIsCreatedTimeoutExpired; message: DryIOC等待"另一方"创建作用域或单例服务已达3000个时间周期仍未完成。 您可以调用`exception.TryGetDetails(container)`获取有问题的服务注册详情。 该错误意味着:要么"另一方"是已启动但无法在指定时间内完成服务创建的并行线程; 更可能的情况是"另一方"为同一线程,存在未检测到的递归依赖, 或者作用域服务创建时抛出异常但被捕获,而您又尝试再次解析该失败的服务。 出于上述原因,DryIOC设置了超时以防止无限等待。 您可以通过`Scope.WaitForScopedServiceIsCreatedTimeoutTicks=NewNumberOfTicks`修改默认超时时间 ...(省略后续栈信息)
一、延长DryIOC超时时间
DryIOC的默认超时由Scope.WaitForScopedServiceIsCreatedTimeoutTicks控制,单位为时钟周期(Tick),1毫秒等于10000个Tick。默认值对应300毫秒左右,高负载下可适当调大:
在Azure Functions Worker的启动配置(Program.cs)中修改:
using DryIoc; using Microsoft.Azure.Functions.Worker; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; var host = new HostBuilder() .ConfigureFunctionsWorkerDefaults(builder => { // 添加全局异常中间件(可选,用于后续捕获详情) builder.UseMiddleware<ExceptionHandlingMiddleware>(); }) .ConfigureServices(services => { // 配置完成后获取DryIOC容器实例 services.PostConfigure<IContainer>(container => { // 设置超时为10秒(转换为Tick) container.ScopeContext.WaitForScopedServiceIsCreatedTimeoutTicks = TimeSpan.FromSeconds(10).Ticks; }); }) .Build(); host.Run();
二、获取问题服务注册详情
通过TryGetDetails方法可获取导致超时的服务依赖链信息,需在捕获DryIoc.ContainerException时调用:
- 添加全局异常处理中间件
创建中间类捕获并处理异常:
using DryIoc; using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Middleware; using Microsoft.Extensions.Logging; public class ExceptionHandlingMiddleware : IFunctionsWorkerMiddleware { private readonly ILogger<ExceptionHandlingMiddleware> _logger; private readonly IContainer _container; public ExceptionHandlingMiddleware(ILogger<ExceptionHandlingMiddleware> logger, IContainer container) { _logger = logger; _container = container; } public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next) { try { await next(context); } catch (ContainerException ex) when (ex.Error == Error.WaitForScopedServiceIsCreatedTimeoutExpired) { // 获取服务注册详情 var details = ex.TryGetDetails(_container); _logger.LogError(ex, "DryIOC超时问题详情:\n{Details}", details); throw; // 保留原异常抛出,或根据需求处理 } } }
- 详情说明
TryGetDetails返回的内容包含:
- 超时服务的类型
- 完整的依赖注入链
- 服务注册的生命周期类型(单例/作用域/瞬态)
这些信息可直接定位递归依赖、服务创建缓慢或失败的根本原因。
内容的提问来源于stack exchange,提问作者Robert25
相关产品推荐
相关产品推荐

