我们有一个使用IIS托pipe的ServiceStack实现的API。 在执行API的负载testing时,我们发现响应时间是好的,但是一旦我们每服务器达到约3,500个并发用户,它们就会迅速恶化。 我们有两台服务器,当用7000个用户点击它们时,所有端点的平均响应时间都低于500ms。 这些盒子位于负载平衡器的后面,所以我们可以得到每台服务器3500个并发数。 但是,一旦我们增加了总并发用户的数量,我们就会看到响应时间显着增加。 将并发用户数量增加到每个服务器5,000个,每个端点的平均响应时间约为7秒。
服务器上的内存和CPU都非常低,两者的响应时间都很好,而且在恶化之后。 在拥有10,000个并发用户的峰值时,CPU的平均值仅仅低于50%,而RAM的坐标大约是3-4 GB。这让我们认为我们正在某种程度上受到某种限制。 以下屏幕截图显示了在负载testing期间perfmon中的一些关键计数器,共有10,000个并发用户。 突出显示的计数器是请求/秒。 在屏幕截图的右侧,您可以看到每秒请求图变得非常不稳定。 这是响应时间缓慢的主要指标。 一旦我们看到这种模式,我们注意到在负载testing中响应时间慢。

如何解决这个性能问题? 我们正试图确定这是一个编码问题还是一个configuration问题。 web.config或IIS中是否有任何设置可以解释这种行为? 应用程序池运行的是.NET v4.0,IIS版本是7.5。 我们通过默认设置进行的唯一更改是将应用程序池“ 队列长度”值从1,000更新为5,000。 我们还将以下configuration设置添加到Aspnet.config文件中:
<system.web> <applicationPool maxConcurrentRequestsPerCPU="5000" maxConcurrentThreadsPerCPU="0" requestQueueLimit="5000" /> </system.web>
更多细节:
API的目的是合并来自各种外部源的数据并作为JSON返回。 目前它正在使用InMemorycaching实现caching数据层的各个外部调用。 对资源的第一个请求将获取所有需要的数据,对相同资源的任何后续请求将从caching中获取结果。 我们有一个“caching运行程序”,作为后台进程实现,以特定的时间间隔更新caching中的信息。 我们添加了从外部资源中获取数据的代码。 我们还实现了以asynchronous方式从外部数据源获取数据的服务,以便端点只能像最慢的外部调用一样慢(除非我们有caching中的数据)。 这是使用System.Threading.Tasks.Task类完成的。 我们可以在进程的可用线程数方面受到限制吗?
以下@DavidSchwartz和@Matt这看起来像一个线程,lockingpipe理问题。
我build议:
冻结外部调用和为其生成的caching,并使用静态外部信息运行负载testing,以放弃与服务器环境端无关的任何问题。
如果不使用它们,请使用线程池。
关于外部调用你说:“我们也实现了服务,以asynchronous的方式从外部来源获取数据,所以端点应该和最慢的外部调用一样慢(除非我们有caching中的数据)。 “
问题是: – 您是否检查过外部调用期间是否有任何caching数据被locking,或只有在将外部调用结果写入caching时才检查? (太明显,但必须说)。 – 你locking整个caching或小部分? (太明显,但必须说)。 – 即使它们是asynchronous的,外部调用运行的频率如何? 即使它们不经常运行,在高速caching被locking时,它们也可能被用户调用的过多caching请求阻塞。 这个场景通常显示固定的CPU使用百分比,因为许multithreading正在等待固定的时间间隔,并且“locking”也必须被pipe理。 – 您是否检查过外部任务是否意味着响应时间在缓慢情况到来时也会增加?
如果问题仍然存在,我build议避免任务类,并通过pipe理用户请求相同的线程池进行外部调用。 这是为了避免以前的情况。