You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ABP事务型工作单元压力测试失败问题求助

ABP事务工作单元并发压力测试异常问题

压力测试场景

并发调用以下API接口500次:

[UnitOfWork(IsDisabled = true)]
[AbpAllowAnonymous]
public async Task StressTest(string input)
{
    using (var uow = UnitOfWorkManager.Begin
        (
        new UnitOfWorkOptions
        {
            Scope = System.Transactions.TransactionScopeOption.RequiresNew,
            IsTransactional = true,
            IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted,
            AsyncFlowOption = System.Transactions.TransactionScopeAsyncFlowOption.Enabled
        })
        )
    {
        var data = await _userRepository.GetAll()
            .Where(x => x.EmailAddress == input)
            .Select(x => new { x.FirstName, x.CreationTime, x.IsDeleted })
            .AsNoTracking()
            .ToListAsync();

        await uow.CompleteAsync();
    }
}

依赖包版本与数据库

  • aspnetboilerplate v3.6.1
  • aspnetcore v2.2.0
  • entityframeworkcore v2.1.0
  • Azure SQL

问题概述

  • 整个应用无响应,所有涉及SQL的HTTP请求挂起直至超时
  • 使用非事务型工作单元(UoW)时测试正常通过
  • 该查询在非压力测试场景下仅需50ms即可完成
  • 问题在生产与本地环境均能复现
  • 所有监控资源均未达到上限
  • 审计功能已关闭

压力测试期间监控的资源

  • CPU利用率
  • 内存利用率
  • 完成线程(Completion Threads)
  • 工作线程(Worker Threads)
  • SQL会话
  • SQL工作进程
  • SQL CPU利用率
  • SQL锁
  • 出站端口

已尝试的解决方案

  • 使用ABP默认初始化的工作单元
  • 针对自定义控制器而非应用服务进行压力测试
  • 修改事务隔离级别(IsolationLevel)
  • 增加连接线程池的最小与最大线程数
  • 增加工作线程与完成线程的最小数量
  • 不调用工作单元的完成方法
  • 开启/关闭数据库连接池

预期ABP应能处理500次并发更新类HTTP请求,推测ABP内部事务管理存在严重问题,但缺乏有效调试手段。

补充说明1

不依赖ABP工作单元,手动开启事务时可顺利完成压力测试,排除Azure SQL与EF Core自身问题,确定问题源于ABP:

[UnitOfWork(IsDisabled = true)]
[AbpAllowAnonymous]
public async Task StressTest(string input)
{
    using (var tx = await _ctx.Database.BeginTransactionAsync(IsolationLevel.ReadCommitted))
    {
        var data = await _ctx.Users
                .Where(x => x.EmailAddress == input)
                .Select(x => new { x.FirstName, x.CreationTime, x.IsDeleted })
                .AsNoTracking()
                .ToListAsync();

        tx.Commit();
    }
}

补充说明2

监控数据库活跃事务时发现明显差异:手动开启事务时,事务会快速创建并关闭,无堆积;而ABP管理事务时,事务会在数据库中持续堆积直至达到连接池上限(例如最大连接数设为200时,会堆积200个事务)。

用于监控活跃事务的SQL查询:

SELECT [s_tst].[session_id],
[database_name] = DB_NAME (s_tdt.database_id),
[s_tdt].[database_transaction_begin_time], 
[sql_text] = [s_est].[text] 
FROM sys.dm_tran_database_transactions [s_tdt]
INNER JOIN sys.dm_tran_session_transactions [s_tst] ON [s_tst].transaction_id = [s_tdt].[transaction_id]
INNER JOIN sys.dm_exec_connections [s_ec] ON [s_ec].[session_id] = [s_tst].[session_id]
CROSS APPLY sys.dm_exec_sql_text ([s_ec].most_recent_sql_handle) AS [s_est];

内容的提问来源于stack exchange,提问作者Dani Mazahreh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 21:50:39