我有一个用C#编写的ASP.NET 3.5服务器应用程序。它使用HttpWebRequest和HttpWebResponse向REST API发出请求。
我设置了一个测试应用程序,在单独的线程上发送这些请求(模拟与服务器的并发)。
请注意,这更多是关于Mono/环境的问题,而不是代码问题;因此,请记住下面的代码不是一字不差的;只是功能位的剪切/粘贴。
以下是一些伪代码:
// threaded client piece
int numThreads = 1;
ManualResetEvent doneEvent;
using (doneEvent = new ManualResetEvent(false))
{
for (int i = 0; i < numThreads; i++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(Test), random_url_to_same_host);
}
doneEvent.WaitOne();
}
void Test(object some_url)
{
// setup service point here just to show what config settings Im using
ServicePoint lgsp = ServicePointManager.FindServicePoint(new Uri(some_url.ToString()));
// set these to optimal for MONO and .NET
lgsp.Expect100Continue = false;
lgsp.ConnectionLimit = 100;
lgsp.UseNagleAlgorithm = true;
lgsp.MaxIdleTime = 100000;
_request = (HttpWebRequest)WebRequest.Create(some_url);
using (HttpWebResponse _response = (HttpWebResponse)_request.GetResponse())
{
// do stuff
} // releases the response object
// close out threading stuff
if (Interlocked.Decrement(ref numThreads) == 0)
{
doneEvent.Set();
}
}
如果在本地开发机器(Windows 7)上在Visual Studio Web服务器上运行应用程序,则可以增加numThreads并在1个“用户”或100个“用户”时获得相同的平均响应时间,并且变化很小。将应用程序发布和部署到在Mono 2.10.2环境下的Apache2中,响应时间几乎呈线性增长。 (即1个线程= 300ms,5个线程= 1500ms,10个线程= 3000ms)。这会发生在不同的服务器端点上(不同的主机名,不同的网络等)。
使用IPTRAF(和其他网络工具),似乎应用程序仅打开1或2个端口来路由所有连接,并且剩余的响应必须等待。
我们构建了一个类似的PHP应用程序,并使用相同的请求在Mono中部署,而响应则适当地扩展。
我已经尝试了我能想到的每个Mono和Apache的配置设置,而两个环境之间(至少在代码中)唯一不同的设置是有时ServicePoint SupportsPipelining = false在Mono中,而从我的机器上是true。
看起来ConnectionLimit(默认为2)在Mono中由于某种原因没有被更改,但我在代码和web.config中为指定的主机设置了更高的值。
我和我的团队要么忽略了重要的事情,要么这是Mono中的某种错误。