Là async HttpClient từ .Net 4.5 là một lựa chọn tồi cho các ứng dụng tải nặng?


130

Gần đây tôi đã tạo ra một ứng dụng đơn giản để kiểm tra thông lượng cuộc gọi HTTP có thể được tạo theo cách không đồng bộ so với cách tiếp cận đa luồng cổ điển.

Ứng dụng này có thể thực hiện một số lượng cuộc gọi HTTP được xác định trước và cuối cùng, nó sẽ hiển thị tổng thời gian cần thiết để thực hiện chúng. Trong các thử nghiệm của tôi, tất cả các cuộc gọi HTTP được thực hiện cho máy chủ IIS cục bộ của tôi và họ đã truy xuất một tệp văn bản nhỏ (kích thước 12 byte).

Phần quan trọng nhất của mã để triển khai không đồng bộ được liệt kê bên dưới:

public async void TestAsync()
{
    this.TestInit();
    HttpClient httpClient = new HttpClient();

    for (int i = 0; i < NUMBER_OF_REQUESTS; i++)
    {
        ProcessUrlAsync(httpClient);
    }
}

private async void ProcessUrlAsync(HttpClient httpClient)
{
    HttpResponseMessage httpResponse = null;

    try
    {
        Task<HttpResponseMessage> getTask = httpClient.GetAsync(URL);
        httpResponse = await getTask;

        Interlocked.Increment(ref _successfulCalls);
    }
    catch (Exception ex)
    {
        Interlocked.Increment(ref _failedCalls);
    }
    finally
    { 
        if(httpResponse != null) httpResponse.Dispose();
    }

    lock (_syncLock)
    {
        _itemsLeft--;
        if (_itemsLeft == 0)
        {
            _utcEndTime = DateTime.UtcNow;
            this.DisplayTestResults();
        }
    }
}

Phần quan trọng nhất của việc thực hiện đa luồng được liệt kê dưới đây:

public void TestParallel2()
{
    this.TestInit();
    ServicePointManager.DefaultConnectionLimit = 100;

    for (int i = 0; i < NUMBER_OF_REQUESTS; i++)
    {
        Task.Run(() =>
        {
            try
            {
                this.PerformWebRequestGet();
                Interlocked.Increment(ref _successfulCalls);
            }
            catch (Exception ex)
            {
                Interlocked.Increment(ref _failedCalls);
            }

            lock (_syncLock)
            {
                _itemsLeft--;
                if (_itemsLeft == 0)
                {
                    _utcEndTime = DateTime.UtcNow;
                    this.DisplayTestResults();
                }
            }
        });
    }
}

private void PerformWebRequestGet()
{ 
    HttpWebRequest request = null;
    HttpWebResponse response = null;

    try
    {
        request = (HttpWebRequest)WebRequest.Create(URL);
        request.Method = "GET";
        request.KeepAlive = true;
        response = (HttpWebResponse)request.GetResponse();
    }
    finally
    {
        if (response != null) response.Close();
    }
}

Chạy thử nghiệm cho thấy phiên bản đa luồng nhanh hơn. Phải mất khoảng 0,6 giây để hoàn thành cho 10k yêu cầu, trong khi một async mất khoảng 2 giây để hoàn thành cùng một lượng tải. Đây là một chút ngạc nhiên, bởi vì tôi đã mong đợi cái async sẽ nhanh hơn. Có lẽ đó là do thực tế là các cuộc gọi HTTP của tôi rất nhanh. Trong một kịch bản trong thế giới thực, nơi máy chủ sẽ thực hiện một hoạt động có ý nghĩa hơn và ở đó cũng cần có độ trễ mạng, kết quả có thể bị đảo ngược.

Tuy nhiên, điều thực sự làm tôi lo lắng là cách ứng xử của httpClient khi tải được tăng lên. Vì phải mất khoảng 2 giây để gửi 10k tin nhắn, tôi nghĩ rằng sẽ mất khoảng 20 giây để gửi số lượng tin nhắn gấp 10 lần, nhưng khi chạy thử nghiệm cho thấy cần khoảng 50 giây để gửi tin nhắn 100k. Hơn nữa, thường mất hơn 2 phút để gửi 200k tin nhắn và thường, một vài ngàn trong số chúng (3-4k) không thành công với ngoại lệ sau:

Không thể thực hiện thao tác trên ổ cắm vì hệ thống thiếu đủ không gian bộ đệm hoặc do hàng đợi đã đầy.

Tôi đã kiểm tra các bản ghi IIS và các hoạt động không thành công với máy chủ. Họ đã thất bại trong khách hàng. Tôi đã chạy thử nghiệm trên máy Windows 7 với phạm vi cổng phù hợp mặc định là 49152 đến 65535. Chạy netstat cho thấy khoảng 5-6k cổng đã được sử dụng trong các thử nghiệm, vì vậy về mặt lý thuyết nên có sẵn nhiều hơn. Nếu việc thiếu các cổng thực sự là nguyên nhân của các ngoại lệ, điều đó có nghĩa là netstat không báo cáo đúng tình huống hoặc HttClient chỉ sử dụng số lượng cổng tối đa sau đó bắt đầu ném ngoại lệ.

Ngược lại, cách tiếp cận đa luồng trong việc tạo các cuộc gọi HTTP hoạt động rất dễ đoán. Tôi mất khoảng 0,6 giây cho 10k tin nhắn, khoảng 5,5 giây cho 100k tin nhắn và như mong đợi khoảng 55 giây cho 1 triệu tin nhắn. Không có tin nhắn thất bại. Hơn nữa, trong khi nó chạy, nó không bao giờ sử dụng hơn 55 MB RAM (theo Trình quản lý tác vụ Windows). Bộ nhớ được sử dụng khi gửi tin nhắn tăng không đồng bộ theo tỷ lệ tải. Nó đã sử dụng khoảng 500 MB RAM trong các bài kiểm tra tin nhắn 200k.

Tôi nghĩ có hai lý do chính cho kết quả trên. Điều đầu tiên là httpClient dường như rất tham lam trong việc tạo kết nối mới với máy chủ. Số lượng cổng được sử dụng cao được báo cáo bởi netstat có nghĩa là nó có thể không được hưởng lợi nhiều từ việc giữ HTTP.

Thứ hai là dường như httpClient không có cơ chế điều tiết. Trong thực tế, điều này dường như là một vấn đề chung liên quan đến hoạt động không đồng bộ. Nếu bạn cần thực hiện một số lượng lớn các hoạt động, tất cả chúng sẽ được bắt đầu cùng một lúc và sau đó các phần tiếp theo của chúng sẽ được thực hiện khi chúng có sẵn. Về lý thuyết, điều này là ổn, bởi vì trong các hoạt động không đồng bộ, tải nằm trên các hệ thống bên ngoài nhưng như đã chứng minh ở trên, điều này không hoàn toàn đúng. Có một số lượng lớn các yêu cầu bắt đầu cùng một lúc sẽ tăng mức sử dụng bộ nhớ và làm chậm toàn bộ quá trình thực thi.

Tôi đã quản lý để có được kết quả tốt hơn, bộ nhớ và thời gian thực hiện khôn ngoan hơn, bằng cách giới hạn số lượng yêu cầu không đồng bộ tối đa với cơ chế trì hoãn đơn giản nhưng nguyên thủy:

public async void TestAsyncWithDelay()
{
    this.TestInit();
    HttpClient httpClient = new HttpClient();

    for (int i = 0; i < NUMBER_OF_REQUESTS; i++)
    {
        if (_activeRequestsCount >= MAX_CONCURENT_REQUESTS)
            await Task.Delay(DELAY_TIME);

        ProcessUrlAsyncWithReqCount(httpClient);
    }
}

Sẽ thực sự hữu ích nếu httpClient bao gồm một cơ chế giới hạn số lượng yêu cầu đồng thời. Khi sử dụng lớp Nhiệm vụ (dựa trên nhóm luồng .Net), việc điều tiết sẽ tự động đạt được bằng cách giới hạn số lượng luồng đồng thời.

Để có cái nhìn tổng quan hoàn chỉnh, tôi cũng đã tạo một phiên bản kiểm tra async dựa trên HttpWebRequest chứ không phải là httpClient và quản lý để thu được kết quả tốt hơn nhiều. Để bắt đầu, nó cho phép đặt giới hạn về số lượng kết nối đồng thời (với ServicePointManager.DefaultConnectionLimit hoặc thông qua cấu hình), có nghĩa là nó không bao giờ hết cổng và không bao giờ bị lỗi đối với bất kỳ yêu cầu nào (theo mặc định, httpClient , nhưng dường như bỏ qua cài đặt giới hạn kết nối).

Cách tiếp cận async httpWebRequest vẫn chậm hơn khoảng 50 - 60% so với phương pháp đa luồng, nhưng nó có thể dự đoán và đáng tin cậy. Nhược điểm duy nhất của nó là nó sử dụng một lượng lớn bộ nhớ dưới tải lớn. Ví dụ, cần khoảng 1,6 GB để gửi 1 triệu yêu cầu. Bằng cách giới hạn số lượng yêu cầu đồng thời (như tôi đã làm ở trên đối với HttpClient), tôi đã quản lý để giảm bộ nhớ đã sử dụng xuống chỉ còn 20 MB và có thời gian thực hiện chậm hơn 10% so với phương pháp đa luồng.

Sau bài thuyết trình dài này, các câu hỏi của tôi là: Có phải lớp httpClient từ .Net 4.5 là một lựa chọn tồi cho các ứng dụng tải chuyên sâu? Có cách nào để điều tiết nó, mà nên khắc phục các vấn đề tôi đề cập đến? Làm thế nào về hương vị không đồng bộ của HttpWebRequest?

Cập nhật (cảm ơn @Stephen Cleary)

Khi nó bật ra, HttpClient, giống như HttpWebRequest (dựa trên mặc định), có thể có số lượng kết nối đồng thời trên cùng một máy chủ bị giới hạn với ServicePointManager.DefaultConnectionLimit. Điều kỳ lạ là theo MSDN , giá trị mặc định cho giới hạn kết nối là 2. Tôi cũng đã kiểm tra xem phía tôi sử dụng trình gỡ lỗi chỉ ra rằng thực sự 2 là giá trị mặc định. Tuy nhiên, dường như trừ khi đặt rõ ràng một giá trị thành ServicePointManager.DefaultConnectionLimit, giá trị mặc định sẽ bị bỏ qua. Vì tôi không đặt giá trị cho nó một cách rõ ràng trong các thử nghiệm httpClient của mình, tôi nghĩ rằng nó đã bị bỏ qua.

Sau khi thiết lập ServicePointManager.DefaultConnectionLimit thành 100 HttpClient trở nên đáng tin cậy và có thể dự đoán được (netstat xác nhận rằng chỉ có 100 cổng được sử dụng). Nó vẫn chậm hơn async HttpWebRequest (khoảng 40%), nhưng lạ thay, nó sử dụng ít bộ nhớ hơn. Đối với thử nghiệm bao gồm 1 triệu yêu cầu, nó đã sử dụng tối đa 550 MB, so với 1,6 GB trong httpWebRequest không đồng bộ.

Vì vậy, trong khi httpClient kết hợp ServicePointManager.DefaultConnectionLimit dường như đảm bảo độ tin cậy (ít nhất là đối với kịch bản mà tất cả các cuộc gọi được thực hiện đối với cùng một máy chủ), có vẻ như hiệu suất của nó bị ảnh hưởng tiêu cực do thiếu cơ chế điều tiết thích hợp. Một cái gì đó sẽ giới hạn số lượng yêu cầu đồng thời ở một giá trị có thể định cấu hình và đặt phần còn lại vào hàng đợi sẽ làm cho nó phù hợp hơn nhiều cho các kịch bản có khả năng mở rộng cao.


4
HttpClientNên tôn trọng ServicePointManager.DefaultConnectionLimit.
Stephen Cleary

2
Những quan sát của bạn có vẻ đáng để nghiên cứu. Mặc dù vậy, có một điều khiến tôi bận tâm: Tôi nghĩ rằng việc phát hành hàng ngàn IO không đồng bộ cùng một lúc là rất khó khăn. Tôi sẽ không bao giờ làm điều này trong sản xuất. Thực tế là bạn không đồng bộ không có nghĩa là bạn có thể tiêu tốn nhiều tài nguyên khác nhau. (Các mẫu chính thức của microsofts cũng có một chút sai lệch về vấn đề đó.)
usr

1
Đừng tiết kiệm thời gian trì hoãn. Điều tiết ở mức tương tranh cố định mà bạn xác định theo kinh nghiệm. Một giải pháp đơn giản sẽ là SemaphoreSlim.WaitAsync mặc dù điều đó cũng không phù hợp với số lượng lớn các nhiệm vụ tùy ý.
usr

1
@FlorinDumitrescu Để điều chỉnh, bạn có thể sử dụng SemaphoreSlim, như đã đề cập hoặc ActionBlock<T>từ TPL Dataflow.
Svick

1
@svick, cảm ơn lời đề nghị của bạn. Tôi không quan tâm đến việc thực hiện thủ công một cơ chế cho giới hạn điều chỉnh / đồng thời. Như đã đề cập, việc thực hiện bao gồm trong câu hỏi của tôi chỉ để thử nghiệm và xác nhận một lý thuyết. Tôi không cố gắng cải thiện nó, vì nó sẽ không được sản xuất. Điều tôi quan tâm là nếu khung .Net cung cấp một cơ chế tích hợp để hạn chế sự tương tranh của các hoạt động IO không đồng bộ (bao gồm cả httpClient).
Florin Dumitrescu

Câu trả lời:


64

Bên cạnh các thử nghiệm được đề cập trong câu hỏi, gần đây tôi đã tạo ra một số thử nghiệm mới liên quan đến các cuộc gọi HTTP ít hơn nhiều (5000 so với 1 triệu trước đó) nhưng với các yêu cầu mất nhiều thời gian hơn để thực hiện (500 mili giây so với khoảng 1 mili giây trước đó). Cả hai ứng dụng thử nghiệm, một ứng dụng đa luồng đồng bộ (dựa trên HTTPWebRequest) và I / O không đồng bộ (dựa trên máy khách HTTP) tạo ra kết quả tương tự: khoảng 10 giây để thực thi sử dụng khoảng 3% CPU và 30 MB bộ nhớ. Sự khác biệt duy nhất giữa hai người thử nghiệm là một luồng đa luồng đã sử dụng 310 luồng để thực thi, trong khi luồng không đồng bộ chỉ 22.

Như một kết luận cho các thử nghiệm của tôi, các cuộc gọi HTTP không đồng bộ không phải là lựa chọn tốt nhất khi xử lý các yêu cầu rất nhanh. Lý do đằng sau đó là khi chạy một tác vụ có chứa một cuộc gọi I / O không đồng bộ, luồng mà tác vụ được bắt đầu sẽ thoát ngay khi cuộc gọi không đồng bộ được thực hiện và phần còn lại của tác vụ được đăng ký dưới dạng gọi lại. Sau đó, khi hoạt động I / O hoàn thành, cuộc gọi lại được xếp hàng để thực hiện trên luồng có sẵn đầu tiên. Tất cả điều này tạo ra một chi phí chung, giúp cho các hoạt động I / O nhanh trở nên hiệu quả hơn khi được thực hiện trên luồng khởi động chúng.

Các cuộc gọi HTTP không đồng bộ là một lựa chọn tốt khi xử lý các hoạt động I / O dài hoặc có khả năng dài bởi vì nó không khiến bất kỳ luồng nào bận rộn khi chờ các hoạt động I / O hoàn tất. Điều này làm giảm tổng số luồng được sử dụng bởi một ứng dụng cho phép sử dụng nhiều thời gian CPU hơn cho các hoạt động ràng buộc của CPU. Hơn nữa, trên các ứng dụng chỉ phân bổ số lượng luồng hạn chế (như trường hợp ứng dụng web), I / O không đồng bộ sẽ ngăn chặn sự suy giảm luồng của luồng xử lý, có thể xảy ra nếu thực hiện các cuộc gọi I / O một cách đồng bộ.

Vì vậy, async HttpClient không phải là nút cổ chai cho các ứng dụng tải chuyên sâu. Về bản chất, nó không phù hợp lắm cho các yêu cầu HTTP rất nhanh, thay vào đó, nó lý tưởng cho các yêu cầu dài hoặc có khả năng dài, đặc biệt là trong các ứng dụng chỉ có số lượng luồng hạn chế. Ngoài ra, đó là một cách thực hành tốt để hạn chế sự tương tranh thông qua ServicePointManager.DefaultConnectionLimit với giá trị đủ cao để đảm bảo mức độ song song tốt, nhưng đủ thấp để ngăn chặn sự suy giảm cổng phù du. Bạn có thể tìm thêm chi tiết về các bài kiểm tra và kết luận được trình bày cho câu hỏi này tại đây .


3
Làm thế nào nhanh là "rất nhanh"? 1ms? 100ms? 1.000ms?
Tim P.

Tôi đang sử dụng một cái gì đó giống như cách tiếp cận "không đồng bộ" của bạn để phát lại tải trên máy chủ web WebLogic được triển khai trên Windows, nhưng tôi đang gặp sự cố cạn kiệt cổng ephemical, khá nhanh chóng. Tôi chưa chạm vào ServicePointManager.DefaultConnectionLimit và tôi đang xử lý và tạo lại mọi thứ (HttpClient và phản hồi) cho mỗi yêu cầu. Bạn có biết điều gì có thể khiến các kết nối vẫn mở và làm cạn kiệt các cổng không?
Margarvanchi

@TimP. đối với các thử nghiệm của tôi, như đã đề cập ở trên, "rất nhanh" là các yêu cầu chỉ mất 1 mili giây để hoàn thành. Trong thế giới thực, điều này sẽ luôn chủ quan. Theo quan điểm của tôi, một cái gì đó tương đương với một truy vấn nhỏ trên cơ sở dữ liệu mạng cục bộ, có thể được coi là nhanh, trong khi một cái gì đó tương đương với một cuộc gọi API qua internet, có thể được coi là chậm hoặc có khả năng chậm.
Florin Dumitrescu

1
@Iravanchi, theo cách tiếp cận "không đồng bộ", yêu cầu gửi và xử lý phản hồi được thực hiện riêng. Nếu bạn có nhiều cuộc gọi, tất cả các yêu cầu sẽ được gửi rất nhanh và phản hồi sẽ được xử lý khi chúng đến. Vì bạn chỉ có thể loại bỏ các kết nối sau khi phản hồi của họ đã đến, một số lượng lớn các kết nối đồng thời có thể tích lũy và làm cạn kiệt các cổng phù du của bạn. Bạn nên giới hạn số lượng kết nối đồng thời tối đa bằng ServicePointManager.DefaultConnectionLimit.
Florin Dumitrescu

1
@FlorinDumitrescu, tôi cũng cho biết thêm rằng các cuộc gọi mạng về bản chất là không thể đoán trước. Những thứ chạy trong 10ms 90% thời gian có thể gây ra sự cố chặn khi tài nguyên mạng đó bị tắc nghẽn hoặc không có sẵn 10% thời gian khác.
Tim P.

27

Một điều cần xem xét có thể ảnh hưởng đến kết quả của bạn là với HttpWebRequest, bạn sẽ không nhận được Phản hồi và tiêu thụ luồng đó. Với HttpClient, theo mặc định, nó sẽ sao chép luồng mạng vào luồng bộ nhớ. Để sử dụng HttpClient theo cách tương tự như bạn hiện đang sử dụng HttpWebRquest, bạn cần phải làm

var requestMessage = new HttpRequestMessage() {RequestUri = URL};
Task<HttpResponseMessage> getTask = httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead);

Một điều khác là tôi không thực sự chắc chắn sự khác biệt thực sự, từ góc độ luồng, bạn đang thực sự thử nghiệm. Nếu bạn tìm hiểu sâu về httpClientHandler, nó chỉ đơn giản thực hiện Task.Factory.StartNew để thực hiện yêu cầu không đồng bộ. Hành vi luồng được ủy quyền cho bối cảnh đồng bộ hóa theo cách chính xác giống như ví dụ của bạn với ví dụ httpWebRequest được thực hiện.

Không còn nghi ngờ gì nữa, httpClient thêm một số chi phí như mặc định, nó sử dụng HttpWebRequest làm thư viện vận chuyển. Vì vậy, bạn sẽ luôn có thể có được sự hoàn hảo tốt hơn với một httpWebRequest trực tiếp trong khi sử dụng HttpClientHandler. Những lợi ích mà HttpClient mang lại là với các lớp tiêu chuẩn như HttpResponseMessage, HttpRequestMessage, HttpContent và tất cả các tiêu đề được gõ mạnh. Bản thân nó không phải là một tối ưu hóa hoàn hảo.


(câu trả lời cũ, nhưng) HttpClientcó vẻ dễ sử dụng và tôi nghĩ rằng không đồng bộ là cách để đi, nhưng dường như có nhiều "buts and ifs" xung quanh điều này. Có lẽ HttpClientnên viết lại để nó sẽ trực quan hơn để sử dụng? Hoặc là tài liệu đã thực sự nhấn mạnh những điều quan trọng về cách sử dụng nó một cách hiệu quả nhất?
mortb

@mortb, Flurl.Http flurl.io trực quan hơn để sử dụng trình bao bọc của
HTTPClient

1
@MichaelFreidgeim: Cảm ơn, mặc dù bây giờ tôi đã học được cách sống với HttpClient ...
mortb

17

Mặc dù điều này không trả lời trực tiếp phần 'không đồng bộ' trong câu hỏi của OP, nhưng điều này giải quyết một lỗi trong quá trình triển khai mà anh ta đang sử dụng.

Nếu bạn muốn ứng dụng của mình mở rộng quy mô, hãy tránh sử dụng các HTTPCl dựa trên cá thể. Sự khác biệt là LỚN! Tùy thuộc vào tải, bạn sẽ thấy số hiệu suất rất khác nhau. HttpClient được thiết kế để được sử dụng lại qua các yêu cầu. Điều này đã được xác nhận bởi những người trong nhóm BCL đã viết nó.

Một dự án gần đây tôi đã có là để giúp một nhà bán lẻ máy tính trực tuyến rất lớn và nổi tiếng mở rộng quy mô cho lưu lượng Thứ Sáu Đen / ngày lễ cho một số hệ thống mới. Chúng tôi gặp phải một số vấn đề về hiệu suất xung quanh việc sử dụng HttpClient. Vì nó thực hiện IDisposable, các nhà phát triển đã làm những gì bạn thường làm bằng cách tạo một thể hiện và đặt nó bên trong một using()câu lệnh. Khi chúng tôi bắt đầu tải thử nghiệm, ứng dụng đưa máy chủ đến đầu gối - vâng, máy chủ không chỉ là ứng dụng. Lý do là mọi phiên bản của HTTPClient đều mở Cổng hoàn thành I / O trên máy chủ. Do việc hoàn thiện không xác định của GC và thực tế là bạn đang làm việc với các tài nguyên máy tính trải rộng trên nhiều lớp OSI , việc đóng các cổng mạng có thể mất một thời gian. Trong thực tế hệ điều hành Windows bản thâncó thể mất tới 20 giây để đóng một cổng (theo Microsoft). Chúng tôi đã mở các cổng nhanh hơn mức chúng có thể bị đóng - cạn kiệt cổng máy chủ khiến CPU tăng 100%. Cách khắc phục của tôi là thay đổi httpClient thành một thể hiện tĩnh để giải quyết vấn đề. Vâng, nó là một tài nguyên dùng một lần, nhưng bất kỳ chi phí nào cũng lớn hơn nhiều so với sự khác biệt về hiệu suất. Tôi khuyến khích bạn thực hiện một số thử nghiệm tải để xem ứng dụng của bạn hoạt động như thế nào.

Cũng trả lời tại liên kết dưới đây:

Chi phí chung của việc tạo một httpClient mới cho mỗi cuộc gọi trong máy khách WebAPI là gì?

https://www.asp.net/web-api/overview/advified/calling-a-web-api-from-a-net-client


Tôi đã tìm thấy chính xác cùng một vấn đề tạo ra sự cạn kiệt cổng TCP trên máy khách. Giải pháp là thuê phiên bản HTTPClient trong thời gian dài nơi các cuộc gọi lặp được thực hiện, không tạo và loại bỏ cho mỗi cuộc gọi. Kết luận mà tôi đạt được là "Chỉ vì nó thực hiện Vứt bỏ, điều đó không có nghĩa là nó rẻ để loại bỏ nó".
PhillipH

Vì vậy, nếu httpClient là tĩnh và tôi cần thay đổi một tiêu đề cho yêu cầu tiếp theo, thì điều đó sẽ làm gì với yêu cầu đầu tiên? Có bất kỳ tác hại nào trong việc thay đổi HttpClient vì nó tĩnh - chẳng hạn như phát hành một HTTPClient.DefaultRequestHeaders.Accept.Clear (); ? Ví dụ: nếu tôi có người dùng đang xác thực thông qua mã thông báo, những mã thông báo đó cần được thêm làm tiêu đề theo yêu cầu cho API, trong đó là các mã thông báo khác nhau. Sẽ không có httpClient dưới dạng tĩnh và sau đó thay đổi tiêu đề này trên HttpClient có ảnh hưởng xấu không?
crizzwald

Nếu bạn cần sử dụng các thành viên thể hiện của HTTPClient như tiêu đề / cookie, v.v. thì bạn không nên sử dụng một HTTPClient tĩnh. Nếu không, dữ liệu cá thể của bạn (tiêu đề, cookie) sẽ giống nhau cho mọi yêu cầu - chắc chắn KHÔNG phải là những gì bạn muốn.
Dave Black

vì đây là trường hợp ... làm thế nào bạn có thể ngăn chặn những gì bạn mô tả ở trên trong bài đăng của bạn - chống lại tải? tải cân bằng và ném nhiều máy chủ vào nó?
crizzwald

@crizzwald - Trong bài viết của tôi, tôi đã lưu ý đến giải pháp được sử dụng. Sử dụng một ví dụ tĩnh của httpClient. Nếu bạn cần sử dụng tiêu đề / cookie trên một HTTPClient, tôi sẽ tìm cách sử dụng một giải pháp thay thế.
Dave Black
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.