首页 > 解决方案 > ASP.NET Core 未同时响应所有请求 Http

问题描述

我是异步编程的新手,我做了一个非常简单的例子,每个请求都会执行一个select sleep (5)。这在我仅发出请求时效果很好,结果按预期在 5 秒内返回。但是当我同时执行 100 Request 时,它并没有按预期工作。ASP.NET Core 阻塞应用程序并一个接一个地返回响应,不会同时执行所有的Request。

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    [HttpGet("test1")]
    public async Task<string> test1()
    {
        using (MySqlConnection MySQLCon = new MySqlConnection("server=127.0.0.1;user id=user1;password=123456"))
        {
            await MySQLCon.OpenAsync();
            using (MySqlCommand MySQLCom = new MySqlCommand("Select sleep(5)", MySQLCon))
            {
                using (var read = await MySQLCom.ExecuteReaderAsync())
                {

                }
            }
        }
        return "ok";
    }
    [HttpGet("test2")]
    public async Task<string> test2()
    {
        await Task.Delay(5000);
        return "ok";
    }
}

这是正确的吗 ?异步编程不应该与此相反,并且能够同时处理多个请求而不会阻塞应用程序。

我正在使用 JavaScript 异步从 html 页面发出请求。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>    
</head>
<body style="margin: 0">
    <button onclick="execultar(1);">test1 (MySQL)</button>
    <button onclick="execultar(2);">test2 (Delay)</button>
    <br />
    <textarea id="log1" style="height: 80vh; width: 700px"></textarea>
    <script>
        function execultar(id_test) {
            var log1 = document.getElementById('log1');
            log1.value = '';
            var count = 0;
            function test1() {
                var start = new Date();
                var xhr = new XMLHttpRequest();
                xhr.onreadystatechange = function () {
                    if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
                        var end = new Date();
                        var duration = end - start;
                        count++;
                        log1.value +=
                            'test' + id_test.toString() + ' ' + 
                            xhr.responseText +
                            '\tcount:' + count.toString() + ' ' +
                            '\tstart:' + start.toLocaleTimeString() +
                            '\tend:' + end.toLocaleTimeString() +
                            '\tduration:' + duration + 'ms\r\n';
                    }
                }
                xhr.open('GET', '/api/values/test' + id_test.toString(), true);
                xhr.send(null);
            }
            for (var i = 0; i < 100; i++) {
                test1();
            }
        }        
    </script>
</body>
</html>

代码的目的是模拟 SQL 查询需要 5 秒的情况。这是我的大问题,当 ASP.NET Core 同时执行几个长 SQL 查询时,即使使用异步,应用程序也会被阻塞。我使用 Select sleep (5) 只是为了模拟一个冗长的查询。

在 test1 上,大多数请求的持续时间超过 5 秒。 在此处输入图像描述

在 test2 上,所有请求的时间都是 5 秒,如预期的那样。 在此处输入图像描述

标签: c#asp.net-core

解决方案


解决方案非常简单,但我对 Oracle 的 MySql.Data 库感到失望。因为看起来这个库并没有使用真正的异步函数,这会导致 ASP.NET Core 应用程序在 SQL 查询需要很长时间时完全阻塞。解决方案是将库更改为mysqlconnector,仅此而已,我的测试代码没有任何行被更改。现在该应用程序完全按预期工作。即使我同时执行 100 个请求,它们都按预期在 5 秒内结束。

这个链接https://bugs.mysql.com/bug.php?id=70111让我觉得 Oracle MySql.Data 库出了点问题,在阅读后我尝试使用其他库以获得快乐。


推荐阅读