programing

WebAPI 클라이언트에서 호출당 새 HttpClient를 생성할 때 발생하는 오버헤드는 얼마입니까?

muds 2023. 5. 21. 12:03
반응형

WebAPI 클라이언트에서 호출당 새 HttpClient를 생성할 때 발생하는 오버헤드는 얼마입니까?

무엇이 되어야 합니까?HttpClientWebAPI 클라이언트의 수명?
한 가지 사례가 더 나은가요?HttpClient여러 통화에 대해?

생성 및 폐기 시 발생하는 오버헤드는 무엇입니까?HttpClient아래의 예와 같이 요청당. (http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-net-client) 에서 제공:

using (var client = new HttpClient())
{
    client.BaseAddress = new Uri("http://localhost:9000/");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    // New code:
    HttpResponseMessage response = await client.GetAsync("api/products/1");
    if (response.IsSuccessStatusCode)
    {
        Product product = await response.Content.ReadAsAsync<Product>();
        Console.WriteLine("{0}\t${1}\t{2}", product.Name, product.Price, product.Category);
    }
}

HttpClient여러 통화에 재사용되도록 설계되었습니다.여러 스레드에서도 마찬가지입니다.HttpClientHandler에는 통화 간에 재사용할 수 있는 자격 증명 및 쿠키가 있습니다.새로운 것을 갖는 것HttpClient인스턴스는 이러한 모든 것을 다시 설정해야 합니다. 고또리그.DefaultRequestHeaders속성에는 여러 호출을 위한 속성이 포함되어 있습니다.각 요청에 대해 해당 값을 재설정해야 할 경우 포인트가 손실됩니다.

의또 주른이의 또 주요 과 같습니다.HttpClient는 가할수있기다니입능을 추가하는 입니다.HttpMessageHandlers교차 절단 문제를 적용하기 위해 요청/응답 파이프라인에 추가합니다.이러한 기능은 로깅, 감사, 조절, 리디렉션 처리, 오프라인 처리, 메트릭 캡처에 사용될 수 있습니다.모든 종류의 다른 것들.각 요청에 대해 새 HttpClient가 생성되는 경우 각 요청에 대해 이러한 모든 메시지 처리기를 설정해야 하며, 이러한 처리기에 대한 요청 간에 공유되는 모든 응용 프로그램 수준 상태도 제공해야 합니다.

더을많록의 을 더 할수록.HttpClient기존 인스턴스를 재사용하는 것이 의미가 있다는 것을 알게 될 것입니다.

하지만, 가장 큰 문제는, 제 생각에.HttpClient클래스는 처분되고, 그것은 처분됩니다.HttpClientHandler로 닫힙니다.TCP/IP에서 ServicePointManager이는 각 요청이 새 요청과 함께 있다는 것을 의미합니다.HttpClient에서는 새 새항을설야합니다해를 설정해야 합니다.TCP/IP연결.

LAN에서 일반 HTTP를 사용하는 제가 테스트한 바로는 성능에 미치는 영향은 무시해도 될 정도입니다.나는 이것이 연결을 열어두는 기본 TCP 킵얼라이브가 있기 때문이라고 생각합니다.HttpClientHandler닫으려고 합니다.

인터넷을 통한 요청에 대해, 저는 다른 이야기를 보았습니다.매번 요청을 다시 열어야 하기 때문에 성능이 40% 이상 향상되었습니다.

나는 a에 대한 히트가 의심됩니다.HTTPS연결은 훨씬 더 나쁠 것입니다.

사용자가 연결하는 각 API에 대해 HttpClient의 인스턴스를 애플리케이션의 수명 동안 유지하는 것이 좋습니다.

애플리케이션을 확장하려면 그 차이가 엄청납니다!부하에 따라 매우 다른 성능 수치가 표시됩니다.Darrel Miller가 언급했듯이 HttpClient는 여러 요청에서 재사용되도록 설계되었습니다.이것은 그것을 쓴 BCL 팀의 사람들에 의해 확인되었습니다.

제가 최근에 진행한 프로젝트는 매우 크고 유명한 온라인 컴퓨터 소매업체가 일부 새로운 시스템을 위해 블랙 프라이데이/휴일 트래픽을 확장할 수 있도록 지원하는 것이었습니다.HttpClient 사용과 관련하여 몇 가지 성능 문제가 발생했습니다.구하기때에를 에.IDisposable개발자들은 인스턴스를 만들고 그것을 내부에 배치함으로써 당신이 보통 할 일을 했습니다.using()진술.일단 애플리케이션 로드 테스트를 시작하면 서버가 무릎을 꿇게 됩니다. 애플리케이션뿐만 아니라 서버도 무릎을 꿇게 됩니다.그 이유는 HttpClient의 모든 인스턴스가 서버에서 포트를 열기 때문입니다.GC의 비결정론적 최종화와 여러 OSI 계층에 걸쳐 있는 컴퓨터 리소스로 작업하기 때문에 네트워크 포트를 닫는 데 시간이 걸릴 수 있습니다.실제로 Windows OS 자체가 포트를 닫는 데 최대 20초가 걸릴 수 있습니다(마이크로소프트당).닫힐 수 있는 것보다 더 빨리 포트를 열고 있었습니다. 서버 포트가 소진되어 CPU가 100%로 떨어졌습니다.저의 해결책은 HttpClient를 문제를 해결하는 정적 인스턴스로 변경하는 것이었습니다.예, 이는 일회용 리소스이지만 모든 오버헤드는 성능 차이로 인해 훨씬 더 중요합니다.앱이 어떻게 작동하는지 확인하기 위해 로드 테스트를 수행하는 것이 좋습니다.

https://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client 에서 문서 및 예제를 보려면 WebAPI Guidance 페이지를 확인할 수도 있습니다.

이 상담에 특히 주의하십시오.

HttpClient는 한 번 인스턴스화되고 응용 프로그램의 수명 동안 재사용됩니다.특히 서버 응용 프로그램에서 모든 요청에 대해 새 HttpClient 인스턴스를 만들면 부하가 높을 때 사용할 수 있는 소켓 수가 소진됩니다.그러면 SocketException 오류가 발생합니다.

이 정적인 것을 가 있다고 되면,HttpClient에는 " " ", " ", ", ", ", " 를 해야 합니다.HttpRequestMessage하고 수으로 설합니다정에 합니다.HttpRequestMessage다음을 사용합니다.HttpClient:SendAsync(HttpRequestMessage requestMessage, ...)

UPDATE for .NET Core: 다음을 사용해야 합니다.IHttpClientFactory Injection을 "Dependency Injection"을 합니다.HttpClient예를 들면수명을 관리하며 명시적으로 폐기할 필요가 없습니다.자세한 내용은 ASP.NET Core의 IHTTP Client Factory를 사용하여 HTTP 요청 만들기를 참조하십시오.

은 다음과 같이 HttpClient재사용할 수 있습니다., 하나의 단, 일항재사를 HttpClient다중 스레드 응용 프로그램의 인스턴스는 다음과 같은 상태 저장 속성의 값을 변경할 수 없음을 의미합니다.BaseAddress그리고.DefaultRequestHeaders(따라서 응용프로그램 전체에서 일정한 경우에만 사용할 수 있습니다.)

한 하는 것입니다.HttpClient모든 것을 복제하는 클래스와 함께.HttpClient (methods)GetAsync,PostAsyncetc한 후 합니다.HttpClient하지만 그것은 꽤 지루합니다(확장 방법도 포장해야 할 것입니다). 다행히도 다른 방법이 있습니다. - 계속해서 새로운 것을 만듭니다.HttpClient인스턴스, 그러나 기본적인 요소를 재사용합니다.HttpClientHandler핸들러를 폐기하지 않도록 하십시오.

HttpClientHandler _sharedHandler = new HttpClientHandler(); //never dispose this
HttpClient GetClient(string token)
{
    //client code can dispose these HttpClient instances
    return new HttpClient(_sharedHandler, disposeHandler: false)         
    {
       DefaultRequestHeaders = 
       {
            Authorization = new AuthenticationHeaderValue("Bearer", token) 
       } 
    };
}

대용량 웹 사이트와 관련이 있지만 HttpClient와 직접 관련이 없습니다.모든 서비스에 아래 코드 조각이 있습니다.

        // number of milliseconds after which an active System.Net.ServicePoint connection is closed.
        const int DefaultConnectionLeaseTimeout = 60000;

        ServicePoint sp =
                ServicePointManager.FindServicePoint(new Uri("http://<yourServiceUrlHere>"));
        sp.ConnectionLeaseTimeout = DefaultConnectionLeaseTimeout;

출처: https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(System.Net.ServicePoint.ConnectionLeaseTimeout);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5.2);k(DevLang-csharp)&rd=true

"이 속성을 사용하여 ServicePoint 개체의 활성 연결이 무기한 열려 있지 않도록 할 수 있습니다.이 속성은 로드 밸런싱 시나리오와 같이 주기적으로 연결을 삭제하고 다시 설정해야 하는 시나리오를 대상으로 합니다.

기본적으로 요청에 대해 KeepAlive가 참이면 MaxIdleTime 속성은 비활성으로 인해 ServicePoint 연결을 닫을 시간 제한을 설정합니다.ServicePoint에 활성 연결이 있는 경우 MaxIdleTime은 영향을 받지 않으며 연결이 무기한으로 열려 있습니다.

ConnectionLeaseTimeout 속성이 -1이 아닌 값으로 설정되어 있고 지정된 시간이 경과한 후 해당 요청에서 KeepAlive를 false로 설정하여 요청을 처리한 후 활성 ServicePoint 연결이 닫힙니다.이 값을 설정하면 ServicePoint 개체에서 관리하는 모든 연결에 영향을 미칩니다."

오류 해결을 원하는 CDN 또는 다른 엔드포인트 뒤에 서비스가 있는 경우 이 설정은 발신자가 사용자를 새 대상으로 이동하는 데 도움이 됩니다.이 예에서는 장애 조치 후 60초 후에 모든 호출자가 새 엔드포인트에 다시 연결해야 합니다.따라서 종속 서비스(호출하는 서비스)와 해당 엔드포인트를 알아야 합니다.

한 가지 짚고 넘어가야 할 점은, "사용하지 않는" 블로그 노트는 단순히 기본 주소와 기본값이 아니라는 것입니다.고려해야 할 헤더입니다.HttpClient를 정적으로 만들면 요청 간에 전달되는 내부 상태가 있습니다.예:FedAuth 토큰(OAuth/OWIN/ 등을 사용하지 않는 이유는 무시)을 얻기 위해 HttpClient를 사용하여 타사에 인증하는 경우, 응답 메시지에 FedAuth에 대한 Set-Cookie 헤더가 있으며 이 헤더는 HttpClient 상태에 추가됩니다.사용자가 각 요청에 대해 이러한 쿠키를 관리하지 않는 한 API에 로그인할 다음 사용자는 마지막 사용자의 FedAuth 쿠키를 보냅니다.

사이먼 팀스의 블로그 게시물을 참조할 수도 있습니다. https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/

그렇지만HttpClient다릅니다.비록 그것이 그것을 구현할지라도.IDisposable인터페이스 실제로는 공유 객체입니다.세이프라는 합니다.의새인스만대신드는의 새 를 만드는 HttpClient 해 공 야 니 해 다 유 를 스 턴 스 일HttpClient응용 프로그램의 전체 수명 동안.그 이유를 알아보겠습니다.

로, 이이지만, 첫번문로, 이스는지만, 사니합다와 합니다.using은 최선의 . 이 당이처때진조최술다아선닙니선택이를 에도 마찬가지이기 때문입니다.HttpClient개체의 경우 기본 소켓이 즉시 해제되지 않으며 '심각한 소모'라는 심각한 문제가 발생할 수 있습니다.

▁issue▁second▁with다▁but있 두 번째 문제가 있습니다.HttpClient싱글톤 또는 정적 개체로 사용할 때 가질 수 있는 기능입니다. 정적인 경우가 .HttpClient 사람DNS변화들.

.net core에서는 HttpClientFactory에서 다음과 같은 작업을 수행할 수 있습니다.

public interface IBuyService
{
    Task<Buy> GetBuyItems();
}
public class BuyService: IBuyService
{
    private readonly HttpClient _httpClient;

    public BuyService(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    public async Task<Buy> GetBuyItems()
    {
        var uri = "Uri";

        var responseString = await _httpClient.GetStringAsync(uri);

        var buy = JsonConvert.DeserializeObject<Buy>(responseString);
        return buy;
    }
}

서비스 구성

services.AddHttpClient<IBuyService, BuyService>(client =>
{
     client.BaseAddress = new Uri(Configuration["BaseUrl"]);
});

여기에 있는 문서 및 예제

언급URL : https://stackoverflow.com/questions/22560971/what-is-the-overhead-of-creating-a-new-httpclient-per-call-in-a-webapi-client

반응형