创新的常州网站建设,重庆最新新闻事件今天,网站建设推广费计入什么科目,站外推广营销方案前言关于HttpClient的使用#xff0c;个人在很多场景都派上用场了#xff0c;比如在Winform或后台服务中用其调用接口获取和上传数据、微服务中用其进行各服务之间的数据共享等#xff0c;到目前来看#xff0c;似乎还没有出现过什么问题#xff0c;但当我看到官方文档介绍… 前言关于HttpClient的使用个人在很多场景都派上用场了比如在Winform或后台服务中用其调用接口获取和上传数据、微服务中用其进行各服务之间的数据共享等到目前来看似乎还没有出现过什么问题但当我看到官方文档介绍使用方式时再回顾之前项目的代码只能说没出问题比较庆幸。官方文档介绍的大概意思如下HttpClient类使用比较简单但在某些情况下许多开发人员却并未正确使用该类虽然此类实现 IDisposable但在 using 语句中声明和实例化它并非首选操作因为释放 HttpClient 对象时基础套接字不会立即释放这可能会导致套接字耗尽问题最终可能会导致 SocketException 错误。要解决此问题推荐的方法是将 HttpClient 对象创建为单一对象或静态对象看到这有一点点小不安(因为有些项目就是用using的方式)虽然目前的并发量还不至于导致SocketException异常的发生但优化得马不停蹄的安排上先来探探HttpClient再来说说IHttpClientFactory。正文1. HttpClient好像一直没用对这里创建了一个控制台程序进行测试(.NetCore3.1)代码比较简单如下注代码中访问的地址是用Nginx搭建在阿里云上搭建的站点没有做负载所以看Socket状态比较直观。上面代码执行完成之后就退出了理论情况来说上面程序执行完毕之后就不应该占用资源啦但通过netstat查看的确还有Socket被占用测试如下Windows 测试执行如下命令看结果netstat -ano | findstr TIME_WAIT
Linux测试我的云服务器之前就把.NetCore运行环境安装好了所以创建一个目录将编译之后的文件通过Xftp将文件传到云服务器执行以下命令即可# 注意这里指定启动的是dll文件
dotnet HttpClientConsoleDemo.dll
查看端口情况执行以下命令即可netstat -ant | grep TIME_WAIT # 查看端口占用情况找到状态为TIME_WAIT
TIME_WAIT 是主动关闭 TCP 连接的那一方出现的状态系统会在 TIME_WAIT 状态下等待 2MSLmaximum segment lifetime 后才能释放连接端口目的是为了在TCP 四次挥手关闭连接机制中保证 ACK 重发和丢弃延迟数据。按照解释来看这种做法也算是合情合理保证数据传输嘛但的确就是占用资源啦具体关于网络的相关知识小伙伴们再去查阅一下。经过Windows和Linux的测试大概差不多两分钟的时间Socket才完全被释放可想如果是在高并发情况下每台机器的能开的连接数是有限的使用这种方式进行服务和服务之间交互数据那肯定会出现问题。而从理论上来讲只要HttpClient继承了IDisposable接口using块执行完就可以释放掉资源而HttpClient确实是间接继承了IDisposable(直接继承HttpMessageInvoker 而HttpMessageInvoker继承了IDisposable接口)。但在这里使用HttpClient分配的Socket端口没有得到及时释放为避免这个问题官方推荐用静态变量的方式使用HttpClient。2. HttpClient换种方式好多啦按照官方建议将HttpClient变量定义为静态变量代码如下运行程序执行netstat命令可以看到资源占用情况明显减少了。如果使用静态变量看似解决了对应的问题但若想针对不同的请求设置不同的头信息时就显得不太方便至于其他问题我暂时还没遇见过(官方说这种方式不支持 DNS 变更)。先忽略其他问题在.NetCore2.1开始出现了IHttpClientFactory 据说是可以解决之前HttpClient面临的一些问题所以有需要用HttpClient的场景直接用IHttpClientFactory 就妥啦不信就来试试。3. IHttpClientFactory用起来很给力IHttpClientFactory是在.NETCore 2.1 开始提供的默认实现为 DefaultHttpClientFactory 专门用于创建在应用程序中用到的 HttpClient实例自动维护内部的HttpMessageHandler池及其生命周期。主要功能如下支持命名化、类型化配置集中管理配置避免冲突出站请求管道配置灵活轻松实现对请求生命周期的管理合理管理内部HttpMessageHanlder的生命周期避免资源占用和DNS刷新等问题内置日志记录器接下来就来看看IHttpClientFactory到底有多给力3.1 控制台演示由于内部需要使用了一些服务并且是采用DI的形式注入的所以首先要把依赖注入的相关的包引入进来代码如下图先来简单看一下需要注册的服务后续会好好说运行程序然后通过以下命令查看端口占用情况netstat -ano | findstr TIME_WAIT # 根据状态去找
netstat -ano | findstr 47.113.204.41 # 根据IP去找
最终没有见到很明显的资源占用情况有没有给力一点还有一些比较常用的方式在WebApi项目中一一演示(毕竟微服务中服务间通信还是比较常用的)。3.2 WebApi项目演示创建一个API项目注册上相关服务即可增加一个测试控制器和测试接口运行看结果在API项目中是不是使用很简单因为项目本身就内置了依赖注入相关功能直接注册上服务就可以使用但这还体现不出有多给力接下来继续看看其他扩展方式的使用。3.3 使用命名和类型模式区分不同HttpClient使用步骤与3.2是一样的只是在注册服务的时候不太一样而已。命名模式注册服务时代码如下增加一个测试接口运行结果和上面一样只是HttpClient实例带的头信息不一样啦如下类型模式其实类型模式原理和命名模式是一样的只是通过指定的类型名称作为对应HttpClient的名称减少了单独定义名称的步骤所以显得比较方便个人比较喜欢这样用。首先定义一个业务处理类直接使用HttpClient代码如下在Startup中注册服务时代码如下增加一个测试接口运行结果和上面一样调用过程如下进入TypeHttpClientService对应的方法看到在注册时设置的头信息已经生效了如下执行完毕后正常返回结果。类型模式不用单独为HttpClient起名而是直接用指定类型的类名作为默认名这样就相对方便啦摘取获取类型名的源码如下小扩展自定义的管道类没有在Startup中手动注册为什么能直接注入使用答案在services.AddHttpClient注册时内部已经将对应Type注册好了摘取代码如下除了能轻松区分不同HttpClient之外如果需要在请求过程中加入其它公共业务处理可以通过增加自定义管道逻辑轻松实现。3.4 在请求管道中增加自定义管道逻辑先定义一个管道类(CustomDelegatingHandler)继承DelegatingHandler然后重写SendAsync方法在Startup中注册对应的服务根据需要在HttpClient上加上自定义管道运行看效果只有用到类型模式的HttpClient才会加入自定义管道因为在配置的时候进行了针对性的配置这种方式是不是感觉和.NetCore的中间件管道很类似编写自定义管道其实就类似于在编写一个中间件(至于原理后续单独扒扒源码)轻松实现在请求前和响应后做相关业务处理就像上面加的RequestID对分析分布式事务及微服务调用链跟踪都有很大的帮助所以小伙伴可以根据自己的需要封装自己想要的HttpClient。4. IHttpClientFactory 搭配Polly就完美了只要牵涉到网络要想服务百分百稳定那是相当难比如常遇到的网络不通、网络波动、远端服务挂了、远端服务响应慢等问题都可能会影响用户对系统的体验别慌还记得之前说过专门为故障、弹性应变设计的Polly库吗(详情请看Polly-故障处理和弹性应对很有一手)如果HttpClientFactory能和Polly搭配使用岂不美哉其实是我们也能结合HttpClientFactory和Polly自己封装 不过微软已经把轮子造好了拿来用即可如下步骤4.1 引入对应版本的包引入Microsoft.Extensions.Http.Polly包这里使用的是.NetCore3.1所以引入对应的版本为3.X都行。4.2 Startup中注册服务的时候指定策略4.3 新增测试接口4.4 运行看效果在浏览器访问接口的时候对比控制台打印的消息会按照设定的时间间隔进行重试效果很明显的。对于IHttpClientFactory集成Polly的使用就先说到这关于其他策略的演示和单独使用Polly是一样的相信小伙伴参照上面案例演示一定能搞定。对于Polly的其他策略使用可以参考《Polly-故障处理和弹性应对很有一手》这篇文章说的挺详细。总结IHttpClientFactory的应用暂时就先说到这上面提到的功能只是平时自己常用的其他功能小伙伴可以去探究探究后续单独和小伙伴们一起扒扒源代码整理整理一下流程。如果现有项目需要用到HttpClient建议通过IHttpClientFactory的方式用起来方便、灵活主要是是能避免一些问题。博文源代码github地址https://github.com/zyq025/DotNetCoreStudyDemo一个被程序搞丑的帅小伙关注Code综艺圈识别关注跟我一起学~~~