正在写WebApi 接口,用到HttpClient,突然想到这个这个用单例模式还是每次new实例好呢,为此在网上查询资料进行总结。
(1)单例模式可以有效的减少响应时间
httpClient 本质就是进行TCP连接,每次new 都会新建连接->传数据->关闭连接,增加了响应时间,所以在访问同一IP接口时,可以对httpClient进行单例长连接模式,多次 HTTP 之间重用同一个 TCP 连接,从而减少创建/关闭多个 TCP 连接的开销(包括响应时间、CPU 资源、减少拥堵等),相对不用时会资源浪费。
(2)长连接线程安全方法
在进行长连接时,往往会担心线程的安全,根据查询得知以下方法线程安全的
CancelPendingRequests
DeleteAsync
GetAsync
GetByteArrayAsync
GetStreamAsync
GetStringAsync
PostAsync
PutAsync
SendAsync
同时在head也需要加入keep-alive告诉服务器
/*HTTP 1.0 中默认是关闭的,需要在http头加入"Connection: Keep-Alive",才能启用Keep-Alive;
HTTP 1.1 中默认启用Keep-Alive,如果加入"Connection: close ",才关闭。*/
Client.DefaultRequestHeaders.Connection.Add("keep-alive");
(3)用分段读取替代永不超时(网上截取到时用用)
为了缓解超时问题,很多人喜欢这么写:
HttpClient.Timeout = Timeout.InfiniteTimeSpan;
然而这却是个再错误不过的做法,因为这将使得程序变得非常不可控,并非使用`CancellationTokenSource 即可简单解决。
要处理这个问题,增加超时时间是一个方法,另外还可以通过设置 HttpRequestHeaders.Range 来进行分段读取:
public static async Task<DlStreamInfo> GetStreamInfoAsync(this HttpClient client, string requestUri, long? from, long? to)
{
using (var request = new HttpRequestMessage(HttpMethod.Get, requestUri))
{
request.Headers.Range = new RangeHeaderValue(from, to);
var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
return new DlStreamInfo(response, await response.EnsureSuccessStatusCode().Content.ReadAsStreamAsync().ConfigureAwait(false),
response.Content.Headers.ContentLength ?? -1);
}
}
先这么多