【.NET】HttpClientの初回が遅いのはプロクシの自動検出が原因


はじめに

サーバーリプレース作業(Windows Server 2008R2 + Oracle 11g → Windows Server 2016 + PostgreSQL 9.6)で、Delphi5で作成されたアプリケーション(インターフェイス)をC#に作り替えました。
別会社によりC++で作成されたアプリケーションからパラメータを引数としてexe形式(Delphi5→C#)で呼び出され、Web(レガシーASP)で処理した結果を返すというものです。

性能検証してDelphi5で作成されたものと同性能であることを確認していました。ところがユーザーにいざ導入してみると体感として3秒くらい遅いとして却下され、Delphi5版をそのまま使用することになってしまいました。

ユーザーのPCは古いPCということもあって、C#(.NET Framework)にしたことで遅くなったのかと思って、Ngen.exe(ネイティブ イメージ ジェネレーター)など導入してもらったのですが結果は変わりませんでした。

調査

導入から4ヶ月くらい経ってようやくユーザーからC#版の調査の許可を得ること出来ました。
何が悪さをしているのか?

  • PC性能の問題
  • ネットワーク環境の問題

Windows 7のPCで確かに3秒くらいかかる現象が発生しました。しかし、Windows 10のPCでは現象が発生しませんでした。
Windows 7のPCは、こちらで持参し性能検証しても問題なかったPCでした。そのPCで現象が発生したということは性能の問題ではないということです。
ネットワークが怪しいということで、そういえばプロキシあたりが悪さをしているのかもとネット上で「プロキシ 遅い C#」で検索してみたところ、下記サイトが見つかりました。
プロキシ設定によりWebページへのアクセスを高速化するには?

プロキシを使用しないようにするconfigファイルの設定

xxx.exe.config
<configuration >
  <system.net>
    <defaultProxy>
      <proxy usesystemdefault="false" />
    </defaultProxy>
  </system.net>
</configuration>

この設定をexeと一緒に配置して実行したところ、3秒くらいかかる現象が発生しなくなりました。

会社に持ち帰り詳細に調査することにしました。会社とユーザーとの環境の違いとして、Widows 7のPCのサーバーへの接続方法があります。
これまで動的IPアドレスで接続していたのですが、固定IPアドレスに切り替えました。ただしプロキシは未指定です。
すると、会社でも固定IPアドレスにすると現象が発生することが分かりました。
また、IEのインターネットオプションの接続タブのLANの設定にて「設定を自動的に検出する」のチェックをオフにすることで、現象が発生しなくなることを確認しました。

原因

調査を踏まえて、どういうことなのかってことですね。キーワードとしては、「自動プロキシ検出」となります。

固定IPアドレスの場合、プロキシの自動検出機能によりプロキシ構成スクリプトの検出で遅くなっている。IPアドレスの自動取得の場合、DHCPサーバーがあることでプロキシ構成スクリプトがすぐ見つかるため遅くならない。

C#(.NET Framework)のWebClientクラスやHttpWebRequestクラスやHttpClientクラスでは、デフォルト設定では自動プロキシ検出が行われるようになっている。Delphi5で問題なかったのは、自動プロキシ検出など使わない方式だったためです。

対応

今回は、configファイルは使用せずにプログラム上で自動プロキシ検出をしないように修正した。

// プロキシを使用しない
HttpClientHandler handler = new HttpClientHandler();
handler.UseProxy = false;

using (var client = new HttpClient(handler))
{
    string uri = "http://localhost/";

今回はexe形式のインターフェイスで起動するたびにインスタンスを生成するため、HttpClientをusingで囲んでいますが、本来はHttpClientをusingで囲わない方がいいです。

最後に

性能検証でユーザー環境と同じ固定IPアドレスにするという観点は見逃していました。そんなところで問題が出るとは思わなかったです。
今回の対応はするとして、自動プロキシ検出に10〜15秒かかるという記事がある中で3秒くらいであること、持参したWindows 10では現象が発生してないことなど、まだ謎が残っている。これは何か分かり次第追記していきます。

.NET Frameworkの初回起動が遅いのは有名ですが、Web系アプリケーションだと自動プロキシ検出で余分にかかっているかも知れませんね。