一. 背景
1.前世
提到HttpClient,在传统的.Net版本中简直臭名昭著,因为我们安装官方用法 using(var httpClient = new HttpClient()),当然可以Dispose,但是在高并发的情况下,连接来不及释放,socket被耗尽,然后就会出现一个喜闻乐见的错误:即各种套接字的问题。
Unable to connect to the remote serverSystem.Net.Sockets.SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted.
PS:当然我们可以通过修改注册表的默认值,来人为的减少超时时间,但可能会引起其他莫名其妙的问题:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\TcpTimedWaitDelay])
2.我们之前的解决方案
把HttpClient做成全局单例的,通过共享一个实例,减少了套接字的浪费,实际上由于套接字重用而传输快一点。
关于单例的封装,详见这篇: https://www.cnblogs.com/yaopengfei/p/10301779.html
封装成单例的也会有些不灵活的地方:
(1).因为是复用的 HttpClient,那么一些公共的设置就没办法灵活的调整了,如请求头的自定义。
(2).因为 HttpClient 请求每个 url 时,会缓存该url对应的主机 ip,从而会导致 DNS 更新失效(TTL 失效了)。
3.HttpClientFactiory应运而生
HttpClientFactory 是 ASP.NET CORE 2.1 中新增加的功能。顾名思义 HttpClientFactory 就是 HttpClient 的工厂,内部已经帮我们处理好了对 HttpClient 的管理,不需要我们人工进行对象释放,同时,支持自定义请求头,支持 DNS 更新。
分析:
HttpClient 继承自 HttpMessageInvoker,而 HttpMessageInvoker 实质就是HttpClientHandler。HttpClientFactory 创建的 HttpClient,也即是 HttpClientHandler,只是这些个 HttpClient 被放到了“池子”中,工厂每次在 create 的时候会自动判断是新建还是复用。(默认生命周期为 2min)。简单的理解成 Task 和 Thread 的关系。
4. 补充请求方式的说明
其中Post请求有两种,分别是: "application/x-www-form-urlencoded"表单提交的方式 和 "application/json" Json格式提交的方式。
(1). Post的表单提交的格式为:"userName=admin&pwd=123456"。
(2). Post的Json的提交格式为:将实体(类)转换成json字符串。
二. 几种用法
用到的服务器端的方法:
/// <summary> /// 充当服务端接口 /// </summary> public class ServerController : Controller { [HttpGet] public string CheckLogin(string userName, string pwd) { if (userName == "admin" && pwd == "123456") { return "ok"; } else { return "error"; } } [HttpPost] public string Register1(string userName, string pwd) { if (userName == "admin" && pwd == "123456") { return "ok"; } else { return "error"; } } [HttpPost] public string Register2([FromBody]UserInfor model) { if (model.userName == "admin" && model.pwd == "123456") { return "ok"; } else { return "error"; } } }