如何使用 HAProxy 在 Ubuntu VPS 上设置 HTTP 负载平衡

关于HAPROXY


HAProxy(高可用性代理)是一个开源负载平衡器,可以平衡任何TCP服务,特别适合HTTP负载平衡,因为它支持会话持久性和7层处理。

通过DigitalOcean(私人网络)(https://www.digitalocean.com/community/articles/how-to-set-up-and-use-digitalocean-private-networking),HAProxy可以配置为前端,通过私人网络连接来平衡两个VPS的负载。

预告片


我们将在这里使用三个VPS(滴滴):

Droplet 1 - 负载平衡器 主机名: haproxy OS: Ubuntu 公共IP: 1.1.1.1 私人IP: 10.0.0.100

Droplet 2 - 节点 1 主机名: lamp1 OS: LAMP 在Ubuntu 私人IP: 10.0.0.1

Droplet 2 - 节点 2 主机名: lamp2 OS: LAMP 在Ubuntu 私人IP: 10.0.0.2

安装 HAProxy


使用apt-get命令来安装 HAProxy。

1apt-get install haproxy

我们需要允许HAProxy通过 init 脚本启动。

1nano /etc/default/haproxy

启用选项设置为1

1ENABLED=1

要检查是否正确地执行HAProxy的 init脚本,没有任何参数。

1root@haproxy:~# service haproxy
2Usage: /etc/init.d/haproxy {start|stop|reload|restart|status}

配置 HAProxy


我们将移动默认配置文件,并创建自己的文件。

1mv /etc/haproxy/haproxy.cfg{,.original}

创建和编辑新的配置文件:

1nano /etc/haproxy/haproxy.cfg

让我们先将配置块按块添加到此文件中:

1global
2	log 127.0.0.1 local0 notice
3	maxconn 2000
4	user haproxy
5	group haproxy

在Ubuntu rsyslog已经安装和运行,但它不听任何IP地址。

maxconn指令规定了前端同时连接的数量.默认值为2000,应根据您的VPS配置调整。

用户指令将HAProxy流程更改到指定的用户/组。

 1defaults
 2	log global
 3	mode http
 4	option httplog
 5	option dontlognull
 6	retries 3
 7	option redispatch
 8	timeout connect 5000
 9	timeout client 10000
10	timeout server 10000

我们在本节中注明了默认值。要修改的值是各种时限指令.连接选项指定了等待VPS连接尝试成功的最大时间。

客户端服务器时间表适用于客户端或服务器在 TCP 流程中预期承认或发送数据时。

回收指令规定了连接故障后VPS上执行的回收次数。

选项重新发送允许在连接故障的情况下重新分配会话,因此如果VPS失效,会话粘度会被覆盖。

 1listen appname 0.0.0.0:80
 2	mode http
 3	stats enable
 4	stats uri /haproxy?stats
 5	stats realm Strictly\ Private
 6	stats auth A_Username:YourPassword
 7	stats auth Another_User:passwd
 8	balance roundrobin
 9	option httpclose
10	option forwardfor
11	server lamp1 10.0.0.1:80 check
12	server lamp2 10.0.0.2:80 check

这包括对前端和后端的配置。我们正在配置HAProxy以便在端口80上倾听appname,这只是识别应用程序的名称。stats指令允许连接统计页面,并通过使用stats auth指令规定的凭证来保护它。

此页面可以用stats uri中提到的URL查看,所以在这种情况下,它是http://1.1.1.1/haproxy?stats;此页面的演示文稿可以在这里查看(http://demo.1wt.eu)。

可用的选项是Round Robin(‘roundrobin’), Static Round Robin(‘static-rr’),Least Connections(‘leastconn’),Source(‘source’),URI(‘uri’)和URL参数(‘url_param’)。

有关每个算法的信息可以从 官方文件中获取。

服务器指令声明后端服务器,语法是:

1server <name> <address>[:port] [param*]

我们在这里提到的名称将出现在日志和警告中。有许多参数(http://cbonte.github.io/haproxy-dconv/configuration-1.4.html#5)由本指令支持,我们将在本文中使用检查cookie参数。

完成配置后,启动 HAProxy 服务:

1service haproxy start

测试负荷平衡和失败


要测试此设置,请在所有 Web 服务器上创建 PHP 脚本(后端服务器 - LAMP1 和 LAMP2 在这里)。

此分類上一篇: www/file.php

1<?php
2header('Content-Type: text/plain');
3echo "Server IP: ".$_SERVER['SERVER_ADDR'];
4echo "\nClient IP: ".$_SERVER['REMOTE_ADDR'];
5echo "\nX-Forwarded-for: ".$_SERVER['HTTP_X_FORWARDED_FOR'];
6?>

现在我们将使用 curl 并多次请求此文件。

1> curl http://1.1.1.1/file.php

服务器 IP: 10.0.0.1 客户端 IP: 10.0.0.100 X-Forwarded-for: 117.213.X.X

curl http://1.1.1.1/file.php

服务器 IP: 10.0.0.2 客户端 IP: 10.0.0.100 X-Forwarded-for: 117.213.X.X

curl http://1.1.1.1/file.php

服务器 IP: 10.0.0.1 客户端 IP: 10.0.0.100 X-For

请注意,HAProxy如何替代LAMP1和LAMP2之间的连接,这就是Round Robin的工作方式。我们在这里看到的客户端IP是负载平衡器的私人IP地址,而X-Forwarded-For标题是您的IP。

要查看故障转移是如何工作的,请前往 Web 服务器并停止服务:

1lamp1@haproxy:~#service apache2 stop

再次用弯曲发送请求,看看事情是如何工作的。

座谈会 静止


如果您的 Web 应用程序基于用户的登录会话提供动态内容(应用程序没有),访问者将因为 VPS 之间的连续切换而经历一些奇怪的事情。

我们将使用以下PHP代码来展示会话粘性是如何工作的。

此分類上一篇: www/session.php

 1<?php
 2header('Content-Type: text/plain');
 3session_start();
 4if(!isset($_SESSION['visit']))
 5{
 6        echo "This is the first time you're visiting this server";
 7        $_SESSION['visit'] = 0;
 8}
 9else
10        echo "Your number of visits: ".$_SESSION['visit'];

$_SESSION['visit']++;

echo "\nServer IP: ".$_SERVER['SERVER_ADDR']; echo "\nClient IP: ".$_SERVER['REMOTE_ADDR']; echo "\nX-Forwarded-for: ".$_SERVER['HTTP_X_FORWARDED_FOR']."\n"; print_r($_COOKIE); ?>

此代码创建一个 PHP 会话,并显示单个会话中页面视图的数量。

在这种方法中,HAProxy向客户端的所有响应都将包含一个设置Cookie:标题,其中后端服务器的名称作为其cookie值,因此,向前的客户端(网页浏览器)将包含此cookie及其所有请求,HAProxy将根据cookie值将请求转发到正确的后端服务器。

对于这种方法,您需要添加cookie指令,并在倾听下修改服务器指令。

1cookie SRVNAME insert
2   server lamp1 10.0.0.1:80 cookie S1 check
3   server lamp2 10.0.0.2:80 cookie S2 check

这导致HAProxy添加一个名为SRVNAME的cookie标题,其值为S1S2,基于后端响应了请求。

1service haproxy restart

使用curl来检查它是如何工作的。

 1> curl -i http://1.1.1.1/session.php
 2HTTP/1.1 200 OK
 3Date: Tue, 24 Sep 2013 13:11:22 GMT
 4Server: Apache/2.2.22 (Ubuntu)
 5X-Powered-By: PHP/5.3.10-1ubuntu3.8
 6Set-Cookie: PHPSESSID=l9haakejnvnat7jtju64hmuab5; path=/
 7Expires: Thu, 19 Nov 1981 08:52:00 GMT
 8Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
 9Pragma: no-cache
10Vary: Accept-Encoding
11Content-Length: 143
12Connection: close
13Content-Type: text/plain
14Set-Cookie: SRVNAME=S1; path=/

这是您第一次访问此服务器 服务器 IP: 10.0.0.1 客户端 IP: 10.0.0.100 X-Forwarded-for: 117.213.X.X Array ( )

这是我们提出的第一个请求,LAMP1 回应了它,正如我们从 Set-Cookie: SRVNAME=S1; path=/ 所看到的。

 1> curl -i http://1.1.1.1/session.php --cookie "PHPSESSID=l9haakejnvnat7jtju64hmuab5;SRVNAME=S1;"
 2HTTP/1.1 200 OK
 3Date: Tue, 24 Sep 2013 13:11:45 GMT
 4Server: Apache/2.2.22 (Ubuntu)
 5X-Powered-By: PHP/5.3.10-1ubuntu3.8
 6Expires: Thu, 19 Nov 1981 08:52:00 GMT
 7Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
 8Pragma: no-cache
 9Vary: Accept-Encoding
10Content-Length: 183
11Connection: close
12Content-Type: text/plain

您的访问次数: 1 服务器 IP: 10.0.0.1 客户端 IP: 10.0.0.100 X-Forwarded-for: 117.213.87.127 Array ( [PHPSESSID] => l9haakejnvnat7jtju64hmuab5 [VNAME] => S1 )

 1> curl -i http://1.1.1.1/session.php --cookie "PHPSESSID=l9haakejnvnat7jtju64hmuab5;SRVNAME=S1;"
 2HTTP/1.1 200 OK
 3Date: Tue, 24 Sep 2013 13:11:45 GMT
 4Server: Apache/2.2.22 (Ubuntu)
 5X-Powered-By: PHP/5.3.10-1ubuntu3.8
 6Expires: Thu, 19 Nov 1981 08:52:00 GMT
 7Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
 8Pragma: no-cache
 9Vary: Accept-Encoding
10Content-Length: 183
11Connection: close
12Content-Type: text/plain

您的访问次数: 2 服务器 IP: 10.0.0.1 客户端 IP: 10.0.0.100 X-Forwarded-for: 117.213.87.127 Array ( [PHPSESSID] => l9haakejnvnat7jtju64hmuab5 [VNAME] => S1 )

这两个请求都由 LAMP1 服务,并正确维护了会话. 如果您希望在 Web 服务器上的所有文件保持粘贴性,此方法非常有用。


另一方面,如果您只想为特定cookie提供粘贴性,或者不想为会话粘贴性设置单独的cookie,则前缀选项是为您设计的。

要使用此方法,请使用以下cookie指令:

1cookie PHPSESSID prefix

PHPSESSID可以被您自己的cookie名称取代,而服务器指令仍然与之前的配置相同。

现在让我们看看这是如何工作的。

 1> curl -i http://1.1.1.1/session.php
 2HTTP/1.1 200 OK
 3Date: Tue, 24 Sep 2013 13:36:27 GMT
 4Server: Apache/2.2.22 (Ubuntu)
 5X-Powered-By: PHP/5.3.10-1ubuntu3.8
 6Set-Cookie: PHPSESSID=S1~6l2pou1iqea4mnhenhkm787o56; path=/
 7Expires: Thu, 19 Nov 1981 08:52:00 GMT
 8Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
 9Pragma: no-cache
10Vary: Accept-Encoding
11Content-Length: 143
12Content-Type: text/plain

这是您第一次访问此服务器 服务器 IP: 10.0.0.1 客户端 IP: 10.0.0.100 X-Forwarded-for: 117.213.X.X Array ( )

请注意服务器cookieS1是如何预先设置到会话cookie。

 1> curl -i http://1.1.1.1/session.php --cookie "PHPSESSID=S1~6l2pou1iqea4mnhenhkm787o56;"
 2HTTP/1.1 200 OK
 3Date: Tue, 24 Sep 2013 13:36:45 GMT
 4Server: Apache/2.2.22 (Ubuntu)
 5X-Powered-By: PHP/5.3.10-1ubuntu3.8
 6Expires: Thu, 19 Nov 1981 08:52:00 GMT
 7Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
 8Pragma: no-cache
 9Vary: Accept-Encoding
10Content-Length: 163
11Content-Type: text/plain

您的访问次数: 1 服务器 IP: 10.0.0.1 客户端 IP: 10.0.0.100 X-Forwarded-for: 117.213.X.X Array ( [PHPSESSID] => 6l2pou1iqea4mnhenhkm787o56 )

 1> curl -i http://1.1.1.1/session.php --cookie "PHPSESSID=S1~6l2pou1iqea4mnhenhkm787o56;"
 2HTTP/1.1 200 OK
 3Date: Tue, 24 Sep 2013 13:36:54 GMT
 4Server: Apache/2.2.22 (Ubuntu)
 5X-Powered-By: PHP/5.3.10-1ubuntu3.8
 6Expires: Thu, 19 Nov 1981 08:52:00 GMT
 7Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
 8Pragma: no-cache
 9Vary: Accept-Encoding
10Content-Length: 163
11Content-Type: text/plain

您的访问次数: 2 服务器 IP: 10.0.0.1 客户端 IP: 10.0.0.100 X-Forwarded-for: 117.213.X.X Array ( [PHPSESSID] => 6l2pou1iqea4mnhenhkm787o56 )

我们可以清楚地看到,LAMP1 已经处理了这两个请求,并且该会话正在完美运作。

为 HAProxy 配置日志


当我们开始配置 HAProxy 时,我们添加了一行:‘log 127.0.0.1 local0 notice’ 将 syslog 消息发送到 localhost IP 地址,但默认情况下,Ubuntu 上的 rsyslog 不会听任何地址,所以我们必须让它这样做。

编辑 rsyslog 的 config 文件。

1nano /etc/rsyslog.conf

添加 / 编辑 / 无评论 以下几行:

1$ModLoad imudp
2$UDPServerAddress 127.0.0.1
3$UDPServerRun 514

现在 rsyslog 将在 UDP 端口 514 上工作,但所有 HAProxy 消息都将进入 `/var/log/syslog,所以我们必须将它们分开。

创建 HAProxy 日志的规则。

1nano /etc/rsyslog.d/haproxy.conf

添加以下一行。

1if ($programname == 'haproxy') then -/var/log/haproxy.log

现在重新启动 rsyslog 服务:

1service rsyslog restart

这将所有HAProxy消息和访问日志写入到/var/log/haproxy.log

在 HAProxy 中使用


倾听指令下,我们使用了option httpclose,它添加了一个连接:关闭标题,这告诉客户端(网页浏览器)在收到回复后关闭连接。

如果您想在 HAProxy 上启用 keep-alives,请将option httpclose行替换为:

1option http-server-close
2timeout http-keep-alive 3000

明智地设置持续时间,以便几个连接不会耗尽负荷平衡器的所有资源。

考验

Keepalives 可以通过同时发送多个请求来使用弯曲来测试。

 1> curl -v http://1.1.1.1/index.html http://1.1.1.1/index.html
 2* About to connect() to 1.1.1.1 port 80 (#0)
 3*   Trying 1.1.1.1... connected
 4> GET /index.html HTTP/1.1
 5> User-Agent: curl/7.23.1 (x86_64-pc-win32) libcurl/7.23.1 OpenSSL/0.9.8r zlib/1.2.5
 6> Host: 1.1.1.1
 7> Accept: */*
 8>
 9......[Output omitted].........
10* Connection #0 to host 1.1.1.1 left intact
11* Re-using existing connection! (#0) with host 1.1.1.1
12* Connected to 1.1.1.1 (1.1.1.1) port 80 (#0)
13> GET /index.html HTTP/1.1
14> User-Agent: curl/7.23.1 (x86_64-pc-win32) libcurl/7.23.1 OpenSSL/0.9.8r zlib/1.2.5
15> Host: 1.1.1.1
16> Accept: */*
17>
18.......[Output Omitted].........
19* Connection #0 to host 1.1.1.1 left intact
20* Closing connection #0

在此输出中,我们必须寻找一个行:与主机 1.1.1.1 重新使用现有连接!(#0),这表明 curl 使用了相同的连接来执行后续请求。

Published At
Categories with 技术
Tagged with
comments powered by Disqus