HAProxy 检查不会检查 IIS 上的内容

HAProxy 检查不会检查 IIS 上的内容

我是 HAproxy 的新手,我已阅读了文档,并在 Google 上搜索了我能想到的所有可能的短语,但我无法让 haproxy 读取我的测试页面返回的内容。

设置如下:单臂配置 - 1x CentOS 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 服务器到数据库的端到端连接。如果测试成功,则检查在网页中以文本形式返回 200 OK。如果其中一个组件不可用,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-check expect string 200\ OK”时(我尝试过在字符串中使用和不使用“\”转义字符),服务器显示关闭,错误为“第 7 层无效响应:http 内容检查发现空响应正文”。

当我使用选项“http-check expect status 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 开发人员从 web.config 中提取 appserver、databaseserver 和 database 参数,而不是将它们发送到 check.aspx

新的配置如下所示:

 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 的新回报:

 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 输出(检查的组件之一已关闭以强制显示错误页面)。

 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

您的配置非常完美,除了一点小问题。您没有指定健康检查是否应该真正获取其请求的页面,因此内容将为空白。

根据 HAProxy文档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 有时可能会有所帮助。请注意,Host 字段在 HTTP/1.1 中是必需的,并且作为一种技巧,可以在版本字符串后面的“\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为发出除 HTTP 状态之外的其他内容。 我曾经需要检查某个特定服务是否正在运行,因为即使实际应用程序在后端关闭,IIS 也总会返回。所以我编写了一个简单的 C# 脚本来执行此操作:200 OK
    200 OK

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

相关内容