A verificação HAProxy não verifica o conteúdo no IIS

1

Sou novo no HAproxy e li os documentos pesquisei todas as frases possíveis que pude pensar, mas não consigo haproxy ler o conteúdo que minha página de teste retorna.

Aqui está a configuração: Configuração de braço único - 1x CentOS 7 haproxy 1.5.14 - 2x Windows Server 2012r2 IIS 8.5

Configuração do servidor de back-end:

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 conecta-se a um banco de dados específico por meio de um cluster de servidor de aplicativos nomeado para confirmar a conectividade de ponta a ponta do servidor da Web por meio do banco de dados. Se o teste for bem-sucedido, a verificação retornará 200 OK em uma página da Web como texto. Se um dos componentes não estiver disponível, check.aspx retornará um erro 500. Sucesso:

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

Falha:

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

Quando eu uso a opção "http-check esperar string 200 \ OK" (tentei com e sem o caractere de escape "\" na string), os servidores aparecem e o erro é "Invalid Layer 7 Response: A verificação do conteúdo http encontrou o corpo da resposta vazia. "

Quando eu uso a opção "http-check esperar status 200 OK", a página de retorno é bem sucedida se o texto de status é 200 ou não (porque suponho, o retorno de check.aspx é bem-sucedido mesmo se retornar o código 500) .

Qualquer ajuda seria muito apreciada.

Aqui está a saída de um curl -v: Parece que o meu pedido é muito longo?

 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

Ok, mais uma vez! Eu fiz o desenvolvedor da Web puxar o parâmetro appserver, databaseserver e database do web.config em vez de enviá-los para o check.aspx

A nova configuração é assim:

 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

Novo retorno do Curl:

 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

O haproxy ainda relata "Status incorreto da camada 7: a verificação do status HTTP foi retornada < 500 >"

Aqui está a saída de onda em um check.aspx com falha (um dos componentes marcados é desligado para forçar a página de erro).

 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
    
por Joe Sutton 16.02.2016 / 23:30

1 resposta

2

Sua configuração é perfeita, exceto por uma pequena coisa. Você não especificou que a verificação de saúde deve buscar a página solicitada e, como resultado, o conteúdo ficará em branco.

De acordo com os docs do HAProxy, option httpchk , por padrão, usa o OPTIONS method, que não obtém o corpo da página.

option httpchk <uri>
option httpchk <method> <uri>
option httpchk <method> <uri> <version>

Enable HTTP protocol to check on the servers health

<method>
is the optional HTTP method used with the requests. When not set, the "OPTIONS" method is used, as it generally requires low server processing and is easy to filter out from the logs. Any method may be used, though it is not recommended to invent non-standard ones.

<uri>
is the URI referenced in the HTTP requests. It defaults to " / " which is accessible by default on almost any server, but may be changed to any other URI. Query strings are permitted.

<version>
is the optional HTTP version string. It defaults to "HTTP/1.0" but some servers might behave incorrectly in HTTP 1.0, so turning it to HTTP/1.1 may sometimes help. Note that the Host field is mandatory in HTTP/1.1, and as a trick, it is possible to pass it after "\r\n" following the version string.

Você tem algumas opções para resolver isso.

  1. Você pode alterar seu método para 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
    

    Eu tentei isso no meu balanceador de carga de teste e ele funciona como esperado.

  2. Você pode alterar check.aspx para emitir algo diferente de um status 200 OK HTTP quando as verificações falharem.
    Eu já tive a necessidade de verificar se um determinado serviço estava em execução, porque o IIS sempre retornava 200 OK , mesmo se o aplicativo real estivesse inativo em um back-end. Então eu escrevi um script C # simples para fazer exatamente isso:

    <%@ 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;
    }
    %>
    

    Você usaria assim:

    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
    
por 17.02.2016 / 17:09