中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

有關.NET Core HttpClient請求異常的問題

發布時間:2021-06-15 15:22:41 來源:億速云 閱讀:174 作者:chen 欄目:編程語言

這篇文章主要講解了“有關.NET Core HttpClient請求異常的問題”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“有關.NET Core HttpClient請求異常的問題”吧!

場景:將相關廠家地磁設備(停車進出場)推送數據,轉發至對接方。

最近一個星期經過觀察會出現兩種異常情況,一種是請求連接操作被取消,另外一種則是請求處理過程中操作被取消,具體異常信息請見如下圖

有關.NET Core HttpClient請求異常的問題

有關.NET Core HttpClient請求異常的問題

我們知道HttpClient默認超時時間為100s,但項目默認設置請求超時時間為30s,初次分析異常情況來看,請求超時導致請求連接被取消異常,首先我telnet對接方端口通暢,于是乎與對接方交涉,是否存在從請求到對接方接口有額外前置處理,以及網絡是否存在波動等等,排查得知相關猜測都予以否決,網絡無任何問題

問題排查分析

既然網絡沒有任何問題,難道是對接方即服務端處理數據量巨大,導致請求應答超時?于是乎對接方甩出幾張最近消息接收數據

有關.NET Core HttpClient請求異常的問題

有關.NET Core HttpClient請求異常的問題

從上述兩張圖來看,最多的一天也才90來萬,最近幾天請求失敗的數據大概2百來條,從我們平臺打印日志來看,每秒請求大致是10個左右,通過HTTP對接完全可以承載。

然后,因為我們將數據(JSON,數據大小幾乎可以忽略不計)轉發到對接方,對接方拿到數據后不會進行任何額外處理,直接存儲,所以我們請求超時時間30s,怎么會導致超時而引發異常呢?很奇怪

沒轍了,只能拿起終極武器,tcp抓包分析,重新學習了tcp/ip協議族一波

WireShark抓包分析

為打開分析上述pcap文件,提前安裝抓包軟件WireShark最新版本,由于軟件項目部署在Linux上,我們通過如下命令進行抓包

tcpdump -i any port 1443 -w exception.pcap

有關.NET Core HttpClient請求異常的問題

從如下抓包信息可以直接知道,對接方使用了HTTPS協議,具體請看如下圖

有關.NET Core HttpClient請求異常的問題

如圖

默認打開如上圖所示,其中time為時間戳,為找到我們指定時間點(2021-06-04  15:46:17.296),通過tab:視圖-時間顯示格式-日期和時間

有關.NET Core HttpClient請求異常的問題

接下來我們找到包文件中導致請求被取消異常的具體時間節點(2021-06-04 15:46:17.296)

有關.NET Core HttpClient請求異常的問題

在TCP協議中RST表示復位,用于異常時關閉連接。在發送RST包關閉連接時,不必等待緩沖區的包都發出去,直接丟棄緩沖區的包而發送RST包。而接收端收到RST包后,也不必發送ACK包來確認。

好像有點眉頭了,繼續往下看

有關.NET Core HttpClient請求異常的問題

好家伙,結合這張圖來看,基本上可以得出結論:原來是我們平臺主動重置了連接,緊接著又開始了多次進行三次握手連接即(SYN、SYN/ACK、ACK)

示例代碼分析

推送邏輯是在類庫中使用HttpClient,所以沒有使用HttpClientFactory,因此定義靜態變量來使用HttpClient,而非每一個請求就實例化一個HttpClient

接下來我們來詳細分析項目示例代碼并對其進行改進

static class Program {     static HttpClient httpClient = CreateHttpClient();     static Program()     {         ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;          ServicePointManager.ServerCertificateValidationCallback = (message, cert, chain, error) => true,     }      static async Task Main(string[] args)     {         await httpClient.PostAsync("", new StringContent(""));     }      static HttpClient CreateHttpClient()     {         var client = new HttpClient(new HttpClientHandler         {             ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true         })         {             Timeout = TimeSpan.FromSeconds(30)         };          client.DefaultRequestHeaders.Accept.Clear();          client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));         client.DefaultRequestHeaders.Add("ContentType", "application/json");         return client;     } }

若對接方僅使用HTTPS協議,無需驗證證書,最好是忽略證書驗證,否則有可能會引起建立驗證證書連接異常,即添加

ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true

我們觀察上述代碼,有兩個地方都對證書驗證進行了設置,一個是在靜態構造函數中ServicePointManager(簡稱SP),另外則在實例化HttpClient構造函數中即HttpClientHandler(簡稱HCH),那么這二者是否有使用上的限制呢?

在.NET Framework中,內置的HttpClient建立在HttpWebRequest之上,因此可以使用SP來配置

在.NET Core中,通過SP配置證書信息僅影響HttpWebRequest,而對HttpClient無效,需通過HCH配置來達到相同目的

所以去除在靜態構造函數中對忽略證書的配置,改為在HttpClientHandler中

var client = new HttpClient(new HttpClientHandler {     ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true,     SslProtocols = SslProtocols.Tls12 })

回到本文的話題,為什么會重置連接即主動關閉連接呢?我們已分析過,和上述配置30s超時沒有關系,主要有兩方面原因

翻開并溫習《圖解HTTP》一書,如果請求頻繁,最好建立持久連接,減少TCP連接的重復建立和斷開所造成的額外開銷,從而減輕服務端負載即重用HTTP連接,也稱為Http  keep-alive,持久連接的特點是,只要任意一方沒有明確提出斷開連接,否則保持TCP連接狀態

配置keep-alive我們俗稱為保活機制,所以在默認請求頭中添加如下一行

//增加保活機制,表明連接為長連接 client.DefaultRequestHeaders.Connection.Add("keep-alive");

上述只是在報文頭中添加持久化連接標識,但不意味著就一定生效,因為默認是禁用持久化連接,所以為了保險起見,添加如下代碼

//啟用保活機制(保持活動超時設置為 2 小時,并將保持活動間隔設置為 1 秒。) ServicePointManager.SetTcpKeepAlive(true, 7200000, 1000);

有個讓我很疑惑的問題,通過查看設置啟用持久化連接源碼得知,這樣設置意義在哪里?沒弄明白,源碼如下

public static void SetTcpKeepAlive(bool enabled, int keepAliveTime, int keepAliveInterval) {     if (enabled)     {         if (keepAliveTime <= 0)         {             throw new ArgumentOutOfRangeException(nameof(keepAliveTime));         }         if (keepAliveInterval <= 0)         {             throw new ArgumentOutOfRangeException(nameof(keepAliveInterval));         }     } }

最關鍵的一點則是默認持久化連接數為2,非持久化連接為4

public class ServicePointManager  {      public const int DefaultNonPersistentConnectionLimit = 4;      public const int DefaultPersistentConnectionLimit = 2;       private ServicePointManager() { }  }

那么問題是否就已很明了,項目中使用非持久化連接,即連接為4,未深究源碼具體細節,大膽猜想一下,若連接大于4,是否會出現將此前連接主動關閉,重建新的連接請求呢?

最終我們講原始代碼修改為如下形式

static class Program {     static HttpClient httpClient = CreateHttpClient();      static Program()     {         //默認連接數限制為2,增加連接數限制         ServicePointManager.DefaultConnectionLimit = 512;          //啟用保活機制(保持活動超時設置為 2 小時,并將保持活動間隔設置為 1 秒。)         ServicePointManager.SetTcpKeepAlive(true, 7200000, 1000);     }      static async Task Main(string[] args)     {         await httpClient.PostAsync("", new StringContent(""));          Console.WriteLine("Hello World!");     }      static HttpClient CreateHttpClient()     {         var client = new HttpClient(new HttpClientHandler         {             ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true,             SslProtocols = SslProtocols.Tls12         })         {             Timeout = TimeSpan.FromSeconds(30)         };          client.DefaultRequestHeaders.Accept.Clear();         //增加保活機制,表明連接為長連接         client.DefaultRequestHeaders.Connection.Add("keep-alive");         client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));         client.DefaultRequestHeaders.Add("ContentType", "application/json");         return client;     } }

進行如上設置后,通過一天觀察,再未出現相關異常,至此問題解決告一段落,希望沒有后續......

強烈建議:利用HttpClient發送請求設置持久化連接和根據實際業務評估增加連接數,而非默認的持久化連接為2,非持久化連接為4,否則極易出現相關異常。

引發思考:利用HttpClientFactory創建HttpClient是否有默認連接限制,據我所知,好像可以通過屬性MaxConnectionsPerServer來配置

若非常清楚默認連接數限制,可能并算不上什么問題,也不存在如此諸多分析,不過對于我而言,收獲的是在問題排查過程中,對可能干擾信息的過濾、篩選、確認以及對網絡協議進一步的理解加深。

在.NET Core和.NET Framework中相關配置還是有些變化,最好是根據對應版本在官網上確認下

感謝各位的閱讀,以上就是“有關.NET Core HttpClient請求異常的問題”的內容了,經過本文的學習后,相信大家對有關.NET Core HttpClient請求異常的問題這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

邻水| 永宁县| 黄浦区| 麟游县| 巨鹿县| 枣阳市| 郴州市| 东海县| 二手房| 壤塘县| 上蔡县| 苏尼特右旗| 静宁县| 开化县| 兴海县| 铁力市| 富源县| 竹北市| 包头市| 遂溪县| 大方县| 彰化县| 津南区| 乳山市| 青川县| 宾阳县| 隆安县| 石城县| 随州市| 汝州市| 彰武县| 阳城县| 西宁市| 茶陵县| 靖宇县| 阿瓦提县| 元江| 团风县| 鄂尔多斯市| 梁山县| 民丰县|