异步控件是否应始终在 MVC 中用于数据访问

Should async controlles always used in MVC for data access

ERP+购物车ASP.NET MVC 4.8 应用程序计划迁移到 .NET 5 MVC Core 应用程序。 Entity Framework 计划使用带有 NpgSql 数据提供程序的核心。

MVC 4.8 应用程序不使用任何异步方法。

.NET 5 中有用于数据访问的异步方法,例如 ToListAsync()、ExecuteSqlInterpolatedAsync()。

Core MVC 控制器示例return 异步任务如

    [HttpPost]
    public async Task<IActionResult> LogOn(LogOnModel model, string returnUrl,
        [FromServices] ShoppingCart shoppingcart
        )

将有 100 个人类用户。 应用程序还具有 Web API 通过 http 提供 json 数据。购物车部分允许匿名访问并被搜索引擎扫描。

Ngpsql 支持连接池,因此会自动添加多个连接。 应用程序托管在 Debian Linux VPS 使用 Apache 的 4 核服务器中。

VSP 有 20 GB 的 RAM,因此 Linux 缓存了大量数据。然而,可能大部分时间仍然消耗在从 Postgres 数据库读取数据上。 大多数控制器读写数据 to/from 数据库。

回答

https://forums.asp.net/t/2136711.aspx?Should+I+always+prefer+async+actions+over+sync+actions+

建议始终使用异步方法进行数据访问。

回答 Always using Async in an ASP.NET MVC Controller

建议不要总是使用异步。

来自https://gokhansengun.com/asp-net-mvc-and-web-api-comparison-of-async-or-sync-actions/ 的结论

However async actions do not come with zero cost, writing async code requires more care, proficiency and it has its own challenges.

应用程序和数据库在同一 VPS 服务器中

回答

mvc should everything be async

说明如果应用程序和数据库在同一台服务器上,则不应使用异步。

回答

I'd say it's good to use it everywhere you're doing I/O.

但之后:

If you're talking about ASP.NET MVC with a single database backend, then you're (almost certainly) not going to get any scalability benefit from async. This is because IIS can handle far more concurrent requests than a single instance of SQL server (or other classic RDBMS)

在我的案例中有两个升级路径:

  1. 继续只使用同步方法。不要在异步上浪费资源。可以使用现有的经过测试的 MVC 控制器代码。 kestrel 中的线程数没有限制。假设将来 .NET 编译器通过分析应用程序创建异步代码,手动异步将变得过时。

  2. 将 MVC 控制器签名更改为

    public 异步任务

    用异步调用替换所有 EF 数据访问调用。假设这是仍然存在的可靠 .NET 功能。重构代码,以便更改后不会出现 Visual Studio 2019 警告。在我的应用程序发布后,这允许优化现有代码而无需大量重写。

在这种情况下应该使用哪个升级路径? 将所有内容更改为异步会在代码中引入新错误吗?

异步对于 Web 应用程序不是强制性的。它大部分仅对 GUI 是强制性的。

您的应用程序将继续工作。异步编程非常擅长处理 scale 的请求。但是你说你最多有 100 个用户。如果他们是 100.000,您的应用程序将遭受很多损失。

而且我可以肯定地说 async 编程确实会带来挑战,因为例如,如果您处理不当,交易就会出现问题。

当然线程也是有代价的。异步的存在是为了避免每个线程所需的 500KB 开销。这意味着机器 运行 应用程序可能需要垂直扩展。从这个意义上说,异步节省了 RAM。

选择权在你。由于您无论如何都在重构您的应用程序,因此您可以努力改进它以进行下一步,并为更大的规模做好准备。

否则您的应用程序仍然可以为 100 个用户正常工作。

[编辑] pull request 相当于 1000 字。在异步上下文中,事务应该用 TransactionScopeAsyncFlowOption.Enabled 初始化以避免描述的异常,并告诉事务引擎线程正在参与异步流。为了简单起见,异步流共享同一个线程,因此应用程序代码(事务管理是 C# 代码)不得依赖线程本地信息并且每次都必须清理上下文上下文 切换到另一个请求关注的异步流。

结论:您的第一条评论是正确的。异步流显着降低 并发 请求的 RAM 利用率。