파티에 늦었지만이 까다로운 주제에 대한 학습 여정이 있습니다.
1. HttpClient 재사용에 대한 공식 옹호자는 어디에서 찾을 수 있습니까?
나는 경우 의미 HttpClient를 재사용하는 것은 의도
와 일을 매우 중요 , 그러한 옹호 더 나은 오히려 "고급 항목", "성능 (안티) 패턴"또는 거기에 다른 블로그 게시물의 많은에 숨겨진되지 않고, 자신의 API 문서에 설명되어 있습니다 . 그렇지 않으면 새로운 학습자가 너무 늦기 전에 그것을 어떻게 알아야합니까?
현재 (2018 년 5 월), "c # httpclient"를 인터넷 검색 할 때의 첫 번째 검색 결과 는 MSDN의이 API 참조 페이지를 가리키며 ,이 의도는 전혀 언급되지 않았습니다. 글쎄, 초보자를위한 여기 1 강의는 항상 MSDN 도움말 페이지 제목 바로 다음에 "기타 버전"링크를 클릭하면 아마도 "현재 버전"에 대한 링크를 찾을 수 있습니다. 이 HttpClient의 경우, 그 의도 설명이 포함 된 최신 문서로 이동
합니다 .
나도 올바른 문서 페이지를 찾을 수 없습니다이 주제에 새이었다 많은 개발자를 의심,이 기술이 널리 확산되지 않은 이유, 그리고 그들이 그것을 발견 할 때 사람들은 놀랐다
나중에 아마도, 하드 방식 .
2. (mis?) 개념 using
IDisposable
이것은 약간 주제에서 벗어나 있지만, 어떻게 비난하는 언급 한 블로그 게시물에있는 사람들을 볼 수있는 우연이 아니다, 지적 여전히 가치가있다 HttpClient
'의 IDisposable
그들이 사용하는 경향이 있습니다 인터페이스 using (var client = new HttpClient()) {...}
패턴을 다음 문제로 이어질는.
나는 그것이 "IDisposable 객체는 수명이 짧을 것으로 예상된다"는 무의미한 개념으로 귀결된다고 생각한다
.
그러나이 스타일로 코드를 작성할 때 확실히 수명이 짧은 것처럼 보입니다.
using (var foo = new SomeDisposableObject())
{
...
}
IDisposable에 대한 공식 문서
는 IDisposable
개체의 수명이 짧아야 한다고 언급하지 않습니다 . 정의에 따르면 IDisposable은 관리되지 않는 리소스를 해제 할 수있는 메커니즘 일뿐입니다. 더 이상 없습니다. 그런 의미에서 결국 폐기를 촉발 할 것으로 예상되지만 단기적으로 그렇게 할 필요는 없습니다.
따라서 실제 물체의 수명주기 요구 사항에 따라 폐기를 트리거 할시기를 올바르게 선택하는 것이 작업입니다. IDisposable을 오래 사용하는 것을 막을 수있는 것은 없습니다 :
using System;
namespace HelloWorld
{
class Hello
{
static void Main()
{
Console.WriteLine("Hello World!");
using (var client = new HttpClient())
{
for (...) { ... } // A really long loop
// Or you may even somehow start a daemon here
}
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
}
이 새로운 이해를 통해 이제 블로그 게시물 을 다시 방문 하면 "수정"이 HttpClient
한 번 초기화 되지만 절대 폐기하지 않는다는 것을 분명히 알 수 있습니다. 따라서 netstat 출력에서 연결이 ESTABLISHED 상태로 유지된다는 것을 알 수 있습니다. 제대로 닫히지 않았습니다. 닫히면 상태는 TIME_WAIT입니다. 실제로 전체 프로그램이 종료 된 후 하나의 연결 만 열면 크게 문제가되지 않으며 블로그 포스터는 여전히 수정 후에도 성능이 향상됩니다. 그러나 여전히 IDisposable을 비난하고 처분하지 않기로 선택하는 것은 개념적으로 올바르지 않습니다.
3. HttpClient를 정적 속성에 넣거나 단일 톤으로 넣어야합니까?
이전 섹션의 이해를 바탕으로 여기에 대한 답변이 "필수 사항은 아님"으로 명확 해 졌다고 생각합니다. HttpClient를 재사용하고 (이상적으로) 결국 폐기하는 한 코드를 구성하는 방법에 달려 있습니다.
유감스럽게도 현재 공식 문서 의 비고 섹션에 나오는 예조차도
엄격하게 올바른 것은 아닙니다. 처리되지 않을 정적 HttpClient 속성을 포함하는 "GoodController"클래스를 정의합니다. 무엇을 거역하는 예 부분에 또 다른 예는
강조한다 : "처분 호출 할 필요가 ... 그래서 응용 프로그램은 자원을 누설하지 않습니다."
마지막으로, 싱글 톤 자체에는 어려움이 없습니다.
"글로벌 변수가 좋은 아이디어라고 생각하는 사람은 몇 명입니까?
얼마나 많은 사람들이 싱글 톤이 좋은 생각이라고 생각합니까? 약간의, 몇개의, 가산 복수 명사 앞에 위치하는 수량 표현.
무엇을 제공합니까? 싱글 톤은 여러 글로벌 변수 일뿐입니다. "
-이 감동적인 연설에서 인용 한 "글로벌 스테이트와 싱글 톤"
PS : SqlConnection
이것은 현재의 Q & A와 관련이 없지만, 아마 알고있을 것입니다. SqlConnection 사용 패턴이 다릅니다. 당신은 도록 SqlConnection을 재사용 할 필요가 없습니다 그것의 연결 풀 나은 그런 식으로 처리 할 수 있기 때문에.
차이점은 구현 방식으로 인해 발생합니다. 각 HttpClient 인스턴스는 자체 연결 풀 ( 여기 에서 인용
)을 사용합니다. 그러나 이것 에 따르면 SqlConnection 자체는 중앙 연결 풀에 의해 관리됩니다 .
그리고 HttpClient에서와 마찬가지로 SqlConnection을 폐기해야합니다.