gpt4 book ai didi

asp.net - 无法配置IIS/Asp.NET来同时处理许多异步请求

转载 作者:行者123 更新时间:2023-12-02 13:46:10 25 4
gpt4 key购买 nike

我正在尝试探索异步ASP.NET请求。 Asp.NET应用程序由IIS 8托管。

客户端使用以下代码发出许多POST请求:

private static async Task<Result> IOAsync(Uri url, byte[] body)
{
var webClient = new WebClient();
webClient.Headers["Content-Type"] = "application/json";
return DeserializeFromBytes(await webClient.UploadDataTaskAsync(url, "POST", body));
}

private static Result DeserializeFromBytes(byte[] bytes)
{
using (var jsonTextReader = new JsonTextReader(new StreamReader(new MemoryStream(bytes))))
{
return new JsonSerializer().Deserialize<Result>(jsonTextReader);
}
}


另一端的Asp.NET代码是由VS 2013新建项目向导创建的Asp.NET Web应用程序,在 HomeController中稍作修改:

public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}

public ActionResult About()
{
ViewBag.Message = "Your application description page.";

return View();
}

public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";

return View();
}

[System.Web.Mvc.HttpPost]
public async Task<JsonResult> SampleAPIAsync([FromBody] BaseContext c, Runner.BasicIOStrategy strategy)
{
return Json(await ((IAsyncRunner)Runner.Create((Runner.IOStrategy)strategy)).IOAsync(c));
}
}


SampleAPIAsync旨在探索执行数据库IO的不同方法,其中只有一种是真正异步的,其余的方法用于证明人们对使用 Task.Run进行“模拟”和类似操作的常见误解。

在我的特定情况下, IOAsync方法是真正异步的:

private async Task<Result> IOAsync(string sqlPauseDuration)
{
Result result;
using (var conn = new SqlConnection(m_connectionString))
using (var cmd = CreateCommand(conn, sqlPauseDuration))
{
await conn.OpenAsync();
using (var reader = await cmd.ExecuteReaderAsync())
{
await reader.ReadAsync();
result = new Result(reader.GetDateTime(0), reader.GetGuid(1));
}
}
return result;
}

private SqlCommand CreateCommand(SqlConnection conn, string sqlPauseDuration)
{
const string SQL = "WAITFOR DELAY @Duration;SELECT GETDATE(),NEWID()";
var sqlCommand = new SqlCommand(SQL, conn) { CommandTimeout = QueryTimeout };
sqlCommand.Parameters.Add(new SqlParameter("Duration", sqlPauseDuration));
return sqlCommand;
}


因此,如您所见,一切都是异步的。我正在使用性能监视器来检查线程数:


客户端应用
IIS工作进程(w3wp.exe)
Sql Server进程


我的期望是看到客户端和IIS工作进程的线条相对平坦,并且Sql Server突然增加。

这永远不会发生。进行600个请求最终转化为运行

WAITFOR DELAY @Duration;SELECT GETDATE(),NEWID()


@Duration为20秒的sql服务器上不会产生任何峰值,并且需要5分钟(几乎完全是这样)!从中可以得出结论,没有以足够的并发性处理请求。如果我想猜,我会说它同时处理(5 * 60)/ 20 = 15个请求。

注意:


在进行测试之前,我有“冷运行”请求来预热IIS和Sql Server。因此,启动时间不会影响方程式。
当我使用相同的设置直接从客户端运行 IOAsync时-600个请求和20秒,我确实看到了Sql Server上线程计数的预期峰值,并且所有少于600个请求在少于21个之后同时完成第二!


从中可以得出结论,问题出在Asp.NET/IIS端。

谷歌搜索问题促使我更改文件C:\ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319 \ Aspnet.config和c:\ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ Aspnet.config,如下所示:

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<runtime>
<legacyUnhandledExceptionPolicy enabled="false" />
<legacyImpersonationPolicy enabled="true"/>
<alwaysFlowImpersonationPolicy enabled="false"/>
<SymbolReadingPolicy enabled="1" />
<shadowCopyVerifyByTimestamp enabled="true"/>
</runtime>
<startup useLegacyV2RuntimeActivationPolicy="true" />
<system.web>
<applicationPool maxConcurrentRequestsPerCPU="5000" maxConcurrentThreadsPerCPU="0" requestQueueLimit="5000"/>
</system.web>
</configuration>


注意/configuration/system.web/applicationPool元素。这样做不会影响结果-同时仍然明显有15个请求。

我究竟做错了什么?

编辑1

不确定是否相关,这是通过Fiddler观察时典型的HTTP请求和响应的外观:

请求

POST http://canws212:12345/Home/SampleAPIAsync?strategy=Async HTTP/1.1
Content-Type: application/json
Host: canws212:12345
Content-Length: 174
Expect: 100-continue

{"IsBlocking":false,"Strategy":0,"Server":"CANWS212","Count":600,"QueryTimeout":30,"DurationSeconds":20,"ConnectionTimeout":4,"DBServer":"localhost","DBName":"tip_DFControl"}


响应

HTTP/1.1 200 OK
Cache-Control: private
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/8.0
X-AspNetMvc-Version: 5.2
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 19 Nov 2015 17:37:15 GMT
Content-Length: 83

{"Id":"16e8c3a2-fc95-446a-9459-7a89f368e074","Timestamp":"\/Date(1447954635240)\/"}


编辑2

请在Asp.Net应用程序的web.config下面找到:

<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=301880
-->
<configuration>
<appSettings>
<add key="webpages:Version" value="3.0.0.0"/>
<add key="webpages:Enabled" value="false"/>
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
</appSettings>
<!--
For a description of web.config changes see http://go.microsoft.com/fwlink/?LinkId=235367.

The following attributes can be set on the <httpRuntime> tag.
<system.Web>
<httpRuntime targetFramework="4.5.2" />
</system.Web>
-->
<system.web>
<compilation debug="true" targetFramework="4.5.2"/>
<httpRuntime targetFramework="4.5"/>
</system.web>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed"/>
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>


编辑3

在web.config中关闭sessionState:

<system.web>
<compilation debug="true" targetFramework="4.5.2"/>
<httpRuntime targetFramework="4.5"/>
<sessionState mode="Off" />
</system.web>


没有爱,同样的结果。

编辑4

检查 <limits>元素,它是默认值:

PS C:\> &"C:\Program Files\IIS Express\appcmd.exe" list config -section:system.applicationHost/sites |sls limits | group

Count Name Group
----- ---- -----
30 <limits /> { <limits />, <limits />, <limits />, <limits />...}


PS C:\>


因此,我想我不是在人为地限制它。 InetMgr报告以下内容:

enter image description here

另一方面,我正在运行带有IIS 8的Windows 8,因此应使用 http://weblogs.asp.net/owscott/windows-8-iis-8-concurrent-requests-limit。我尝试将网站默认值和网站默认值都更改为5000,但结果没有结果。

我所做的是:


使用InetMgr GUI在相关站点上将限制更改为5000。
重置
运行我的测试


结果相同。

编辑5

我的JSON正文反序列化代码有一个错误-持续时间使用默认值,而不是请求正文中的默认值。因此,这不是20秒,而是每个SQL语句5秒的持续时间。我使用的公式是错误的,应该是

NumberOfConcurrentRequests = TotalRequests / NumberOfBatches 
= TotalRequests / (TotalTime / OneRequestDuration)
= (TotalRequests / TotalTime) * OneRequestDuration
= (600 / 300) * 5
= 10


http://weblogs.asp.net/owscott/windows-8-iis-8-concurrent-requests-limit一致

现在,我已经部署到Windows Server 2012,可以发出75个DB请求,每个请求10秒长,几乎可以在10秒内完成。但是不是76,因此我得出的实际并发限制是75。不是5000。仍然在寻找线索。

编辑6

按照 Stephen Cleary的建议,我用 Task.Delay替换了所有的数据库IO,并停止了Sql Server。

没有asp.net,我可以轻松地运行10秒的600 Task.Delay,它们都在10秒内结束(有一点点额外的花费)。

使用asp.net的结果是一致的-75个请求是完全并发和异步的。除此之外,情况有所不同。因此,80个请求花了16秒,100个请求花了20秒,200个花了30秒。对我来说很明显,就像使用DB IO之前一样,Asp.NET或IIS限制了请求。

最佳答案

我猜想这是由于原始HTTP规范要求的客户端“每个端点最多两个并发连接”规则引起的。

您需要将ServicePointManager.DefaultConnectionLimit设置为适当的值,以允许更多并发连接。

例如:(在发送请求之前在客户端执行此操作)

ServicePointManager.DefaultConnectionLimit = int.MaxValue;


这将允许您的应用程序打开无限(实际上)数量的并发HTTP连接。



以下引用来自 section 8.1.4 of the HTTP/1.1 RFC


单用户客户端不应与任何服务器或代理维持超过2个连接。这些准则旨在缩短HTTP响应时间并避免拥塞。


因此,合规客户端通常必须确保与单个服务器的打开连接不得超过两个。

但是,这已更改,您可以覆盖此行为。以下引用来自 section 6.4 of RFC 7230,它是HTTP / 1.1协议的更新:


HTTP的先前版本提供了特定数量的连接作为
天花板,但是发现对于许多应用来说这是不切实际的。
结果,该规范没有规定特定的最大值
连接数,但鼓励客户成为
打开多个连接时保持保守。

关于asp.net - 无法配置IIS/Asp.NET来同时处理许多异步请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33810495/

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