Share via


HttpClient 사용 지침

System.Net.Http.HttpClient 클래스는 URI로 식별되는 리소스에서 HTTP 요청을 보내고 HTTP 응답을 받습니다. HttpClient 인스턴스는 해당 인스턴스에서 실행되는 모든 요청에 적용되는 설정의 컬렉션이며, 각 인스턴스는 자체 연결 풀을 사용하여 요청을 다른 인스턴스와 격리합니다. .NET Core 2.1부터 SocketsHttpHandler 클래스는 구현을 제공하여 모든 플랫폼에서 일관된 동작이 가능합니다.

DNS 동작

HttpClient는 연결을 설정할 때 DNS 항목만 확인합니다. DNS 서버에서 지정한 TTL(Time to Live) 기간을 추적하지 않습니다. 일부 시나리오에서 발생할 수 있듯이 DNS 항목이 정기적으로 변경되는 경우 클라이언트는 이러한 업데이트를 적용하지 않습니다. 이 문제를 해결하려면 연결을 바꿀 때 DNS 조회가 반복되도록 PooledConnectionLifetime 속성을 설정하여 연결 수명을 제한할 수 있습니다. 다음과 같은 예제를 참조하세요.

var handler = new SocketsHttpHandler
{
    PooledConnectionLifetime = TimeSpan.FromMinutes(15) // Recreate every 15 minutes
};
var sharedClient = new HttpClient(handler);

위의 HttpClient는 15분 동안 연결을 다시 사용하도록 구성되었습니다. PooledConnectionLifetime에 지정된 시간 범위가 경과하면 연결이 닫히고 새 연결이 만들어집니다.

풀링된 연결

HttpClient에 대한 연결 풀은 기본 SocketsHttpHandler에 연결됩니다. HttpClient 인스턴스가 삭제되면 풀 내의 기존 연결이 모두 삭제됩니다. 나중에 동일한 서버에 요청을 보내는 경우 새 연결을 다시 만들어야 합니다. 따라서 불필요한 연결 만들기로 인한 성능 저하가 발생합니다. 또한 TCP 포트는 연결 닫기 직후 해제되지 않습니다. (자세한 내용은 RFC 9293TCP TIME-WAIT 를 참조하세요.) 요청 속도가 높은 경우 사용 가능한 포트의 운영 체제 제한이 소진될 수 있습니다. 포트 고갈 문제를 방지하려면 가능한 한 많은 HTTP 요청에 인스턴스를 HttpClient 다시 사용하는 것이 좋습니다.

수명 관리 측면에서 권장 HttpClient 되는 사용을 요약하려면 수명이 긴 클라이언트와 집합 PooledConnectionLifetime (.NET Core 및 .NET 5 이상) 또는 에서 만든 IHttpClientFactory수명이 짧은 클라이언트를 사용해야 합니다.

  • .NET Core 및 .NET 5 이상:

    • 예상 DNS 변경 내용에 static 따라 원하는 간격(예: 2분)으로 PooledConnectionLifetime 설정된 단일 인스턴스 또는 싱글톤HttpClient 인스턴스를 사용합니다. 이렇게 하면 IHttpClientFactory의 오버헤드를 추가하지 않고 포트 소진 및 DNS 변경 문제가 모두 해결됩니다. 처리기를 모의해야 하는 경우 별도로 등록할 수 있습니다.

    제한된 수의 HttpClient 인스턴스만 사용하는 경우 이는 허용 가능한 전략이기도 합니다. 중요한 것은 각 요청이 각각 연결 풀을 포함하기 때문에 생성되고 삭제되지 않는다는 것입니다. 여러 프록시가 있는 시나리오 또는 쿠키 처리를 완전히 사용하지 않도록 설정하지 않고 쿠키 컨테이너를 분리하려는 경우에는 둘 이상의 인스턴스를 사용해야 합니다.

    • IHttpClientFactory를 사용하면 다양한 사용 사례에 대해 다르게 구성된 클라이언트가 여러 개 있을 수 있습니다. 그러나 팩터리에서 만든 클라이언트는 수명이 짧아야 하며 일단 만들어진 클라이언트는 팩터리에서 더 이상 제어할 수 없습니다.

      팩터리는 HttpMessageHandler 인스턴스를 풀링하며, 팩터리에서 새 HttpClient 인스턴스를 만들 때 풀에서 수명이 만료되지 않은 처리기를 다시 사용할 수 있습니다. 이 재사용은 소켓 소진 문제를 방지합니다.

      IHttpClientFactory가 제공하는 구성 가능성이 필요한 경우 형식화된 클라이언트 접근 방식을 사용하는 것이 좋습니다.

  • .NET Framework에서는 IHttpClientFactory를 사용하여 HttpClient 인스턴스를 관리합니다. 팩터리를 사용하지 않고 각 요청에 대한 새 클라이언트 인스턴스를 직접 만드는 경우 사용 가능한 포트를 소진할 수 있습니다.

    앱에 쿠키가 필요한 경우 자동 쿠키 처리를 사용하지 않도록 설정하거나 IHttpClientFactory을 사용하지 않는 것이 좋습니다. HttpMessageHandler 인스턴스를 풀링하면 CookieContainer 개체가 공유됩니다. 예상치 못한 CookieContainer 개체 공유로 잘못된 코드가 발생하는 경우가 많습니다.

수명을 관리하는 HttpClient 방법에 대한 자세한 내용은 지침을 참조하세요IHttpClientFactory.IHttpClientFactory

정적 클라이언트를 사용하는 복원력

다음 패턴을 사용하여 여러 복원력 파이프라인을 사용하도록 단일 클라이언트 또는 단일 클라이언트를 구성할 static 수 있습니다.

using System;
using System.Net.Http;
using Microsoft.Extensions.Http;
using Microsoft.Extensions.Http.Resilience;
using Polly;

var retryPipeline = new ResiliencePipelineBuilder<HttpResponseMessage>()
    .AddRetry(new HttpRetryStrategyOptions
    {
        BackoffType = DelayBackoffType.Exponential,
        MaxRetryAttempts = 3
    })
    .Build();

var socketHandler = new SocketsHttpHandler
{
    PooledConnectionLifetime = TimeSpan.FromMinutes(15)
};
var resilienceHandler = new ResilienceHandler(retryPipeline)
{
    InnerHandler = socketHandler,
};

var httpClient = new HttpClient(resilienceHandler);

앞의 코드가 하는 역할은 다음과 같습니다.

  • Microsoft.Extensions.Http.Resilience NuGet 패키지에 의존합니다.
  • 각 시도에서 기하급수적으로 백오프 지연 간격을 가져오는 재시도 파이프라인으로 구성된 일시적인 HTTP 오류 처리기를 지정합니다.
  • 에 대한 풀된 연결 수명(15분)을 socketHandler정의합니다.
  • 재시도 논리를 resilienceHandler 사용하여 해당 논리를 전달합니다socketHandler.
  • 지정된 .를 HttpClient 인스턴스화합니다 resilienceHandler.

Important

라이브러리는 Microsoft.Extensions.Http.Resilience 현재 실험적으로 표시되며 나중에 변경될 수 있습니다.

참고 항목