日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

把HttpClient换成IHttpClientFactory之后,放心多了

發(fā)布時間:2023/12/4 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 把HttpClient换成IHttpClientFactory之后,放心多了 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

關(guān)于HttpClient的使用,個人在很多場景都派上用場了,比如在Winform或后臺服務(wù)中用其調(diào)用接口獲取和上傳數(shù)據(jù)、微服務(wù)中用其進行各服務(wù)之間的數(shù)據(jù)共享等,到目前來看,似乎還沒有出現(xiàn)過什么問題,但當(dāng)我看到官方文檔介紹使用方式時,再回顧之前項目的代碼,只能說沒出問題比較慶幸。

官方文檔介紹的大概意思如下:

HttpClient類使用比較簡單,但在某些情況下,許多開發(fā)人員卻并未正確使用該類;雖然此類實現(xiàn) IDisposable,但在 using 語句中聲明和實例化它并非首選操作,因為釋放 HttpClient 對象時,基礎(chǔ)套接字不會立即釋放,這可能會導(dǎo)致套接字耗盡問題,最終可能會導(dǎo)致 SocketException 錯誤。要解決此問題,推薦的方法是將 HttpClient 對象創(chuàng)建為單一對象或靜態(tài)對象

看到這,有一點點小不安(因為有些項目就是用using的方式),雖然目前的并發(fā)量還不至于導(dǎo)致SocketException異常的發(fā)生,但優(yōu)化得馬不停蹄的安排上;先來探探HttpClient,再來說說IHttpClientFactory。

正文

1. HttpClient好像一直沒用對

這里創(chuàng)建了一個控制臺程序進行測試(.NetCore3.1),代碼比較簡單,如下:

注:代碼中訪問的地址是用Nginx搭建在阿里云上搭建的站點,沒有做負(fù)載,所以看Socket狀態(tài)比較直觀。

上面代碼執(zhí)行完成之后就退出了,理論情況來說,上面程序執(zhí)行完畢之后,就不應(yīng)該占用資源啦,但通過netstat查看,的確還有Socket被占用,測試如下:

  • Windows 測試

    執(zhí)行如下命令看結(jié)果:

    netstat?-ano?|?findstr?TIME_WAIT
  • Linux測試

    我的云服務(wù)器之前就把.NetCore運行環(huán)境安裝好了,所以創(chuàng)建一個目錄,將編譯之后的文件通過Xftp將文件傳到云服務(wù)器,執(zhí)行以下命令即可:

    #?注意,這里指定啟動的是dll文件 dotnet?HttpClientConsoleDemo.dll

    查看端口情況,執(zhí)行以下命令即可:

    netstat?-ant?|?grep?TIME_WAIT?#?查看端口占用情況,找到狀態(tài)為TIME_WAIT

    TIME_WAIT 是主動關(guān)閉 TCP 連接的那一方出現(xiàn)的狀態(tài),系統(tǒng)會在 TIME_WAIT 狀態(tài)下等待 2MSL(maximum segment lifetime )后才能釋放連接(端口),目的是為了在TCP 四次揮手關(guān)閉連接機制中,保證 ACK 重發(fā)和丟棄延遲數(shù)據(jù)。按照解釋來看,這種做法也算是合情合理,保證數(shù)據(jù)傳輸嘛,但的確就是占用資源啦;具體關(guān)于網(wǎng)絡(luò)的相關(guān)知識,小伙伴們再去查閱一下。

經(jīng)過Windows和Linux的測試,大概差不多兩分鐘的時間Socket才完全被釋放,可想,如果是在高并發(fā)情況下,每臺機器的能開的連接數(shù)是有限的,使用這種方式進行服務(wù)和服務(wù)之間交互數(shù)據(jù),那肯定會出現(xiàn)問題。

而從理論上來講,只要HttpClient繼承了IDisposable接口,using塊執(zhí)行完就可以釋放掉資源,而HttpClient確實是間接繼承了IDisposable(直接繼承HttpMessageInvoker ,而HttpMessageInvoker繼承了IDisposable接口)。但在這里,使用HttpClient分配的Socket端口沒有得到及時釋放,為避免這個問題,官方推薦用靜態(tài)變量的方式使用HttpClient。

2. HttpClient換種方式好多啦

按照官方建議,將HttpClient變量定義為靜態(tài)變量,代碼如下:

運行程序,執(zhí)行netstat命令可以看到,資源占用情況明顯減少了。

如果使用靜態(tài)變量,看似解決了對應(yīng)的問題,但若想針對不同的請求設(shè)置不同的頭信息時就顯得不太方便,至于其他問題我暫時還沒遇見過(官方說這種方式不支持 DNS 變更)。先忽略其他問題,在.NetCore2.1開始出現(xiàn)了IHttpClientFactory ,據(jù)說是可以解決之前HttpClient面臨的一些問題,所以有需要用HttpClient的場景,直接用IHttpClientFactory 就妥啦,不信就來試試。

3. IHttpClientFactory用起來很給力

IHttpClientFactory是在.NETCore 2.1 開始提供的,默認(rèn)實現(xiàn)為 DefaultHttpClientFactory ,專門用于創(chuàng)建在應(yīng)用程序中用到的 HttpClient實例,自動維護內(nèi)部的HttpMessageHandler池及其生命周期。主要功能如下:

  • 支持命名化、類型化配置,集中管理配置,避免沖突;

  • 出站請求管道配置靈活,輕松實現(xiàn)對請求生命周期的管理;

  • 合理管理內(nèi)部HttpMessageHanlder的生命周期,避免資源占用和DNS刷新等問題

  • 內(nèi)置日志記錄器

接下來就來看看IHttpClientFactory到底有多給力;

3.1 控制臺演示

由于內(nèi)部需要使用了一些服務(wù),并且是采用DI的形式注入的,所以首先要把依賴注入的相關(guān)的包引入進來,代碼如下圖:

先來簡單看一下需要注冊的服務(wù),后續(xù)會好好說:

運行程序,然后通過以下命令查看端口占用情況;

netstat?-ano?|?findstr?TIME_WAIT????#?根據(jù)狀態(tài)去找 netstat?-ano?|?findstr?47.113.204.41?#?根據(jù)IP去找

最終沒有見到很明顯的資源占用情況,有沒有給力一點;還有一些比較常用的方式,在WebApi項目中一一演示(畢竟微服務(wù)中服務(wù)間通信還是比較常用的)。

3.2 WebApi項目演示
  • 創(chuàng)建一個API項目,注冊上相關(guān)服務(wù)即可

  • 增加一個測試控制器和測試接口

  • 運行看結(jié)果

    在API項目中是不是使用很簡單,因為項目本身就內(nèi)置了依賴注入相關(guān)功能,直接注冊上服務(wù)就可以使用;但這還體現(xiàn)不出有多給力,接下來繼續(xù)看看其他擴展方式的使用。

3.3 使用命名和類型模式區(qū)分不同HttpClient

使用步驟與3.2是一樣的,只是在注冊服務(wù)的時候不太一樣而已。

  • 命名模式

    注冊服務(wù)時代碼如下:

    增加一個測試接口,運行結(jié)果和上面一樣,只是HttpClient實例帶的頭信息不一樣啦,如下:

  • 類型模式

    其實類型模式原理和命名模式是一樣的,只是通過指定的類型名稱作為對應(yīng)HttpClient的名稱,減少了單獨定義名稱的步驟,所以顯得比較方便,個人比較喜歡這樣用。

    首先定義一個業(yè)務(wù)處理類,直接使用HttpClient,代碼如下:

    在Startup中注冊服務(wù)時代碼如下:

    增加一個測試接口,運行結(jié)果和上面一樣,調(diào)用過程如下:

    進入TypeHttpClientService對應(yīng)的方法,看到在注冊時設(shè)置的頭信息已經(jīng)生效了,如下:

    執(zhí)行完畢后,正常返回結(jié)果。類型模式不用單獨為HttpClient起名,而是直接用指定類型的類名作為默認(rèn)名,這樣就相對方便啦;摘取獲取類型名的源碼如下:

    小擴展:自定義的管道類沒有在Startup中手動注冊,為什么能直接注入使用?

    答案:在services.AddHttpClient注冊時,內(nèi)部已經(jīng)將對應(yīng)Type注冊好了,摘取代碼如下:

    除了能輕松區(qū)分不同HttpClient之外,如果需要在請求過程中加入其它公共業(yè)務(wù)處理,可以通過增加自定義管道邏輯輕松實現(xiàn)。

3.4 在請求管道中增加自定義管道邏輯
  • 先定義一個管道類(CustomDelegatingHandler),繼承DelegatingHandler,然后重寫SendAsync方法

  • 在Startup中注冊對應(yīng)的服務(wù),根據(jù)需要在HttpClient上加上自定義管道

  • 運行看效果,只有用到類型模式的HttpClient才會加入自定義管道,因為在配置的時候進行了針對性的配置

    這種方式是不是感覺和.NetCore的中間件管道很類似,編寫自定義管道其實就類似于在編寫一個中間件(至于原理,后續(xù)單獨扒扒源碼),輕松實現(xiàn)在請求前和響應(yīng)后做相關(guān)業(yè)務(wù)處理,就像上面加的RequestID,對分析分布式事務(wù)及微服務(wù)調(diào)用鏈跟蹤都有很大的幫助,所以小伙伴可以根據(jù)自己的需要封裝自己想要的HttpClient。

4. IHttpClientFactory 搭配Polly就完美了

只要牽涉到網(wǎng)絡(luò),要想服務(wù)百分百穩(wěn)定那是相當(dāng)難,比如常遇到的網(wǎng)絡(luò)不通、網(wǎng)絡(luò)波動、遠(yuǎn)端服務(wù)掛了、遠(yuǎn)端服務(wù)響應(yīng)慢等問題,都可能會影響用戶對系統(tǒng)的體驗,別慌,還記得之前說過專門為故障、彈性應(yīng)變設(shè)計的Polly庫嗎(詳情請看Polly-故障處理和彈性應(yīng)對很有一手),如果HttpClientFactory能和Polly搭配使用豈不美哉;

其實是我們也能結(jié)合HttpClientFactory和Polly自己封裝, 不過微軟已經(jīng)把輪子造好了,拿來用即可,如下步驟:

4.1 引入對應(yīng)版本的包

引入Microsoft.Extensions.Http.Polly包,這里使用的是.NetCore3.1,所以引入對應(yīng)的版本為3.X都行。

4.2 Startup中注冊服務(wù)的時候指定策略
4.3 新增測試接口
4.4 運行看效果

在瀏覽器訪問接口的時候,對比控制臺打印的消息,會按照設(shè)定的時間間隔進行重試,效果很明顯的。

對于IHttpClientFactory集成Polly的使用就先說到這,關(guān)于其他策略的演示,和單獨使用Polly是一樣的,相信小伙伴參照上面案例演示一定能搞定。對于Polly的其他策略使用,可以參考《Polly-故障處理和彈性應(yīng)對很有一手》這篇文章,說的挺詳細(xì)。

總結(jié)

IHttpClientFactory的應(yīng)用暫時就先說到這,上面提到的功能只是平時自己常用的,其他功能小伙伴可以去探究探究;后續(xù)單獨和小伙伴們一起扒扒源代碼,整理整理一下流程。

如果現(xiàn)有項目需要用到HttpClient,建議通過IHttpClientFactory的方式,用起來方便、靈活,主要是是能避免一些問題。

博文源代碼github地址:https://github.com/zyq025/DotNetCoreStudyDemo

一個被程序搞丑的帥小伙,關(guān)注"Code綜藝圈",識別關(guān)注跟我一起學(xué)~~~

總結(jié)

以上是生活随笔為你收集整理的把HttpClient换成IHttpClientFactory之后,放心多了的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。