ASP.NET Core 2.1のHttpClientFactory(Part 1)HttpClientFactory紹介

8084 ワード

原文:https://www.stevejgordon.co.uk/introduction-to-httpclientfactory-aspnetcore発表:2018年1月
ASP.NET Core 2.1では、開発者がHttpClientインスタンスを使用する際に発生する可能性のある問題を解決するのに役立つ新しいHttpClientFactory機能が登場します.

紹介する


私は2017年11月中旬からこの文章を書く準備をしていました.その時、私は初めて新しいHttpClientFactoryバージョンライブラリがGitHubに表示されていることに気づきました.私はその出現に好奇心を持って、そしてASPを知りたいです.NETチームが何をしていたのか、当時のリポジトリのコードを深く検討しました.それ以来、私はずっとこの問題に注意して、コードの更新、問題のフィードバックとコミュニティの討論に注目して、開発チームが絶えずその機能を改善しているのを見ています.
最近、この機能はより多くの議論を始め、Damian EdwardsとDavid FowlerがNDCロンドンで行った講演で言及した.実際、この紹介を書いた日、Jeff Fritzの生放送番組とASP.NET Community Standupで展示されています.Ryan Nowakはこの機能の主な開発者の一人で、彼は機能が十分に安定していると思って、みんなに展示することができます.
注意:この文章は.NET Core 2.1の公式プレビュー版の前にASPを使用する.NET Core 2.1と.NET Core SDKの毎晩構築バージョンが作成されています.したがって、これらのプレビューから受け取ったフィードバックに基づいて、公開プレビューの前と期間(来月中にこれらのコンテンツを取得したい)、2.1の最終リリースの前に変更が発生する可能性があります.

HttpClientFactoryとは?


ASPでNETチームによると、「HttpClientインスタンスを作成するための独善的な工場」であり、ASPである.NET Core 2.1が発表した新機能.過去にHttpClientを使用した経験に基づいて、いくつかの落とし穴に遭遇したことがあるか、問題があることに気づいていない可能性があります.
1つ目の問題は、コードにHttpClientsを作成しすぎると、2つの負の問題をもたらします.
  • は、接続ごとに独自のリモート・サーバ接続プールがあるため、効率的ではありません.これは、作成したクライアントごとにリモート・サーバに再接続するために追加のオーバーヘッドを支払う必要があることを意味します.
  • でさらに大きな問題に直面する可能性があるのは、短時間で多くのクライアントを作成した場合、Socket消費の問題に直面する可能性があります.一定時間使えるSocketには制限があります.HttpClientを使用して接続を開くと、最大240秒のTIME_が維持されます.WAITステータス(この期間、リモート・サーバからのパケットはすべて通過します).

  • HttpClientはIDisposableを実現し、通常、開発者はIDisposableオブジェクトを使用するときにusingブロックで作成し、使用後にオブジェクトが解放されることを保証します.もっとこの方面の情報を読みたいなら、ASP.NET Monstersは彼らの文章「HttpClientを誤って使用しており、ソフトウェアの安定性を失っている」とよく述べています.
    通常、優先的な方法は、接続を再利用できるようにHttpClientインスタンスを再利用することです.HttpClientは可変オブジェクトですが、変更しない限り、実際にはスレッドが安全で共有できます.従って、一般的な方法は、DIフレームワークを介して単一の例として登録するか、または静的インスタンスとしてコンテナを作成することである.
    しかし、これは新しい問題を生む.この方法はDNS生存時間(TTL)の設定を守らず、接続はDNSの更新を受けず、通信するサーバはアドレスを更新しません.
    場合によっては、複数のホスト(Hosts)を負荷平均として使用する可能性があります.時間が経つにつれて、一部のホストは消え、一部のホストは新しく追加されます.ホストが消えた場合、HttpClient接続のIPアドレスはリクエストに応答しません.このような問題の詳細については、「単一のHttpClient?注意して使用し、どのように解決するか」および「単一のHttpClientがDNS更新に従わない」を参照してください.
    HttpClientFactoryは、これらの問題を解決するために設計され、HttpClientインスタンスを管理および作成するための新しいバックグラウンドメカニズムを提供する.それは私たちのために「やるべきこと」をして、私たちが他のことに集中できるようにします.上の問題はすべてHttpClientを指しているが,実際に問題の根源はHttpClientが使用するHttpClientHandlerにある.HttpClientFactoryは、Handlersのライフサイクルを管理するために使用され、DNSが期限切れにならないようにプール(pool)を再利用できます.
    HttpClientを使用して最も消費される部分は、実際にはHttpClientHandlerと接続(Connection)を作成することです.プール(pool)に置くのは、システムでより効率的に使用するためです.HttpClientFactoryを使用してHttpClientを要求すると、実際には毎回新しいインスタンスが得られます.これは、その状態を変更する心配がないことを意味します.HttpClientは、接続を維持するためにプール(pool)に既存のHttpClientHandlerを使用する(または使用しない)ことができる.
    デフォルトでは、新しいHttpClientHandler(HttpMessageHandlerから派生)ごとに2分のライフサイクルで作成されます.ハンドラチェーンを作成するときに、名前付きクライアントごとに制御できます.ライフサイクルに達すると、ハンドラ(handler)はすぐに解放されず、期限切れのプールに格納されます.元のプロセッサチェーン(original handler chain)に基づくクライアントは、それを使用し続けることができます.バックグラウンド・ジョブでは、期限切れのプールをチェックして、プロセッサのすべての参照が範囲外であるかどうかを確認し、処理できます.ハンドラチェーン(handler chain)が期限切れになると、新しいクライアントに対する新しい要求はすべて新しいハンドラチェーンを取得します.
    この方法はよく仕事ができるが、しかし.NET Coreはさらに進みます.のNET Coreチームは、DNSをよりよく管理し、原則としてより長く維持できる新しいManagedHandlerを開発しています.これは、接続をより効率的に共有できることを意味します.この新しいハンドラ(handler)も、異なるオペレーティングシステムでより一貫して動作するように設計されている.この作業が完了するまで(2.1時間の範囲内である可能性があります)、上記のプロセッサプールは合理的な解決方法です.

    HttpClientFactoryの使用方法


    重要な説明:以下の機能とコードの例では、SDKの毎晩の構築バージョンと.NET CoreとASP.NET Coreライブラリでは、設定や使用方法については説明しません.この機能がどのように機能しているかを示すだけで、2.1の正式なリリース時に使用するかどうかを考慮できます.今日この点を試してみない限り、2.1プレビューがリリースされるまで待つことをお勧めします.来月ごろにします.
    このセクションでは、主にHttpClientFactoryの基本的な使い方を紹介します.簡単なWebAPIプロジェクトを作成し、csprojファイルを編集して新しいものにアップグレードします.NET CoreとASP.NET Core 2.1.まず、netcoreapp 2に基づいて設定する必要があります.1(まだ公式プレビューにはありません)、必要な2つのパッケージが含まれています.私たちのプロジェクトファイルは以下の通りです.
    "Microsoft.NET.Sdk.Web">
    
      
        netcoreapp2.1
      
    
      
        "Microsoft.AspNetCore.All" Version="2.1.0-preview1-28124" />
        "Microsoft.Extensions.Http" Version="2.1.0-preview1-28124" />
      
      
    

    次はStartupでcs登録サービス.HttpClientFactoryには、複数のServiceCollection拡張方式があります.どちらかを使用します.
    services.AddHttpClient();

    これは、IHttpClientFactoryの実装である必要なサービスを登録します.次に、ValuesControllerを更新してこの機能を使用します.
    [Route("api/[controller]")]
    public class ValuesController : Controller
    {
        private readonly IHttpClientFactory _httpClientFactory;
    
        public ValuesController(IHttpClientFactory httpClientFactory)
        {
            _httpClientFactory = httpClientFactory;
        }
    
        [HttpGet]
        public async Task Get()
        {
            var client = _httpClientFactory.CreateClient();
            var result = await client.GetStringAsync("http://www.google.com");
            return Ok(result);
        }
    }

    ここではまずIHttpClientFactoryへの依存を追加し,DIシステムからコントローラに注入する.IHttpClientFactoryでは、HttpClientインスタンスを要求および受信できます.
    Get操作では、HttpClientFactoryを使用してクライアントを作成します.内部では、HttpClientFactoryが新しいHttpClientを作成します.しかし、以前はリクエストごとに新しいHttpClientを作成するのは大変だと言っていたのではないでしょうか.しかし、実際にはこれは少し誤解されています.HttpClient自体が本格的な問題ではなく、HTTP呼び出しを実現するためのHttpClientHandlerであることが実際の問題である.HttpClientHandlerは、プライマリHttpClientが解放された後でも、外部サービスとの接続を開くために使用され、これらの接続は、オープンを維持し、socketsを阻止する.
    HttpClientFactoryは、これらのHttpClientHandlerインスタンスを集約し、ライフサイクルを管理して、私が前に述べた問題を解決します.HttpClientを要求するたびに、既存のHttpClientHandlerを使用する可能性がある(または使用しない可能性がある)新しいインスタンスが得られます.HttpClient自体はあまり重くないので大丈夫です.
    作成されると、HttpClientHandlersはプール(pool)に配置され、デフォルトでは約2分保持されます.これは、新しいCreateClientリクエストが1つのプロセッサを共有できるため、接続を共有できることを意味します.HttpClientが存在する場合、そのプロセッサは使用可能であり、接続を共有します.
    2分後、各HttpClientHandlerは期限切れとしてマークされます.有効期限が切れた状態は、新しいHttpClientインスタンスを作成するときに使用しないようにマークされます.ただし、他のHttpClientインスタンスが使用している可能性があるため、すぐには処理されません.HttpClientFactoryはバックグラウンドサービスを使用して期限切れのプロセッサを監視し、参照されなくなると正しく処理し、接続を閉じることができます.
    プール(pooling)は、DNS更新の問題を解決するために、長いライフサイクルのHttpClientHandlersインスタンスと保留中の接続を処理することができるsocket消費のリスクを低減するのに役立つ.これは合理的な折衷案だ.

    まとめ


    ここで紹介します.今後の記事では、いくつかの優れた機能が展示に値するため、HttpClientFactoryの高度な方法を深く検討します.名前付きHttpClientインスタンスの作成と、独自のタイプ化クライアントの作成を構成する方法を見てみましょう.これはこの機能の本当のハイライトです.この基本例では、HTTP呼び出しを最も正確かつ効率的に処理して、私たちの使用例を満たす方法を理解してください.クライアントのライフサイクルをどのように管理するか、DNSの問題が発生することを心配する必要はありません.ASP.でNET Core 2.1が正式にリリースされた後、これらの機能は生産環境に応用できる.