【问题标题】:Web Api 2 OWIN Selfhost handle multiple concurrent requestsWeb Api 2 OWIN Selfhost 处理多个并发请求
【发布时间】:2017-10-15 15:34:57
【问题描述】:

我有一个使用 OWIN 的自托管 Web api,但我似乎在并发连接上很吃力。当我使用 50 个并发 get 事件运行压力测试时,响应时间增加了很多,即使操作非常简单,在 uri 中键入 id 时返回 200 OK。

我如何让我的 web api OWIN 和 api 控制器根据请求同时运行??

这是我的项目示例:

启动类

public class Startup
{
    public void Configuration(IAppBuilder appBuilder)
    {
        try
        {
            appBuilder.UseWelcomePage("/welcome.html");
            appBuilder.UseErrorPage(new ErrorPageOptions
            {
                ShowExceptionDetails =
    #if DEBUG
                true
    #else
                false
    #endif
            });

            Debug.WriteLine($"Setting Web Api Configuration up...");
            var apiConfig = ConfigureWebApi();
            appBuilder.UseWebApi(new HttpServer(apiConfig));
            appBuilder.UseCors(CorsOptions.AllowAll);

            Debug.WriteLine($"Completed Web Api configuration.");
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"Failed to complete Web Api setup.", ex);
            throw;
        }
    }
}

控制器

public class TestController : ApiController
{
    public async Task<IHttpActionResult> Get(int id)
    {
        return Task<IHttpActionResult>.Factory.StartNew(() => {
            try
            {
                return Ok(id);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message, nameof(Get));
                return InternalServerError();
            }
        });
    }
}

我的web api控制台启动:

public static void Open()
{
    _webApp = WebApp.Start<Startup>(HostAddress);
    Console.WriteLine($"Host open -> {HostAddress}");
}

【问题讨论】:

  • 你的压力测试怎么样?你能发布那个代码吗?
  • 另外,您可以返回不太可能阻塞的Task.FromResult(Ok(Id)),而不是Factory.StartNew。不确定这是否会导致您的问题。
  • 使用 Paessler 的 Webserver Stress 工具执行压力测试。考虑创建一个简单的客户端,看看它是如何进行的。感谢 Task.FromResult 的提示。
  • 我认为您最好创建自己的测试客户端。我认为 Paessler 的工具不会正确测试 WebApi。它似乎更适用于传统的 HTML 网页。
  • 您使用线程只是为了返回 200。这是性能损失。你为什么这样做?您不需要在控制器中创建基于任务的方法。你没有做任何从多线程中受益的事情。

标签: c# asp.net-web-api asp.net-web-api2 owin owin-middleware


【解决方案1】:

您的所有 api 控制器方法将同时运行,显然受限于托管 api 的服务器的功能。这是 Web 服务器的功能,无论是 IIS 还是自托管。但是,您可以采取一些措施来帮助实现这一目标。

如果您始终保持一切异步,您将看到最佳性能。例如,如果您的控制器方法如下所示:

public async Task<IHttpActionResult> Get(int id)
{
    var testObject = await _repository.GetAsync(id);

    return Ok(testObject);
}

你有一个如下所示的存储库方法:

public async Task<TestObject> GetAsync(int id)
{
    using(var connection = new SqlConnection(_connectionString)
    {
        // using Dapper
        return await connection.QuerySingleAsync<TestObject>("sp_GetTestObject", new {Id = id}, commandType = CommandType.StoredProcedure);
    }
}

这样做允许计算机将工作线程用于数据库 I/O,从而释放处理能力来处理其他任务,例如接受对 API 端点的其他请求。像@StephenCleary 这样的人可能可以解释我所说的和/或纠正它。 @StephenCleary 的 blog 和书绝对值得一读以了解异步编程。

希望对您有所帮助。

【讨论】:

  • 谢谢,这正是我想要的。现在似乎运行得尽可能顺畅。
猜你喜欢
  • 1970-01-01
  • 2016-07-27
  • 2019-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多