我正在编写测试工具来测试HTTP Post。测试用例将在10秒间隔内使用webclient类中的UploadValuesAsync发送8个http请求。它在每8个请求后睡10秒。我正在记录每个请求的开始时间和结束时间。当我计算平均响应时间时。我大约800毫秒。但是当我在Web客户端中使用UploadValues方法同步运行此测试用例时,我的平均响应时间为250毫秒。你能告诉我为什么这两种方法有区别吗?我期待Aync的响应时间减少,但我没有得到。
以下是发送8个异步请求的代码
var count = 0;
foreach (var nameValueCollection in requestCollections)
{
count++;
NameValueCollection collection = nameValueCollection;
PostToURL(collection,uri);
if (count % 8 == 0)
{
Thread.Sleep(TimeSpan.FromSeconds(10));
count = 0;
}
}
已更新 这是发送8个请求SYNC
的代码public void PostToURLSync(NameValueCollection collection,Uri uri)
{
var response = new ServiceResponse
{
Response = "Not Started",
Request = string.Join(";", collection.Cast<string>()
.Select(col => String.Concat(col, "=", collection[col])).ToArray()),
ApplicationId = collection["ApplicationId"]
};
try
{
using (var transportType2 = new DerivedWebClient())
{
transportType2.Expect100Continue = false;
transportType2.Timeout = TimeSpan.FromMilliseconds(2000);
response.StartTime = DateTime.Now;
var responeByte = transportType2.UploadValues(uri, "POST", collection);
response.EndTime = DateTime.Now;
response.Response = Encoding.Default.GetString(responeByte);
}
}
catch (Exception exception)
{
Console.WriteLine(exception.ToString());
}
response.ResponseInMs = (int)response.EndTime.Subtract(response.StartTime).TotalMilliseconds;
responses.Add(response);
Console.WriteLine(response.ResponseInMs);
}
以下是发布到HTTP URI的代码
public void PostToURL(NameValueCollection collection,Uri uri)
{
var response = new ServiceResponse
{
Response = "Not Started",
Request = string.Join(";", collection.Cast<string>()
.Select(col => String.Concat(col, "=", collection[col])).ToArray()),
ApplicationId = collection["ApplicationId"]
};
try
{
using (var transportType2 = new DerivedWebClient())
{
transportType2.Expect100Continue = false;
transportType2.Timeout = TimeSpan.FromMilliseconds(2000);
response.StartTime = DateTime.Now;
transportType2.UploadValuesCompleted += new UploadValuesCompletedEventHandler(transportType2_UploadValuesCompleted);
transportType2.UploadValuesAsync(uri, "POST", collection,response);
}
}
catch (Exception exception)
{
Console.WriteLine(exception.ToString());
}
}
这是上传完成的活动
private void transportType2_UploadValuesCompleted(object sender, UploadValuesCompletedEventArgs e)
{
var now = DateTime.Now;
var response = (ServiceResponse)e.UserState;
response.EndTime = now;
response.ResponseInMs = (int) response.EndTime.Subtract(response.StartTime).TotalMilliseconds;
Console.WriteLine(response.ResponseInMs);
if (e.Error != null)
{
response.Response = e.Error.ToString();
}
else
if (e.Result != null && e.Result.Length > 0)
{
string downloadedData = Encoding.Default.GetString(e.Result);
response.Response = downloadedData;
}
//Recording response in Global variable
responses.Add(response);
}
答案 0 :(得分:2)
您可能遇到的一个问题是,默认情况下,.NET会将传出的HTTP连接限制为相关RFC规定的限制(每个远程主机有2个并发连接)。假设2个并发连接和每个请求250毫秒,这意味着前2个请求的响应时间将是250毫秒,第二个2将是500毫秒,第三个750毫秒,最后1000毫秒。这将产生625ms的平均响应时间,这与您所看到的800ms相差不远。
要删除限制,请将ServicePointManager.DefaultConnectionLimit
增加到您要支持的最大并发连接数,并且应该会看到平均响应时间不断下降。
第二个问题可能是服务器本身处理多个并发连接的速度慢于一次处理一个请求。即使你解除上面的限制问题,我也希望每个异步请求平均执行速度比服务器一次只执行一个请求要慢一些。慢多少取决于服务器针对并发请求进行优化的程度。
最终问题可能是由测试方法引起的。例如,如果您的测试客户端通过存储cookie并使用每个请求重新发送cookie来模拟浏览器会话,则可能会遇到一些服务器的问题,这些服务器将序列化来自单个用户的请求。这通常是服务器应用程序的简化,因此他们不必处理锁定交叉请求状态,如会话状态。如果您遇到此问题,请确保每个WebClient发送不同的Cookie以模拟不同的用户。
我并不是说你遇到了所有这三个问题 - 你可能只会遇到1或2 - 但这些是你所看到的问题最可能的罪魁祸首。
答案 1 :(得分:0)
正如贾斯汀所说,我尝试过ServicePointManager.DefaultConnectionLimit,但这并没有解决问题。我无法重现Justin提出的其他问题。我不知道如何在第一时间重现它们。
我做了什么,我在对等机器上运行了相同的代码,运行时间与我预期的完全相同。两台机器之间的区别在于操作系统。我在Windows Server 2003上运行,其他计算机在Windows Server 2008上运行。
由于它在其他机器上工作,我怀疑它可能是Justin指定的问题之一,或者可能是2003年或其他的服务器设置。我没有花太多时间来挖掘这个问题。由于这是一个测试工具,我们在这个问题上没有优先考虑。我们没有时间进一步离开。
由于我没有完全固定它的胶水,我不接受除此之外的任何答案。至少我知道切换到服务器2008解决了这个问题。