日韩欧美人妻无码精品白浆,夜夜嗨AV免费入口,国产欧美官网在线看,高校回应聋哑女生因长相完美被质疑

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開(kāi)發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

如何避免 HttpClient 丟失請(qǐng)求頭:通過(guò) HttpRequestMessage 解決并優(yōu)化

freeflydom
2024年11月7日 8:47 本文熱度 1277

在使用 HttpClient 發(fā)起 HTTP 請(qǐng)求時(shí),可能會(huì)遇到請(qǐng)求頭丟失的問(wèn)題,尤其是像 Accept-Language 這樣的請(qǐng)求頭丟失。這個(gè)問(wèn)題可能會(huì)導(dǎo)致請(qǐng)求的內(nèi)容錯(cuò)誤,甚至影響整個(gè)系統(tǒng)的穩(wěn)定性和功能。本文將深入分析這一問(wèn)題的根源,并介紹如何通過(guò) HttpRequestMessage 來(lái)解決這一問(wèn)題。

1. 問(wèn)題的背景:HttpClient的設(shè)計(jì)與共享機(jī)制

HttpClient 是 .NET 中用于發(fā)送 HTTP 請(qǐng)求的核心類(lèi),它是一個(gè)設(shè)計(jì)為可復(fù)用的類(lèi),其目的是為了提高性能,減少在高并發(fā)情況下頻繁創(chuàng)建和銷(xiāo)毀 HTTP 連接的開(kāi)銷(xiāo)。HttpClient 的復(fù)用能夠利用操作系統(tǒng)底層的連接池機(jī)制,避免了每次請(qǐng)求都要建立新連接的性能損失。

但是,HttpClient 復(fù)用的機(jī)制也可能導(dǎo)致一些問(wèn)題,尤其是在多線程并發(fā)請(qǐng)求時(shí)。例如,如果我們?cè)诠蚕淼?nbsp;HttpClient 實(shí)例上頻繁地修改請(qǐng)求頭,可能會(huì)導(dǎo)致這些修改在不同的請(qǐng)求之間意外地“傳遞”或丟失。

2. 常見(jiàn)問(wèn)題:丟失請(qǐng)求頭

假設(shè)我們有如下的代碼,其中我們希望在每次請(qǐng)求時(shí)設(shè)置 Accept-Language 頭:

using System.Net.Http;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace ConsoleApp9
{
    internal class Program
    {
        private static readonly JsonSerializerSettings serializerSettings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver(),
            NullValueHandling = NullValueHandling.Ignore
        };
        private static readonly HttpClient httpClient = new HttpClient(); // 復(fù)用HttpClient實(shí)例
        private static readonly SemaphoreSlim semaphore = new SemaphoreSlim(100); // 限制并發(fā)請(qǐng)求數(shù)量為100
        static async Task Main(string[] args)
        {
            List<Task> tasks = new List<Task>();
            int taskNoCounter = 1; // 用于跟蹤 taskno
            // 只使用一個(gè)HttpClient對(duì)象(全局共享)
            for (int i = 0; i < 50; i++)
            {
                tasks.Add(Task.Run(async () =>
                {
                    // 等待信號(hào)量,控制最大并發(fā)數(shù)
                    await semaphore.WaitAsync();
                    try
                    {
                        var postData = new
                        {
                            taskno = taskNoCounter++,
                            content = "等待翻譯的內(nèi)容"
                        };
                        var json = JsonConvert.SerializeObject(postData, serializerSettings);
                        var reqdata = new StringContent(json, Encoding.UTF8, "application/json");
                        // 設(shè)置請(qǐng)求頭語(yǔ)言
                        httpClient.DefaultRequestHeaders.Add("Accept-Language", "en-US");                      
                        // 發(fā)送請(qǐng)求
                        var result = await httpClient.PostAsync("http://localhost:5000/translate", reqdata);
                        // 讀取并反序列化 JSON 數(shù)據(jù)
                        var content = await result.Content.ReadAsStringAsync();
                        var jsonResponse = JsonConvert.DeserializeObject<Response>(content);
                        var response = jsonResponse.Data.Content;
                       
                        // 反序列化后,直接輸出解碼后的文本
                        Console.WriteLine($"結(jié)果為:{response}");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"請(qǐng)求失敗: {ex.Message}");
                    }
                    finally
                    {
                        // 釋放信號(hào)量
                        semaphore.Release();
                    }
                }));
            }
            await Task.WhenAll(tasks);
        }
    }
    // 定義與響應(yīng)結(jié)構(gòu)匹配的類(lèi)
    public class Response
    {
        public int Code { get; set; }
        public ResponseData Data { get; set; }
        public string Msg { get; set; }
    }
    public class ResponseData
    {
        public string Content { get; set; }
        public string Lang { get; set; }
        public int Taskno { get; set; }
    }
}


接收代碼如下:

from flask import Flask, request, jsonify
from google.cloud import translate_v2 as translate
app = Flask(__name__)
# 初始化 Google Cloud Translate 客戶端
translator = translate.Client()
@app.route('/translate', methods=['POST'])
def translate_text():
    try:
        # 從請(qǐng)求中獲取 JSON 數(shù)據(jù)
        data = request.get_json()
        # 獲取請(qǐng)求的文本內(nèi)容
        text = data.get('content')
        taskno = data.get('taskno', 1)
        # 獲取請(qǐng)求頭中的 Accept-Language 信息,默認(rèn)為 'zh-CN'
        accept_language = request.headers.get('Accept-Language', 'zh-CN')
        # 調(diào)用 Google Translate API 進(jìn)行翻譯
        result = translator.translate(text, target_language=accept_language)
        # 構(gòu)造響應(yīng)數(shù)據(jù)
        response_data = {
            "code": 200,
            "msg": "OK",
            "data": {
                "taskno": taskno,
                "content": result['translatedText'],
                "lang": accept_language
            }
        }
        # 返回 JSON 響應(yīng)
        return jsonify(response_data), 200
    except Exception as e:
        return jsonify({"code": 500, "msg": str(e)}), 500
if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port=5000)

 

Accept-Language 請(qǐng)求頭是通過(guò) httpClient.DefaultRequestHeaders.Add("Accept-Language", language) 來(lái)設(shè)置的。這是一個(gè)常見(jiàn)的做法,目的是為每個(gè)請(qǐng)求指定特定的語(yǔ)言。然而,在實(shí)際應(yīng)用中,尤其是當(dāng) HttpClient 被復(fù)用并發(fā)發(fā)送多個(gè)請(qǐng)求時(shí),這種方法可能會(huì)引發(fā)請(qǐng)求頭丟失或錯(cuò)誤的情況。

測(cè)試結(jié)果:每20個(gè)請(qǐng)求就會(huì)有一個(gè)接收拿不到語(yǔ)言,會(huì)使用默認(rèn)的zh-CN,這條請(qǐng)求就不會(huì)翻譯。在上面的代碼中,

3. 為什么會(huì)丟失請(qǐng)求頭?

丟失請(qǐng)求頭的問(wèn)題通常出現(xiàn)在以下兩種情況:

  • 并發(fā)請(qǐng)求之間共享 HttpClient 實(shí)例:當(dāng)多個(gè)線程或任務(wù)共享同一個(gè) HttpClient 實(shí)例時(shí),它們可能會(huì)修改 DefaultRequestHeaders,導(dǎo)致請(qǐng)求頭在不同請(qǐng)求之間互相干擾。例如,如果一個(gè)請(qǐng)求修改了 Accept-Language,它會(huì)影響到后續(xù)所有的請(qǐng)求,而不是每個(gè)請(qǐng)求都獨(dú)立使用自己的請(qǐng)求頭。

  • 頭部緩存問(wèn)題HttpClient 實(shí)例可能會(huì)緩存頭部信息。如果請(qǐng)求頭未正確設(shè)置,緩存可能會(huì)導(dǎo)致丟失之前設(shè)置的頭部。

在這種情況下,丟失請(qǐng)求頭或請(qǐng)求頭不一致的現(xiàn)象就會(huì)發(fā)生,從而影響請(qǐng)求的正確性和響應(yīng)的準(zhǔn)確性。

4. 解決方案:使用 HttpRequestMessage

為了解決這個(gè)問(wèn)題,我們可以使用 HttpRequestMessage 來(lái)替代直接修改 HttpClient.DefaultRequestHeadersHttpRequestMessage 允許我們?yōu)槊總€(gè)請(qǐng)求獨(dú)立地設(shè)置請(qǐng)求頭,從而避免了多個(gè)請(qǐng)求之間共享頭部的風(fēng)險(xiǎn)。

以下是改進(jìn)后的代碼:

using System.Net.Http;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace ConsoleApp9
{
    internal class Program
    {
        private static readonly JsonSerializerSettings serializerSettings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver(),
            NullValueHandling = NullValueHandling.Ignore
        };
        private static readonly HttpClient httpClient = new HttpClient(); // 復(fù)用HttpClient實(shí)例
        private static readonly SemaphoreSlim semaphore = new SemaphoreSlim(100); // 限制并發(fā)請(qǐng)求數(shù)量為100
        static async Task Main(string[] args)
        {
            List<Task> tasks = new List<Task>();
            int taskNoCounter = 1; // 用于跟蹤 taskno
            // 只使用一個(gè)HttpClient對(duì)象(全局共享)
            for (int i = 0; i < 50; i++)
            {
                tasks.Add(Task.Run(async () =>
                {
                    // 等待信號(hào)量,控制最大并發(fā)數(shù)
                    await semaphore.WaitAsync();
                    try
                    {
                        var postData = new
                        {
                            taskno = taskNoCounter++,
                            content = "等待翻譯的內(nèi)容"
                        };
                        var json = JsonConvert.SerializeObject(postData, serializerSettings);
                        var reqdata = new StringContent(json, Encoding.UTF8, "application/json");
                        // 使用HttpRequestMessage確保每個(gè)請(qǐng)求都可以單獨(dú)設(shè)置頭
                        var requestMessage = new HttpRequestMessage(HttpMethod.Post, "http://localhost:5000/translate")
                        {
                            Content = reqdata
                        };
                        // 設(shè)置請(qǐng)求頭
                        requestMessage.Headers.Add("Accept-Language", "en-US");
                        // 發(fā)起POST請(qǐng)求
                        var result = await httpClient.SendAsync(requestMessage);
                        // 讀取并反序列化 JSON 數(shù)據(jù)
                        var content = await result.Content.ReadAsStringAsync();
                        var jsonResponse = JsonConvert.DeserializeObject<Response>(content);
                        var response = jsonResponse.Data.Content;
                     
                        // 反序列化后,直接輸出解碼后的文本
                        Console.WriteLine($"結(jié)果為:{response}");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"請(qǐng)求失敗: {ex.Message}");
                    }
                    finally
                    {
                        // 釋放信號(hào)量
                        semaphore.Release();
                    }
                }));
            }
            await Task.WhenAll(tasks);
        }
    }
    // 定義與響應(yīng)結(jié)構(gòu)匹配的類(lèi)
    public class Response
    {
        public int Code { get; set; }
        public ResponseData Data { get; set; }
        public string Msg { get; set; }
    }
    public class ResponseData
    {
        public string Content { get; set; }
        public string Lang { get; set; }
        public int Taskno { get; set; }
    }
}
?

  

5. 解析解決方案:為何 HttpRequestMessage 更加可靠

  • 獨(dú)立請(qǐng)求頭HttpRequestMessage 是一個(gè)每個(gè)請(qǐng)求都可以獨(dú)立設(shè)置頭部的類(lèi),它允許我們?yōu)槊總€(gè) HTTP 請(qǐng)求單獨(dú)配置請(qǐng)求頭,而不會(huì)被其他請(qǐng)求所干擾。通過(guò)這種方式,我們可以確保每個(gè)請(qǐng)求都使用準(zhǔn)確的請(qǐng)求頭。

  • 高并發(fā)控制:當(dāng) HttpClient 實(shí)例被多個(gè)請(qǐng)求共享時(shí),HttpRequestMessage 確保每個(gè)請(qǐng)求都能夠獨(dú)立處理頭部。即使在高并發(fā)環(huán)境下,每個(gè)請(qǐng)求的頭部設(shè)置都是獨(dú)立的,不會(huì)相互影響。

  • 請(qǐng)求靈活性HttpRequestMessage 不僅可以設(shè)置請(qǐng)求頭,還可以設(shè)置請(qǐng)求方法、請(qǐng)求體、請(qǐng)求的 URI 等,這使得它比直接使用 DefaultRequestHeaders 更加靈活和可控。

6. 小結(jié):優(yōu)化 HttpClient 請(qǐng)求頭管理

總結(jié)來(lái)說(shuō),當(dāng)使用 HttpClient 時(shí),若多個(gè)請(qǐng)求共用一個(gè)實(shí)例,直接修改 DefaultRequestHeaders 會(huì)導(dǎo)致請(qǐng)求頭丟失或不一致的問(wèn)題。通過(guò)使用 HttpRequestMessage 來(lái)管理每個(gè)請(qǐng)求的頭部,可以避免這個(gè)問(wèn)題,確保請(qǐng)求頭的獨(dú)立性和一致性。

  • 使用 HttpRequestMessage 來(lái)獨(dú)立設(shè)置請(qǐng)求頭,是確保請(qǐng)求頭正確性的最佳實(shí)踐。

  • 復(fù)用 HttpClient 實(shí)例是提升性能的好方法,但要注意并發(fā)請(qǐng)求時(shí)請(qǐng)求頭可能會(huì)丟失或錯(cuò)誤,HttpRequestMessage 是解決這一問(wèn)題的有效工具。

轉(zhuǎn)自https://www.cnblogs.com/morec/p/18529308


該文章在 2024/11/7 8:47:54 編輯過(guò)
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專(zhuān)業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車(chē)隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開(kāi)發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類(lèi)企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷(xiāo)售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫(kù)管理,保質(zhì)期管理,貨位管理,庫(kù)位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved