Я новичок в 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 подключается к конкретной базе данных через именованный кластер серверов приложений, чтобы подтвердить сквозное соединение от веб-сервера через базу данных. Если проверка прошла успешно, проверка вернет 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, ожидайте строку 200 \ OK» (я пробовал использовать и без escape-символа «\» в строке), серверы отображаются вниз, и появляется ошибка «Неверный ответ уровня 7: проверка содержимого http. найдено пустое тело ответа ".
Когда я использую опцию «http-check expect status 200 OK», страница возврата будет успешной вне зависимости от того, равен ли текст статуса 200 (поскольку я предполагаю, что возврат check.aspx будет успешным, даже если вернет код 500).
Любая помощь будет принята с благодарностью.
Вот результат команды 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 <customErrors> tag within a "web.config" configuration file located in the root directory of the current web application. This <customErrors> tag should then have its "mode" attribute set to "Off".<br><br>
<table width=100% bgcolor="#ffffcc">
<tr>
<td>
<code><pre>
<!-- Web.Config Configuration File -->
<configuration>
<system.web>
<customErrors mode="Off"/>
</system.web>
</configuration></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 "defaultRedirect" attribute of the application's <customErrors> configuration tag to point to a custom error page URL.<br><br>
<table width=100% bgcolor="#ffffcc">
<tr>
<td>
<code><pre>
<!-- Web.Config Configuration File -->
<configuration>
<system.web>
<customErrors mode="RemoteOnly" defaultRedirect="mycustompage.htm"/>
</system.web>
</configuration></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.config вместо того, чтобы отправлять их в 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>»
Вот результат curl для неудачной проверки check.aspx (один из проверенных компонентов отключен, чтобы вызвать страницу с ошибкой).
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 <customErrors> tag within a "web.config" configuration file located in the root directory of the current web application. This <customErrors> tag should then have its "mode" attribute set to "Off".<br><br>
<table width=100% bgcolor="#ffffcc">
<tr>
<td>
<code><pre>
<!-- Web.Config Configuration File -->
<configuration>
<system.web>
<customErrors mode="Off"/>
</system.web>
</configuration></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 "defaultRedirect" attribute of the application's <customErrors> configuration tag to point to a custom error page URL.<br><br>
<table width=100% bgcolor="#ffffcc">
<tr>
<td>
<code><pre>
<!-- Web.Config Configuration File -->
<configuration>
<system.web>
<customErrors mode="RemoteOnly" defaultRedirect="mycustompage.htm"/>
</system.web>
</configuration></pre></code>
</td>
</tr>
</table>
<br>
</body>
</html>
* Connection #0 to host xx.xx.xx.xx left intact
Ваш конфиг идеален, за исключением одной мелочи. Вы не указали, что проверка работоспособности должна действительно получать запрашиваемую страницу, и в результате содержимое будет пустым.
По данным HAProxy документы, option httpchk
по умолчанию использует OPTIONS
метод, который не получает тело страницы.
вариант httpchk <uri>
опция httpchk <метод> <uri>
option httpchk <метод> <uri> <версия>Включите протокол HTTP для проверки работоспособности серверов
<метод>
- необязательный HTTP-метод, используемый с запросами. Если не задан, используется метод «OPTIONS», так как он обычно требует низкой обработки на сервере и его легко отфильтровать из журналов. Можно использовать любые методы, но придумывать нестандартные не рекомендуется.<uri>
- это URI, на который ссылаются HTTP-запросы. По умолчанию используется «/», который доступен по умолчанию практически на любом сервере, но может быть изменен на любой другой URI. Строки запроса разрешены.<версия>
- необязательная строка версии HTTP. По умолчанию используется «HTTP / 1.0», но некоторые серверы могут работать некорректно в HTTP 1.0, поэтому переключение на HTTP / 1.1 иногда может помочь. Обратите внимание, что поле Host является обязательным в HTTP / 1.1, и в качестве уловки его можно передать после "\ r \ n" после строки версии.
У вас есть несколько вариантов решения этой проблемы.
Вы можете изменить свой метод на 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
Я пробовал это на своем тестовом балансировщике нагрузки, и он работает, как ожидалось.
Ты можешь измениться check.aspx
испустить что-то кроме 200 OK
Статус HTTP при неудачной проверке.
Однажды мне нужно было проверить, запущена ли конкретная служба, потому что 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