gpt4 book ai didi

asp.net-web-api2 - 最大池大小忽略使用 Azure SQL 和 Azure AppServices

转载 作者:行者123 更新时间:2023-12-04 16:06:13 25 4
gpt4 key购买 nike

我在 ASP.NET Web API 项目(完整的 .NET Framework 4.6.1)中工作并使用 Azure SQL 数据库,API 部署在 Azure AppService 上。关于服务层,我们在 Azure SQL 数据库 (50 DTU) 的情况下使用 S2,在部署了 API 端点(1 个核心和 1.75 GB 的 RAM)的 AppService 的情况下使用 B1。目前我们正在使用 2 个实例(2 个带有负载均衡器的虚拟机)

我们的 QA 团队正在尝试找出平台在性能方面的容量。他们使用 JMeter 配置了一个性能测试,其中包括在 60 秒的时间间隔内启动 4000 个请求。

在第一次执行性能测试后,HTTP 500 错误的比例非常高,查看日志后,我们发现了很多这样的异常:

System.InvalidOperationException: Timeout expired.  The timeout period elapsed prior to obtaining a connection from the pool.  This may have occurred because all pooled connections were in use and max pool size was reached.
at System.Data.Common.ADP.ExceptionWithStackTrace(Exception e)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.<>c__DisplayClass4.<<ExecuteAsync>b__3>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.<ExecuteAsyncImplementation>d__9`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Data.Entity.Core.EntityClient.EntityConnection.<OpenAsync>d__8.MoveNext()

我首先想到的是连接泄漏问题,我们正在审查代码,并使用 sp_who2 命令监视 SQL Server 上的连接,但连接已按预期处理。

我们使用的注入(inject)容器在每次必须处理新请求时创建 Entity Framework 上下文(查询是异步的), Entity Framework 上下文在请求结束时自动处理(范围依赖)。

我们得出的结论是,我们需要增加连接池的大小,以缓解流量负载巨大的场景中的超时。

在互联网上快速搜索我发现 Max Pool Size 值的默认值为 100:

https://www.connectionstrings.com/all-sql-server-connection-string-keywords/

我决定将值增加到 400:
Server=tcp:XXXX.database.windows.net,1433;Initial Catalog=XXXX;Persist Security Info=False;User ID=XXXX;Password=XXXXXXXXXXXX;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Max Pool Size=400;

重复性能测试后,我们惊讶的是我们没有注意到任何改进,因为我们收到了相同比例的 HTTP 500 错误。我们得出的结论是最大池大小被忽略了。

接下来我们做的是在性能测试期间监控 SQL Server 以找出每个主机进程打开了多少 session ,此时我们为此使用了以下 SQL 语句:
SELECT        
COUNT(*) AS sessions,
host_name,
host_process_id,
program_name,
DB_NAME(database_id) AS database_name
FROM
sys.dm_exec_sessions AS s
WHERE
(is_user_process = 1) AND
(program_name = '.Net SqlClient Data Provider')
GROUP BY host_name, host_process_id, program_name, database_id
ORDER BY sessions DESC

在监控每个主机进程(部署 API 端点的虚拟机)打开的 session 后,我们发现每个虚拟机只创建了 128 个数据库 session 。

在这一点上,我想到了几个选项,它可以解释这种奇怪的行为:
  • 记住连接池是一个属于客户端的概念,我首先想到的是 IIS 应用程序池中的某种参数负责这种行为。
  • 另一种选择是每个主机进程和数据库登录只能打开 128 个 session 。我没有在互联网上找到任何指向此的内容.. 但在其他数据库(如 Oracle)中,可以配置此约束以限制每次登录打开的 session 数量。
  • 最后一个选项 .. 在一些博客和 stackoverflow 线程中,我读到了我们收到的异常(在从池中获取连接之前超时时间已过。这可能是因为所有池连接都在使用中并且最大池大小已达到)可能具有误导性,并且存在其他问题导致异常的可能性..

  • 快速解决方案是禁用连接字符串中的池,但这是我要做的最后一件事..

    另一种解决方案是扩展 AppService 以添加更多 VM 实例,但这在资金方面很昂贵..

    任何人都知道 Azure AppServices 中是否存在某种限制,这解释了为什么在启用连接池时只打开 128 个 session ?

    最佳答案

    连接池超时通常是症状而不是原因。如果您遇到了 120 maximum concurrent requests on S2 的约束,在数据库中抛出更多连接/查询不会提高吞吐量。 .您投入的其他工作将排队,包括新的连接请求。我不确定这是否会在实际达到最大大小之前导致连接池超时错误。

    JMeter 测试的构建方式可能会影响结果。出于容量测试的目的,请确保 QA 执行合理缓慢的提升,直到达到错误 SLA。您也可以尝试迁移到 S3 或更高版本,看看是否可以缓解连接问题。

    关于asp.net-web-api2 - 最大池大小忽略使用 Azure SQL 和 Azure AppServices,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48712764/

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