HttpClient

使用HttpClient可以很方便的请求Web API,但在使用时有一些需要注意的地方,不然会给你的程序带来毁灭性的问题。

HttpClient是一个继承了IDisposable接口的对象,所以在使用的时候,需要主动调用Dispose方法来释放它。或者使用using

using(var client = new HttpClient())
{
//do something with http client
}

  

这看起来似乎没什么问题。我们使用一些代码来测试一下它,我们将发起10个GET请求:

namespace ConsoleApplication
{
public class Program
{
public static async Task Main(string[] args)
{
Console.WriteLine("Starting connections");
for(int i = 0; i<10; i++)
{
using(var client = new HttpClient())
{
var result = await client.GetAsync("http://www.zkea.net");
Console.WriteLine(result.StatusCode);
}
}
Console.WriteLine("Connections done");
}
}
}

  

输出结果如下:

Starting connections
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
Connections done

  

看起来一切正常,但实际上并不是!我们使用netstat来查看一下sockets的使用情况:

C:\Users\wayne>NETSTAT.EXE
...
Proto Local Address Foreign Address State
TCP 10.211.55.6:12050 47.74.132.243:http TIME_WAIT
TCP 10.211.55.6:12051 47.74.132.243:http TIME_WAIT
TCP 10.211.55.6:12053 47.74.132.243:http TIME_WAIT
TCP 10.211.55.6:12054 47.74.132.243:http TIME_WAIT
TCP 10.211.55.6:12055 47.74.132.243:http TIME_WAIT
TCP 10.211.55.6:12056 47.74.132.243:http TIME_WAIT
TCP 10.211.55.6:12057 47.74.132.243:http TIME_WAIT
TCP 10.211.55.6:12058 47.74.132.243:http TIME_WAIT
TCP 10.211.55.6:12059 47.74.132.243:http TIME_WAIT
TCP 10.211.55.6:12060 47.74.132.243:http TIME_WAIT
TCP 10.211.55.6:12061 47.74.132.243:http TIME_WAIT
TCP 10.211.55.6:12062 47.74.132.243:http TIME_WAIT
...

  

虽然应用程序已经退出,但是刚才发起的连接仍处于 TIME_WAIT 状态。TIME_WAIT 状态是指连接已经在一边关闭,但仍在等待是否有其他数据包出现, 因为它们可能在网络上的某个地方被延迟,socket资源并没有立即被回收。所以,如果你的程序(网站)的并发量很大,而每一次都实例化一个HttpClient对象,你的程序将会消耗掉服务器上所有可用的socket资源,并导致程序出现异常,不可正常访问。

正确使用HttpClient

HttpClient里面的方法都是线程安全的:

CancelPendingRequests
DeleteAsync
GetAsync
GetByteArrayAsync
GetStreamAsync
GetStringAsync
PostAsync
PutAsync
SendAsync

  

所以你应当只实例化一个HttpClient对象,并且不需要去主动释放它,它会在你程序退出的时候一起被释放掉。

我们对程序做以下修改再测试一下:

namespace ConsoleApplication
{
public class Program
{
private static HttpClient Client = new HttpClient();
public static async Task Main(string[] args)
{
Console.WriteLine("Starting connections");
for(int i = 0; i<10; i++)
{
var result = await Client.GetAsync("http://aspnetmonsters.com");
Console.WriteLine(result.StatusCode);
}
Console.WriteLine("Connections done");
Console.ReadLine();
}
}
}

  

再看看socket使用情况,这下就一切正常了:

TCP    10.211.55.6:12254      47.74.132.243:http  ESTABLISHED

  

原文链接:http://www.zkea.net/codesnippet/detail/post-122.html

.Net Core使用HttpClient请求Web API注意事项的更多相关文章

  1. 使用 HttpClient 请求 Web Api

    1.获取 post 请求 body 内容 [HttpPost] public string GetId() { //如果方法参数里面有 [FromBody],则需要重新调整内容指针,再进行读取. // ...

  2. Web API WinForm使用HttpClient呼叫Web API

    前言 之前几篇文章已经介绍了 Web 与 Web API 的使用方式,接下来将介绍如何在 Windows Form 呼叫 Web API 的方法,要在 WinForm 中使用 Web API 的话,除 ...

  3. 002.Create a web API with ASP.NET Core MVC and Visual Studio for Windows -- 【在windows上用vs与asp.net core mvc 创建一个 web api 程序】

    Create a web API with ASP.NET Core MVC and Visual Studio for Windows 在windows上用vs与asp.net core mvc 创 ...

  4. ASP.NET Core MVC中构建Web API

    在ASP.NET CORE MVC中,Web API是其中一个功能子集,可以直接使用MVC的特性及路由等功能. 在成功构建 ASP.NET CORE MVC项目之后,选中解决方案,先填加一个API的文 ...

  5. WebApi系列~实际项目中如何使用HttpClient向web api发异步Get和Post请求并且参数于具体实体类型

    回到目录 本讲比较实际,在WEB端有一个Index和Create方法,用来从web api显示实体列表数据和向api插入实体对象,这就是以往的网站,只不过是把数据持久化过程放到了web pai上面,它 ...

  6. 从实体框架核心开始:构建一个ASP。NET Core应用程序与Web API和代码优先开发

    下载StudentApplication.Web.zip - 599.5 KB 下载StudentApplication.API.zip - 11.5 KB 介绍 在上一篇文章中,我们了解了实体框架的 ...

  7. ASP.NET Core 1.0开发Web API程序

    .NET Core版本:1.0.0-rc2Visual Studio版本:Microsoft Visual Studio Community 2015 Update 2开发及运行平台:Windows ...

  8. 使用HttpClient 调用Web Api

    C#4.5 添加了异步调用Web Api . 如果你的项目是4.5以上版本,可以直接参考官方文档. http://www.asp.net/web-api/overview/web-api-client ...

  9. 【ASP.NET Web API2】利用HttpClient调用Web API(TODO)

    参照: 在一个空ASP.NET Web项目上创建一个ASP.NET Web API 2.0应用 纯属记录一下遇到的问题: 我们利用HttpClient来调用自宿主方式寄宿的Web API.HttpCl ...

随机推荐

  1. SpringBoot 之 普通类获取Spring容器中的bean

    [十]SpringBoot 之 普通类获取Spring容器中的bean   我们知道如果我们要在一个类使用spring提供的bean对象,我们需要把这个类注入到spring容器中,交给spring容器 ...

  2. Quartz实现JAVA定时任务的动态配置

    什么是动态配置定时任务? 首先说下这次主题,动态配置.没接触过定时任务的同学可以先看下此篇:JAVA定时任务实现的几种方式 定时任务实现方式千人千种,不过基础的无外乎 1.JDK 的Timer类 2. ...

  3. Spring框架中的单例Beans是线程安全的么

    Spring框架并没有对单例bean进行任何多线程的封装处理.关于单例bean的线程安全和并发问题需要开发者自行去搞定.但实际上,大部分的Spring bean并没有可变的状态(比如Serview类和 ...

  4. params over length limit is 20

  5. maven学习系列 之 常见问题

    1.新建的maven项目无法修改 Project Facets 的 Dynamic Web Module 版本 RE: 在工程目录下有一个.settings文件夹,打开org.eclipse.wst. ...

  6. mybatis 需要注意的点 MyBatis 插入空值时,需要指定JdbcType (201

    转自:https://blog.csdn.net/snakemoving/article/details/76052875 前天遇到一个问题 异常显示如下: 引用 Exception in threa ...

  7. VMware Workstation 虚拟机的服务启动项

  8. 使用SQL查询所有数据库名和表名

    使用SQL查询所有数据库名和表名 MySQL中查询所有数据库名和表名 查询所有数据库 show databases; 1 1 查询指定数据库中所有表名 select table_name from i ...

  9. POJ2533 最长递增子序列

    描述: 7 1 7 3 5 9 4 8 输出4 最长递增子序列为1 3 5 9,不必连续. 解法: 三种思路: 转化为最长公共子序列(n^2),动态规划(n^2),不知叫什么解法(nlogn). 解法 ...

  10. HTTP Cookie 详解

    参考: http://blog.csdn.net/lijing198997/article/details/22174151