web-dev-qa-db-ja.com

HAProxyチェックはIIS

私はHAproxyを初めて使用し、考えられるすべてのフレーズをgoogledで読んだことがありますが、テストページが返すコンテンツをhaproxyに読み取らせることができません。

セットアップは次のとおりです。シングルアーム構成-1xCentOS 7 haproxy 1.5.14-2x Windows Server 2012r2 IIS 8.5

バックエンドサーバーの構成:

backend mt-http
balance     roundrobin
mode http
option httpchk /check.aspx?appserver=dev-cluster.xxxx.com&databaseserver=test.xxxx.com&database=######dev
http-check expect string 200\ OK
server  WebLB-test2 xx.xx.xx.xx:80 check
server  WebLB-test1 xx.xx.xx.xx:80 check

check.aspxは、名前付きアプリサーバークラスターを介して特定のデータベースに接続し、データベースを介したWebサーバーからのエンドツーエンドの接続を確認します。テストが成功した場合、チェックはWebページにテキストとして200OKを返します。コンポーネントの1つが使用できない場合、check.aspxは500エラーを返します。成功:

 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head><title>
        Mediatools Check
 </title></head>
 <body id="bodyID">200 OK</body>
 </html>

不合格:

 <html xmlns="http://www.w3.org/1999/xhtml">
 <head><title>
     Mediatools Check
 </title></head>
 <body id="bodyID">500 Internal Server Error</body>
 </html>

オプション「http-checkexpectstring 200\OK」を使用すると(文字列に「\」エスケープ文字を使用した場合と使用しない場合)、サーバーが表示され、「レイヤー7無効な応答:httpコンテンツチェック」というエラーが表示されます。空の応答本文が見つかりました。」

オプション「http-checkexpectstatus 200 OK」を使用すると、ステータステキストが200であるかどうかに関係なく、戻りページは成功します(500コードを返しても、check.aspxの戻りは成功すると思います)。

どんな助けでも大歓迎です。

Curl -vからの出力は次のとおりです。リクエストが長すぎるようです。

 curl -v xx.xx.xx.xx/yourDB/check.aspx?appserver=dev-cluster.yourdomain.com&databaserver=test.yourdomain.com&database=yourDBdev
 [1] 16077
 [2] 16078
 [root@dev-cluster log]# * About to connect() to xx.xx.xx.xx port 80 (#0)
 *   Trying xx.xx.xx.xx...
 * Connected to xx.xx.xx.xx (xx.xx.xx.xx) port 80 (#0)
 > GET /customer/check.aspx?appserver=dev-cluster.yourdomain.com HTTP/1.1
 > User-Agent: curl/7.29.0
 > Host: xx.xx.xx.xx
 > Accept: */*
 > 
 < HTTP/1.1 500 Internal Server Error
 < Cache-Control: private
 < Content-Type: text/html; charset=utf-8
 < Server: Microsoft-IIS/8.5
 < X-AspNet-Version: 4.0.30319
 < X-UA-Compatible: IE=EmulateIE7
 < Date: Wed, 17 Feb 2016 22:16:59 GMT
 < Content-Length: 3428
 < 
 <!DOCTYPE html>
 <html>
  <head>
    <title>Runtime Error</title>
    <meta name="viewport" content="width=device-width" />
    <style>
     body {font-family:"Verdana";font-weight:normal;font-size: .7em;color:black;} 
     p {font-family:"Verdana";font-weight:normal;color:black;margin-top: -5px}
     b {font-family:"Verdana";font-weight:bold;color:black;margin-top: -5px}
     H1 { font-family:"Verdana";font-weight:normal;font-size:18pt;color:red }
     H2 { font-family:"Verdana";font-weight:normal;font-size:14pt;color:maroon }
     pre {font-family:"Consolas","Lucida Console",Monospace;font-size:11pt;margin:0;padding:0.5em;line-height:14pt}
     .marker {font-weight: bold; color: black;text-decoration: none;}
     .version {color: gray;}
     .error {margin-bottom: 10px;}
     .expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }
     @media screen and (max-width: 639px) {
      pre { width: 440px; overflow: auto; white-space: pre-wrap; Word-wrap: break-Word; }
     }
     @media screen and (max-width: 479px) {
      pre { width: 280px; }
     }
    </style>
</head>

<body bgcolor="white">

        <span><H1>Server Error in '/customer' Application.<hr width=100% size=1 color=silver></H1>

        <h2> <i>Runtime Error</i> </h2></span>

        <font face="Arial, Helvetica, Geneva, SunSans-Regular, sans-serif ">

        <b> Description: </b>An application error occurred on the server. The current custom error settings for this application prevent the details of the application error from being viewed remotely (for security reasons). It could, however, be viewed by browsers running on the local server machine.
        <br><br>

        <b>Details:</b> To enable the details of this specific error message to be viewable on remote machines, please create a &lt;customErrors&gt; tag within a &quot;web.config&quot; configuration file located in the root directory of the current web application. This &lt;customErrors&gt; tag should then have its &quot;mode&quot; attribute set to &quot;Off&quot;.<br><br>

        <table width=100% bgcolor="#ffffcc">
           <tr>
              <td>
                  <code><pre>

 &lt;!-- Web.Config Configuration File --&gt;

  &lt;configuration&gt;
  &lt;system.web&gt;
    &lt;customErrors mode=&quot;Off&quot;/&gt;
&lt;/system.web&gt;
 &lt;/configuration&gt;</pre></code>

              </td>
           </tr>
        </table>

        <br>

        <b>Notes:</b> The current error page you are seeing can be replaced by a custom error page by modifying the &quot;defaultRedirect&quot; attribute of the application&#39;s &lt;customErrors&gt; configuration tag to point to a custom error page URL.<br><br>

        <table width=100% bgcolor="#ffffcc">
           <tr>
              <td>
                  <code><pre>

 &lt;!-- Web.Config Configuration File --&gt;

 &lt;configuration&gt;
 &lt;system.web&gt;
    &lt;customErrors mode=&quot;RemoteOnly&quot; defaultRedirect=&quot;mycustompage.htm&quot;/&gt;
&lt;/system.web&gt;
 &lt;/configuration&gt;</pre></code>

              </td>
           </tr>
        </table>

        <br>

</body>
 </html>
  * Connection #0 to Host xx.xx.xx.xx left intact

 [1]-  Done                    curl -v xx.xx.xx.xx/customer/check.aspx?appserver=dev-cluster.yourdomain.com
 [2]+  Done                    databaserver=test.yourdomain.com

もう一度大丈夫! Web開発者に、appserver、databaseserver、およびdatabaseパラメーターをcheck.aspxに送信する代わりに、web.configからプルしてもらいました。

新しい構成は次のようになります。

 backend mt-http
 balance     roundrobin
 mode http
 option httpchk GET /customer/check.aspx
 http-check expect status 200 OK
 server  WebLB-test2 xx.xx.xx.xx:80 check
 server  WebLB-test1 xx.xx.xx.xx:80 check

カールからの新しいリターン:

 curl -v xx.xx.xx.xx/pgglobal/check.aspx
 * About to connect() to xx.xx.xx.xx port 80 (#0)
 *   Trying xx.xx.xx.xx...
 * Connected to xx.xx.xx.xx (xx.xx.xx.xx) port 80 (#0)
 > GET /customer/check.aspx HTTP/1.1
 > User-Agent: curl/7.29.0
 > Host: xx.xx.xx.xx
 > Accept: */*
 > 
 < HTTP/1.1 200 OK
 < Cache-Control: private
 < Content-Type: text/html; charset=utf-8
 < Server: Microsoft-IIS/8.5
 < Set-Cookie: ASP.NET_SessionId=whvmaboyg03lsl3rd1gcsbxl; path=/; secure; HttpOnly
 < X-AspNet-Version: 4.0.30319
 < X-UA-Compatible: IE=EmulateIE7
 < Date: Wed, 17 Feb 2016 23:00:07 GMT
 < Content-Length: 162
 < 


 <!DOCTYPE html>

 <html xmlns="http://www.w3.org/1999/xhtml">
 <head><title>
Happiness Check
 </title></head>
 <body id="bodyID">Success</body>
 </html>
 * Connection #0 to Host xx.xx.xx.xx left intact

haproxyはまだ「レイヤー7の間違ったステータス:HTTPステータスチェックが<500>を返しました」と報告します

これは、失敗したcheck.aspxのcurl出力です(チェックされたコンポーネントの1つがオフになり、エラーページが強制されます)。

 curl -v xx.xx.xx.xx/Customer/check.aspx
 * About to connect() to xx.xx.xx.xx port 80 (#0)
 *   Trying xx.xx.xx.xx...
 * Connected to xx.xx.xx.xx (xx.xx.xx.xx) port 80 (#0)
 > GET /Customer/check.aspx HTTP/1.1
 > User-Agent: curl/7.29.0
 > Host: xx.xx.xx.xx
 > Accept: */*
 > 
 < HTTP/1.1 500 Internal Server Error
 < Cache-Control: private
 < Content-Type: text/html; charset=utf-8
 < Server: Microsoft-IIS/8.5
 < X-AspNet-Version: 4.0.30319
 < X-UA-Compatible: IE=EmulateIE7
 < Date: Thu, 18 Feb 2016 17:17:01 GMT
 < Content-Length: 3428
 < 
 <!DOCTYPE html>
 <html>
  <head>
    <title>Runtime Error</title>
    <meta name="viewport" content="width=device-width" />
    <style>
     body {font-family:"Verdana";font-weight:normal;font-size: .7em;color:black;} 
     p {font-family:"Verdana";font-weight:normal;color:black;margin-top: -5px}
     b {font-family:"Verdana";font-weight:bold;color:black;margin-top: -5px}
     H1 { font-family:"Verdana";font-weight:normal;font-size:18pt;color:red }
     H2 { font-family:"Verdana";font-weight:normal;font-size:14pt;color:maroon }
     pre {font-family:"Consolas","Lucida Console",Monospace;font-size:11pt;margin:0;padding:0.5em;line-height:14pt}
     .marker {font-weight: bold; color: black;text-decoration: none;}
     .version {color: gray;}
     .error {margin-bottom: 10px;}
     .expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }
     @media screen and (max-width: 639px) {
      pre { width: 440px; overflow: auto; white-space: pre-wrap; Word-wrap: break-Word; }
     }
     @media screen and (max-width: 479px) {
      pre { width: 280px; }
     }
    </style>
 </head>

 <body bgcolor="white">

        <span><H1>Server Error in '/Customer' Application.<hr width=100% size=1 color=silver></H1>

        <h2> <i>Runtime Error</i> </h2></span>

        <font face="Arial, Helvetica, Geneva, SunSans-Regular, sans-serif ">

        <b> Description: </b>An application error occurred on the server. The current custom error settings for this application prevent the details of the application error from being viewed remotely (for security reasons). It could, however, be viewed by browsers running on the local server machine.
        <br><br>

        <b>Details:</b> To enable the details of this specific error message to be viewable on remote machines, please create a &lt;customErrors&gt; tag within a &quot;web.config&quot; configuration file located in the root directory of the current web application. This &lt;customErrors&gt; tag should then have its &quot;mode&quot; attribute set to &quot;Off&quot;.<br><br>

        <table width=100% bgcolor="#ffffcc">
           <tr>
              <td>
                  <code><pre>

 &lt;!-- Web.Config Configuration File --&gt;

 &lt;configuration&gt;
  &lt;system.web&gt;
    &lt;customErrors mode=&quot;Off&quot;/&gt;
  &lt;/system.web&gt;
 &lt;/configuration&gt;</pre></code>

              </td>
           </tr>
        </table>

        <br>

        <b>Notes:</b> The current error page you are seeing can be replaced by a custom error page by modifying the &quot;defaultRedirect&quot; attribute of the application&#39;s &lt;customErrors&gt; configuration tag to point to a custom error page URL.<br><br>

        <table width=100% bgcolor="#ffffcc">
           <tr>
              <td>
                  <code><pre>

 &lt;!-- Web.Config Configuration File --&gt;

 &lt;configuration&gt;
  &lt;system.web&gt;
    &lt;customErrors mode=&quot;RemoteOnly&quot; defaultRedirect=&quot;mycustompage.htm&quot;/&gt;
  &lt;/system.web&gt;
 &lt;/configuration&gt;</pre></code>

              </td>
           </tr>
        </table>

        <br>

  </body>
 </html>
 * Connection #0 to Host xx.xx.xx.xx left intact
1
Joe Sutton

あなたの設定は、1つの小さなことを除いて完璧です。ヘルスチェックが要求しているページを実際にフェッチするように指定していないため、内容が空白になります。

HAProxy docs によると、option httpchkはデフォルトでOPTIONSメソッドを使用しますが、これはページの本文を取得しません。

オプションhttpchk <uri>
オプションhttpchk <メソッド> <uri>
オプションhttpchk <メソッド> <uri> <バージョン>

HTTPプロトコルを有効にして、サーバーの状態を確認します

<メソッド>
は、リクエストで使用されるオプションのHTTPメソッドです。設定されていない場合は、「OPTIONS」方式が使用されます。これは、通常、サーバー処理が少なくて済み、ログから簡単に除外できるためです。非標準的な方法を発明することは推奨されませんが、どのような方法でも使用できます。

<uri>
は、HTTPリクエストで参照されるURIです。デフォルトは「/」で、ほとんどすべてのサーバーでデフォルトでアクセスできますが、他のURIに変更することもできます。クエリ文字列を使用できます。

<バージョン>
はオプションのHTTPバージョン文字列です。デフォルトは「HTTP/1.0」ですが、一部のサーバーはHTTP 1.0で正しく動作しない可能性があるため、HTTP /1.1に変更すると役立つ場合があります。 HTTP/1.1ではHostフィールドは必須であり、トリックとして、バージョン文字列に続く「\ r\n」の後に渡すことができることに注意してください。

これを解決するには、いくつかのオプションがあります。

  1. メソッドをGETに変更できます。

    backend mt-http
      balance roundrobin
      mode http
      option httpchk GET /check.aspx?appserver=dev-cluster.xxxx.com&databaseserver=test.xxxx.com&database=######dev
      http-check expect string 200\ OK
      server  WebLB-test2 xx.xx.xx.xx:80 check
      server  WebLB-test1 xx.xx.xx.xx:80 check
    

    テストロードバランサーでこれを試しましたが、期待どおりに機能します。

  2. check.aspxを変更して、チェックが失敗したときに200 OKHTTPステータス以外のものを発行することができます。
    実際のアプリケーションがバックエンドでダウンしている場合でも、IISは常に200 OKを返すため、特定のサービスが実行されているかどうかを確認する必要がありました。そこで、それを行うための簡単なC#スクリプトを作成しました。

    <%@ Page Language="C#"%>
    <%@ Import Namespace="System" %>
    <%@ Import Namespace="System.ServiceProcess" %>
    <%@ Import Namespace="System.Net" %>
    <%  
    
    ServiceController sc = new ServiceController(Request.QueryString["service"]);
    
    switch (sc.Status)
    {
      case ServiceControllerStatus.Running:
        Response.StatusCode = (int)HttpStatusCode.OK;
        Response.ContentType = "text/plain";
        Response.Write("Running");
        break;
    
      default:
        Response.StatusCode = (int)HttpStatusCode.ServiceUnavailable;
        Response.ContentType = "text/plain";
        Response.Write("Failed");
        break;
    }
    %>
    

    あなたはそれをこうして使うでしょう:

    backend FooBar
      balance roundrobin
      mode http
      option httpchk GET /ServiceCheck/check.aspx?service=ServiceName
      http-check expect status 200
      server  WebLB-test2 xx.xx.xx.xx:80 check
      server  WebLB-test1 xx.xx.xx.xx:80 check
    
2
GregL