关于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 会话,并显示单个会话中页面视图的数量。
Cookie 插入方法
在这种方法中,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标题,其值为S1
或S2
,基于后端响应了请求。
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 Prefix 方法
另一方面,如果您只想为特定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 使用了相同的连接来执行后续请求。