.Net Core使用HttpClient请求Web API注意事项

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

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏aCloudDeveloper

internet 的一词多义

这是在《unix网络编程》中看到的比较全面的解释,在此作为一个整理。 一 是网际网,采用TCP/IP协议族通信的任何网络都是网际网,因特网就是一个网际网。 二 ...

1848
来自专栏james大数据架构

使用AsyncTask异步更新UI界面及原理分析

概述: AsyncTask是在Android SDK 1.5之后推出的一个方便编写后台线程与UI线程交互的辅助类。AsyncTask的内部实现是一个线程池,所有...

23910
来自专栏PHP在线

TCP/IP、HTTP协议概述

术语TCP/IP代表传输控制协议/网际协议,指的是一系列协议。“IP”代表网际协议,TCP和UDP使用该协议从一个网络传送数据包到另 一个网络。把IP想像成一种...

3185
来自专栏静默虚空的博客

[协议]ICMP协议剖析

1、ICMP简介 ICMP全名为(INTERNET CONTROL MESSAGE PROTOCOL)网络控制消息协议。 ICMP的协议号为1。 ICMP报文就...

3907
来自专栏跟着阿笨一起玩NET

GB2312转换成UTF-8与utf_8转换成GB2312

4841
来自专栏跟着阿笨一起玩NET

C#测试web服务是否可用

转载:http://www.cnblogs.com/xienb/p/3443282.html

671
来自专栏xiaoxi666的专栏

计算机网络学习记录(不断更新)

平时TTL减为0时最后一个经手的路由器会返回TTL-Exceeded报文,到目的主机后由于端口大于30000,会返回Port-Unreachable报文,这样就...

1092
来自专栏Java技术分享圈

杨老师课堂之Excel VBA 程序开发第三讲创建日报表

方式1:本节课件下载地址:链接: https://pan.baidu.com/s/1K51AlChFb-N-zsyCtcdm4A 密码: xpwn

592
来自专栏拂晓风起

Flash Actionscript 多线程Worker 压缩图片

1084
来自专栏技术小黑屋

关于Android中工作者线程的思考

本文为 InfoQ 中文站特供稿件,首发地址为:http://www.infoq.com/cn/articles/android-worker-thread 如...

592

扫码关注云+社区

领取腾讯云代金券