如何使使用HttpWebRequest的C#应用程序像fiddler一样工作
我有一个控制台应用程序,它使用大约20个线程连接到远程web服务器,并发送任意http请求,大小相当小,100%通过ssl。远程web服务器实际上是一个完整的负载平衡数据中心,拥有高可用性系统,每秒可以处理数十万个请求。这不是服务器或带宽问题。话虽如此,我不运行它,对它的配置也没有任何影响,所以即使我想做服务器端的更改,也无法进行 使用fiddler运行应用程序时,应用程序的运行速度惊人。当不使用fiddler时,它的速度会慢得多,以至于对手头的任务毫无用处。它似乎也锁定在某个点,而不是在过程的早期,但这可能只是一个死锁的问题,我还不确定 无论如何,作为代理的fiddler无疑是在以某种方式修改我的请求/连接,以确保出色的吞吐量,但我不知道它在做什么。我正试图弄明白这一点,这样我就可以强制我的.net应用程序模拟fiddler的连接处理行为,而不必通过fiddler实际运行它 我已经在下面粘贴了连接代码如何使使用HttpWebRequest的C#应用程序像fiddler一样工作,c#,.net,httpwebrequest,fiddler,C#,.net,Httpwebrequest,Fiddler,我有一个控制台应用程序,它使用大约20个线程连接到远程web服务器,并发送任意http请求,大小相当小,100%通过ssl。远程web服务器实际上是一个完整的负载平衡数据中心,拥有高可用性系统,每秒可以处理数十万个请求。这不是服务器或带宽问题。话虽如此,我不运行它,对它的配置也没有任何影响,所以即使我想做服务器端的更改,也无法进行 使用fiddler运行应用程序时,应用程序的运行速度惊人。当不使用fiddler时,它的速度会慢得多,以至于对手头的任务毫无用处。它似乎也锁定在某个点,而不是在过程的
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
namespace Redacted
{
public class HiveCommunicator
{
public static IResponse SendRequest(IRequest request) {
ServicePointManager.DefaultConnectionLimit = 60;
ServicePointManager.Expect100Continue = false;
string hostUrlString = string.Empty;
if (request.SiteID <= 0)
hostUrlString = string.Format("{0}://{1}{2}", request.UseSSL ? "https" : "http", DataCenters.GetCenter(request.DataCenter), request.Path);
else
hostUrlString = string.Format("{0}://{1}{2}", request.UseSSL ? "https" : "http", DataCenters.GetCenter(request.DataCenter), string.Format(request.Path, request.SiteID));
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(hostUrlString);
switch (request.ContentType)
{
default:
case ContentTypes.XML:
webRequest.ContentType = "application/xml";
break;
case ContentTypes.JSON:
webRequest.ContentType = "application/json";
break;
case ContentTypes.BINARY:
webRequest.ContentType = "application/octet-stream";
break;
}
if (request.RequiresAuthorizationToken)
{
AuthorizationToken tok = HiveAuthentication.GetToken(request.SiteID);
if (tok == null)
{
return null;
}
webRequest.Headers.Add(HttpRequestHeader.Authorization, tok.Token);
}
bool UsesRequestBody = true;
switch (request.HttpVerb)
{
case HttpVerbs.POST:
webRequest.Method = "POST";
break;
case HttpVerbs.DELETE:
webRequest.Method = "DELETE";
UsesRequestBody = false;
break;
case HttpVerbs.PUT:
webRequest.Method = "PUT";
break;
default:
case HttpVerbs.GET:
webRequest.Method = "GET";
UsesRequestBody = false;
break;
}
HttpWebResponse webResponse = null;
Stream webRequestStream = null;
byte[] webRequestBytes = null;
if (UsesRequestBody)
{
webRequestBytes = request.RequestBytes;
webRequest.ContentLength = webRequestBytes.Length;
webRequestStream = webRequest.GetRequestStream();
for (int i = 0; i < webRequest.ContentLength; i++)
{
webRequestStream.WriteByte(webRequestBytes[i]);
}
}
try
{
webResponse = (HttpWebResponse)webRequest.GetResponse();
}
catch (WebException ex)
{
webResponse = (HttpWebResponse)ex.Response;
}
if (UsesRequestBody)
{
webRequestStream.Close();
webRequestStream.Dispose();
}
IResponse respReturn = request.ParseResponse(webResponse);
webResponse.Close();
return respReturn;
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
Net系统;
使用System.IO;
名称空间编辑
{
公共类HiveCommunicator
{
公共静态IResponse SendRequest(IRequest请求){
ServicePointManager.DefaultConnectionLimit=60;
ServicePointManager.Expect100Continue=false;
string hostUrlString=string.Empty;
如果(request.SiteID在这里胡乱猜测,但可能与简单的app.config设置有关:
<system.net>
<connectionManagement>
<add address="*" maxconnection="40"/>
</connectionManagement>
</system.net>
我曾经在一个多线程HTTP请求应用程序中遇到过同样的问题,这解决了这个问题。你可以使用Fiddler的“连接选项”看看Fiddler强大的吞吐量的原因是重用客户端连接。如果是这样的话,你可能想考虑实现一个共享的安全HTTP连接池,或者只是去看一部电影之类的东西。^ ^ < p>我感谢这里的那些试图帮助的人。不幸的是,这需要一个对微软专业支持的调用。
尽管我使用的是ServicePointManager.Expect100Continue=false;
但它发生在应用程序生命周期的后期。查看System.Net.Trace日志,我们发现expect-100 continue标头仍在使用中(使用fiddler时除外)。解决方案是将其放入应用程序启动中(在Main()中)
我还试图在关闭请求流之前读取响应流
修复后,一切都很好地加快了速度。没有fiddler的应用程序比没有fiddler的应用程序运行得快得多,这正是我所期望的
一些人说在HttpWebResponse上调用dispose。该类没有公共dispose方法。我假设.Close()在内部调用.dispose()。鉴于您的应用程序发送“任意http请求,大小相当小”,它可能有助于禁用Nagle算法。
ServicePointManager.UseNagleAlgorithm = true;
From:使用HttpWebRequest时,有许多因素会影响性能,包括:
- 这个班
- 财产
- 财产
Nagle算法[…]在通过网络发送数据之前,将小消息序列累积成较大的TCP数据包。[…]通常,对于恒定的大容量吞吐量,使用Nagle算法可以实现性能改进。但是对于吞吐量较小的应用,性能可能会下降。[…]如果应用程序正在使用低延迟连接,则将此属性设置为false可能会有所帮助。
ServicePointManager.UseNagleAlgorithm = true;
我不确定在哪里可以找到关于设置“共享安全http连接池”的信息,我想知道你是否可以推荐一些谷歌搜索词()Jon Skeet建议在WebResponse上显式调用dispose,以便底层基础结构可以重用相同的连接。也许这会有所帮助。感谢您的提示,我已经尝试过了,但似乎不起作用,但感谢您的建议;)我也遇到了这个标题的问题。我一辈子都无法理解为什么MS让这个标题变得如此难以更改。这就是导致我出现问题的原因。当我设置ServicePointManager.UseNagleAlgorithm=false时,我的连接从200ms变为6ms。