我们的网络应用程序在.Net Framework 4.0中运行.UI通过ajax调用调用控制器方法.
我们需要从供应商处使用REST服务.我正在评估在.Net 4.0中调用REST服务的最佳方法.REST服务需要基本身份验证方案,它可以返回XML和JSON中的数据.没有要求上传/下载大量数据,我将来也看不到任何东西.我看了几个用于REST消费的开源代码项目,并没有找到任何值来证明项目中的额外依赖性.开始评估WebClient
和HttpClient
.我从NuGet下载了用于.Net 4.0的HttpClient.
我搜索了WebClient
和之间的差异,HttpClient
并且该网站提到单个HttpClient可以处理并发调用,它可以重用已解析的DNS,cookie配置和身份验证.我还没有看到由于差异我们可能获得的实用价值.
我做了一个快速的性能测试,以找到WebClient
(同步调用),HttpClient
(同步和异步)如何执行.以下是结果:
HttpClient
对所有请求使用相同的实例(min - max)
WebClient同步:8毫秒 - 167毫秒
HttpClient同步:3毫秒 - 7228毫秒
HttpClient异步:985 - 10405毫秒
HttpClient
为每个请求使用new (min - max)
WebClient同步:4毫秒 - 297毫秒
HttpClient同步:3毫秒 - 7953毫秒
HttpClient异步:1027 - 10834毫秒
public class AHNData
{
public int i;
public string str;
}
public class Program
{
public static HttpClient httpClient = new HttpClient();
private static readonly string _url = "http://localhost:9000/api/values/";
public static void Main(string[] args)
{
#region "Trace"
Trace.Listeners.Clear();
TextWriterTraceListener twtl = new TextWriterTraceListener(
"C:\\Temp\\REST_Test.txt");
twtl.Name = "TextLogger";
twtl.TraceOutputOptions = TraceOptions.ThreadId | TraceOptions.DateTime;
ConsoleTraceListener ctl = new ConsoleTraceListener(false);
ctl.TraceOutputOptions = TraceOptions.DateTime;
Trace.Listeners.Add(twtl);
Trace.Listeners.Add(ctl);
Trace.AutoFlush = true;
#endregion
int batchSize = 1000;
ParallelOptions parallelOptions = new ParallelOptions();
parallelOptions.MaxDegreeOfParallelism = batchSize;
ServicePointManager.DefaultConnectionLimit = 1000000;
Parallel.For(0, batchSize, parallelOptions,
j =>
{
Stopwatch sw1 = Stopwatch.StartNew();
GetDataFromHttpClientAsync>(sw1);
});
Parallel.For(0, batchSize, parallelOptions,
j =>
{
Stopwatch sw1 = Stopwatch.StartNew();
GetDataFromHttpClientSync>(sw1);
});
Parallel.For(0, batchSize, parallelOptions,
j =>
{
using (WebClient client = new WebClient())
{
Stopwatch sw = Stopwatch.StartNew();
byte[] arr = client.DownloadData(_url);
sw.Stop();
Trace.WriteLine("WebClient Sync " + sw.ElapsedMilliseconds);
}
});
Console.Read();
}
public static T GetDataFromWebClient()
{
using (var webClient = new WebClient())
{
webClient.BaseAddress = _url;
return JsonConvert.DeserializeObject(
webClient.DownloadString(_url));
}
}
public static void GetDataFromHttpClientSync(Stopwatch sw)
{
HttpClient httpClient = new HttpClient();
var response = httpClient.GetAsync(_url).Result;
var obj = JsonConvert.DeserializeObject(
response.Content.ReadAsStringAsync().Result);
sw.Stop();
Trace.WriteLine("HttpClient Sync " + sw.ElapsedMilliseconds);
}
public static void GetDataFromHttpClientAsync(Stopwatch sw)
{
HttpClient httpClient = new HttpClient();
var response = httpClient.GetAsync(_url).ContinueWith(
(a) => {
JsonConvert.DeserializeObject(
a.Result.Content.ReadAsStringAsync().Result);
sw.Stop();
Trace.WriteLine("HttpClient Async " + sw.ElapsedMilliseconds);
}, TaskContinuationOptions.None);
}
}
}
REST调用以3-4s返回,这是可以接受的.调用REST服务是在从ajax调用调用的控制器方法中启动的.首先,调用在不同的线程中运行,不会阻止UI.那么,我可以坚持同步电话吗?
上面的代码在我的localbox中运行.在prod设置中,将涉及DNS和代理查找.使用HttpClient
结束有什么好处WebClient
吗?
是HttpClient
并发好过WebClient
?从测试结果中,我看到 WebClient
同步调用表现更好.
HttpClient
如果我们升级到.Net 4.5,将是一个更好的设计选择吗?性能是关键的设计因素.
Anant Dabhi.. 221
我生活在F#和Web API世界中.
Web API发生了很多好事,特别是以安全性的消息处理程序等形式.
我知道我的意见只有一个,但我只建议HttpClient
将来用于任何工作.也许有一些方法可以利用其他部分System.Net.Http
而不直接使用该程序集,但我无法想象这将如何起作用.
说到比较这两个
HttpClient比WebClient更接近HTTP.
HttpClient并不是Web客户端的完全替代品,因为有些报告进度,自定义URI方案以及WebClient提供的FTP调用 - 但是HttpClient没有.
如果您使用的是.NET 4.5,请使用Microsoft为开发人员提供的HttpClient的async优度.HttpClient与HTTP的服务器端兄弟非常对称,即HttpRequest和HttpResponse.
更新:使用新HttpClient API的5个理由:
强类型标题.
共享缓存,cookie和凭据
访问cookie和共享cookie
控制缓存和共享缓存.
将代码模块注入ASP.NET管道.更清晰和模块化的代码.
参考
C#5.0 Joseph Albahari
(Channel9 - Video Build 2013)
使用新的HttpClient API连接到Web服务的五大理由
WebClient vs HttpClient vs HttpWebRequest