asp.net – 在IIS 7.5上使用传出异步Web请求时的可扩展性问题
下面有点长的描述,但它是一个相当棘手的问题。我试图覆盖我们知道的问题,以缩小搜索范围。这个问题更多的是一个持续的调查,而不是单个问题为基础的一个,但我认为它可以帮助其他人。但请在评论中添加信息或纠正我,如果你认为我错了以下的一些假设。
更新19/2,2013:我们已经清除了一些问号在这,我有一个理论的主要问题是,我会在下面更新。不准备写一个“解决”的反应,但它。 更新24/4,2013年:事情已经稳定在生产(虽然我相信它是暂时的)一段时间,我认为这是由于两个原因。 1)端口增加,以及2)减少的输出(转发)请求的数量。我将在正确的上下文中继续此更新。 我们目前正在调查我们的生产环境,以确定为什么当太多的传出异步Web服务请求(一个传入请求可能触发多个传出请求)时IIS Web服务器不扩展。 CPU只有20%,但我们收到HTTP 503错误传入的请求和许多传出的Web请求得到以下异常:“SocketException:无法执行套接字上的操作,因为系统缺乏足够的缓冲区空间或因为队列完全“显然,在某处存在可扩展性瓶颈,我们需要找出它是什么,如果可以通过配置解决它。 应用上下文: 我们在Windows 2008 R2 64位操作系统上使用.NET 4.5运行IIS v7.5集成管理管道。我们在IIS中只使用1个工作进程。硬件略有不同,但用于检查错误的机器是Intel Xeon 8内核(16个超线程)。 我们使用异步和同步Web请求。那些异步的是使用新的.NET异步支持,使每个传入请求在应用程序中对持久化TCP连接(保持活动)的其他服务器发出多个HTTP请求。同步请求执行时间低0-32 ms(由于线程上下文切换,发生更长的时间)。对于异步请求,执行时间可以在请求中止前最多120 ms。 通常每个服务器最多提供?1000个传入请求。当问题开始出现时,传出请求约?300请求/秒高达?600请求/秒。仅当传出异步时才会出现问题。请求在服务器上启用,我们超过一定级别的传出请求(?600 req./s)。 问题的可能解决方案: 在这个问题上搜索互联网可以发现大量可能的解决方案。虽然,他们非常依赖于.NET,IIS和操作系统的版本,所以它需要时间在我们的上下文中找到的东西(anno 2013)。 下面是一个解决方案候选列表和我们到目前为止关于我们的配置上下文的结论。我已经分类检测到的问题区域,到目前为止在以下主要类别: >一些队列填满 1)一些队列填满 传出的异步请求异常消息确实指示缓冲区的某个队列已经被填满。但它不会说哪个队列/缓冲区。通过IIS forum(和博客文章引用那里)我已经能够区分4可能6(或更多)不同类型的队列在请求管道标记为A-F下面。 虽然应该说明的是,在所有下面定义的队列中,我们看到1.B)ThreadPool性能计数器请求排队在有问题的负载期间变得非常满。所以很可能是问题的原因是在.NET级别,不低于这个(C-F)。 1.A).NET Framework级队列? 我们使用.NET框架类WebClient发出异步调用(异步支持),而不是我们遇到的HttpClient具有相同的问题,但是具有低得多的req / s阈值。我们不知道.NET Framework实现是隐藏任何内部队列还是不隐藏在Thread池上面。我们不认为这是真的。 .NET线程池 线程池作为一个自然的队列,因为.NET线程(默认)调度器从线程池中选择线程来执行。 性能计数器:[ASP.NET v4.0.30319]。[请求排队]。 配置可能性: >(ApplicationPool)maxConcurrentRequestsPerCPU应为5000(而不是前面的12)。所以在我们的情况下,它应该是5000 * 16 = 80.000请求/秒,这应该足够在我们的方案。 1.C)全局,进程宽,本地队列(仅限IIS集成模式) 如果线程池已满,请求开始在此本机(非管理)队列中堆积。 性能计数器:[ASP.NET v4.0.30319]。[本机队列中的请求] 配置可能性:? 1.D)HTTP.sys队列 这个队列与上面的1.C)不是同一个队列。这里是我所说的解释“HTTP.sys内核队列本质上是一个完成端口,用户模式(IIS)从内核模式(HTTP.sys)接收请求。它有一个队列限制,当超过时,您将收到503状态码。 HTTPErr日志还将通过记录503状态和QueueFull指示这发生。 性能计数器:我找不到此队列的任何性能计数器,但是通过启用IIS HTTPErr日志,应该可以检测此队列是否被洪泛。 配置可能性:这是在IIS中对应用程序池设置,高级设置:队列长度。默认值为1000.我已经看到将建议增加到10.000。虽然尝试这个增加还没有解决我们的问题。 1.E)操作系统未知队列? 虽然不太可能,我猜测OS实际上可能有一个队列在网卡缓冲区和HTTP.sys队列之间的某个地方。 1.F)网卡缓冲区: 当请求到达网卡时,很自然地,它们被放置在某些缓冲区中以便被某些OS内核线程拾取。由于这是内核级别的执行,因此很快,它不可能是罪魁祸首。 Windows性能计数器:[网络接口]。[丢弃的数据包]使用网卡实例。 配置可能性:? 2)TCP连接和端口的问题 这是一个候选人弹出这里和那里,虽然我们的传出(异步)TCP请求是由持久(保持活动)TCP连接。因此,随着流量的增长,可用临时端口的数量实际上只会由于传入请求而增长。我们知道,当我们有传出请求启用时,问题才会出现。 然而,由于在请求的较长时间段期间分配端口,所以仍然可能出现问题。外发请求可能需要长达120 ms的时间来执行(在.NET任务(线程)被取消之前),这可能意味着端口数量被分配更长的时间段。分析Windows性能计数器,验证此假设,因为TCPv4的数量[连接已建立]从正常2-3000到总峰值高达几乎12.000的问题发生时。 我们已经验证配置的最大TCP连接数被设置为默认值16384.在这种情况下,它可能不是问题,虽然我们危险地接近最大限制。 当我们尝试在服务器上使用netstat时,它通常返回没有任何输出,也使用TcpView显示很少的项目在开始。如果我们让TcpView运行一段时间,它很快开始显示新的(传入)连接相当迅速(说25连接/秒)。几乎所有连接都处于TIME_WAIT状态,表明他们已经完成并等待清理。这些连接是否使用临时端口?本地端口始终为80,远程端口正在增加。我们想使用TcpView为了看到流出的连接,但我们不能看到他们列出,这是非常奇怪。这两个工具不能处理我们拥有的连接数量? 更多,作为一边踢这里。在本博客文章“ASP.NET Thread Usage on IIS 7.5,IIS 7.0,and IIS 6.0”中建议ServicePointManager.DefaultConnectionLimit应设置为int maxValue,否则可能是一个问题。但在.NET 4.5中,这是从一开始就已经是默认的。 更新19/2,2013: >可以合理地假设我们确实达到了16.384个端口的最大限制。我们将所有端口数量都增加了一倍,但是只有一个服务器,只有老的服务器会遇到问题,当我们达到传统请求的高峰负载。那么为什么TCP.v4。[Connections Established]在问题时间从来没有告诉我们比?12.000更高的数字? MY理论:很可能,虽然没有建立为事实(但),性能计数器TCPv4。[建立连接]不等于当前分配的端口数。我还没有时间赶上TCP状态学习,但我猜测,有更多的TCP状态比“连接已建立”显示哪些将使端口被占用。虽然由于我们不能使用“连接已建立”性能计数器作为一种检测端口用尽的危险的方法,重要的是我们找到一些其他方式来检测达到这个最大端口范围。并且如上文所述,我们不能在我们的生产服务器上使用NetStat或应用程序TCPview。这是个问题! (我会写一个即将到来的响应我想这个帖子更多) END UPDATE 19/2,2013 更新24/4,2013: 但是,在问题发生的时候,我们没有看到GC和CPU使用率的增加,所以我们认为建议的CPU节流机制不是我们的解决方案。 UPDATE 19/2,2013:我们使用一个缓存交换机制在正常的intervalls,一个(几乎)完整的内存缓存重新加载到内存,旧缓存可以得到垃圾收集。在这些时候,GC将不得不更努力地工作,并从正常的请求处理中窃取资源。使用Windows性能计数器用于线程上下文切换,它显示上下文切换的数量从高GC使用时的正常高值显着减少。我认为在这样的缓存重新加载期间,服务器是额外的漏洞排队请求,并有必要减少GC的占用。解决这个问题的一个可能的办法是只填充缓存,而不是一直分配内存。多一点工作,但它应该是可行的。 更新24/4,2013: END UPDATE 24/4 解决方法
我已经通过Async Http处理程序实现了一个逆向代理用于基准测试目的(作为我的博士论文的一部分),并遇到了与你一样的问题。
为了缩放,必须将processModel设置为false并微调线程池。我发现,与processModel默认值的文档相反,许多线程池未正确配置,当processModel设置为true时。 maxConnection设置也很重要,因为它限制了您的可扩展性,如果限制设置得太低。见http://support.microsoft.com/default.aspx?scid=kb;en-us;821268 由于套接字上的TIME_WAIT延迟,您的应用程序运行的端口不足,我也面临同样的问题,因为我在240秒内从有限的一组机器注入流量超过64k的请求。我将TIME_WAIT降低到30秒没有任何问题。 我也错误地在几个线程中重用了一个代理对象到Web服务端点。虽然代理没有任何状态,我发现GC有很多问题收集与其内部缓冲区(String []实例)相关联的内存,并导致我的应用程序耗尽内存。 您应该监视的一些有趣的性能计数器是与排队请求,执行中的请求和ASP.NET应用程序类别下的请求时间相关的计数器。如果您看到排队的请求或执行时间较少,但客户端看到长的请求时间,那么您的服务器中会出现某种争用。还监视LocksAndThreads类别下的计数器,以查找争用。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net – 无Cookie属性web.config
- asp.net-mvc – 如何使用“?”路由查询字符串以及如何处理
- 处理ASP.NET Core中的HTML5客户端路由回退
- asp.net – 这两件事之间的区别
- asp.net-mvc – 在数据实体框架中显示名称
- 如何在ASP.NET Core类库项目中读取配置文件详解
- asp.net-mvc – 为什么HtmlHelpers需要这个HtmlHelper帮助器
- ASP.NET Web API项目自定义接口路由和HTTP请求方式
- asp.net-mvc – 如何使用我的Error.cshtml视图中的过滤器放
- .NET HttpSessionState案例不敏感
- content is not supported outside 'script&
- asp.net-mvc-5 – 带有LDAP身份验证的OWIN
- .Net Core技术研究-WebApi迁移ASP.NET Core2.0
- asp.net – 用于Basic或Windows身份验证的无限重
- asp.net-mvc – 具有持久HTTP连接的IDbConnectio
- asp.net – ClientScriptManager.GetPostBackEve
- asp.net – 如何将Sitecore Droptree源设置为项目
- asp.net-mvc – 为id而不是name设置HtmlFieldPre
- asp.net – 按Enter键时提交表单
- asp.net – Owin Middleware vs ExceptionHandle