随着基于 web 的应用和服务的增多,it 系统管理员肩上的责任也越来越重。当遇到不可预期的事件如流量达到高峰,流量增大或者内部的挑战比如硬件的损坏或紧急维修,无论如何,你的 web 应用都必须要保持可用性。甚至现在流行的 devops 和持续交付(cd)也可能威胁到你的 web 服务的可靠性和性能的一致性。

http 负载均衡是一个网络解决方案,它将进入的 http 或 https 请求分配至一组提供相同的 web 应用内容的服务器用于响应。通过将请求在这样的多个服务器间进行均衡,负载均衡器可以防止服务器出现单点故障,可以提升整体的可用性和响应速度。它还可以让你能够简单的通过添加或者移除服务器来进行横向扩展或收缩,对工作负载进行调整。
负载均衡可以提升服务器的使用性能和最大可用性,当你的服务器开始出现高负载时就可以使用负载均衡。或者你在为一个大型项目设计架构时,在前端使用负载均衡是一个很好的习惯。当你的环境需要扩展的时候它会很有用。
在这个教程中,我们会为 http web 服务器配置一个基于 haproxy 的负载均衡。
<a target="_blank"></a>
对于大多数的发行版,我们可以使用发行版的包管理器来安装 haproxy。
在 debian wheezy 中我们需要添加源,在 /etc/apt/sources.list.d 下创建一个文件 "backports.list" ,写入下面的内容
deb http://cdn.debian.net/debian wheezybackports main
刷新仓库的数据,并安装 haproxy
# apt get update
# apt get install haproxy
# yum install haproxy
本教程假设有两台运行的 http web 服务器,它们的 ip 地址是 192.168.100.2 和 192.168.100.3。我们将负载均衡配置在 192.168.100.4 的这台服务器上。
为了让 haproxy 工作正常,你需要修改 /etc/haproxy/haproxy.cfg 中的一些选项。我们会在这一节中解释这些修改。一些配置可能因 gnu/linux 发行版的不同而变化,这些会被标注出来。
你要做的第一件事是为 haproxy 配置日志功能,在排错时日志将很有用。日志配置可以在 /etc/haproxy/haproxy.cfg 的 global 段中找到他们。下面是针对不同的 linux 发型版的 haproxy 日志配置。
在 centos/rhel中启用日志,将下面的:
log 127.0.0.1 local2
替换为:
log 127.0.0.1 local0
然后配置 haproxy 在 /var/log 中的日志分割,我们需要修改当前的 rsyslog 配置。为了简洁和明了,我们在 /etc/rsyslog.d 下创建一个叫 haproxy.conf 的文件,添加下面的内容:
$modload imudp
$udpserverrun 514
$template haproxy,"%msg%\n"
local0.=info /var/log/haproxy.log;haproxy
local0.notice /var/log/haproxystatus.log;haproxy
local0.* ~
这个配置会基于 $template 在 /var/log 中分割 haproxy 日志。现在重启 rsyslog 应用这些更改。
# service rsyslog restart
在 debian 或 ubuntu 中启用日志,将下面的内容
log /dev/log local0
log /dev/log local1 notice
然后为 haproxy 配置日志分割,编辑 /etc/rsyslog.d/ 下的 haproxy.conf (在 debian 中可能叫 49-haproxy.conf),写入下面你的内容
下一步是设置 haproxy 的默认选项。在 /etc/haproxy/haproxy.cfg 的 default 段中,替换为下面的配置:
defaults
log global
mode http
option httplog
option dontlognull
retries 3
option redispatch
maxconn 20000
contimeout 5000
clitimeout 50000
srvtimeout 50000
上面的配置是当 haproxy 为 http 负载均衡时建议使用的,但是并不一定是你的环境的最优方案。你可以自己研究 haproxy 的手册并配置它。
web 集群配置定义了一组可用的 http 服务器。我们的负载均衡中的大多数设置都在这里。现在我们会创建一些基本配置,定义我们的节点。将配置文件中从 frontend 段开始的内容全部替换为下面的:
listen webfarm *:80
mode http
stats enable
stats uri /haproxy?stats
stats realm haproxy\ statistics
stats auth haproxy:stats
balance roundrobin
cookie lbn insert indirect nocache
option httpclose
option forwardfor
server web01 192.168.100.2:80 cookie node1 check
server web02 192.168.100.3:80 cookie node2 check
"listen webfarm *:80" 定义了负载均衡器监听的地址和端口。为了教程的需要,我设置为 "*" 表示监听在所有接口上。在真实的场景汇总,这样设置可能不太合适,应该替换为可以从 internet 访问的那个网卡接口。
上面的设置定义了,负载均衡器的状态统计信息可以通过 http://<load-balancer-ip>/haproxy?stats 访问。访问需要简单的 http 认证,用户名为 "haproxy" 密码为 "stats"。这些设置可以替换为你自己的认证方式。如果你不需要状态统计信息,可以完全禁用掉。
下面是一个 haproxy 统计信息的例子
"balance roundrobin" 这一行表明我们使用的负载均衡类型。这个教程中,我们使用简单的轮询算法,可以完全满足 http 负载均衡的需要。haproxy 还提供其他的负载均衡类型:
leastconn:将请求调度至连接数最少的服务器
source:对请求的客户端 ip 地址进行哈希计算,根据哈希值和服务器的权重将请求调度至后端服务器。
uri:对 uri 的左半部分(问号之前的部分)进行哈希,根据哈希结果和服务器的权重对请求进行调度
url_param:根据每个 http get 请求的 url 查询参数进行调度,使用固定的请求参数将会被调度至指定的服务器上
hdr(name):根据 http 首部中的 <name> 字段来进行调度
"cookie lbn insert indirect nocache" 这一行表示我们的负载均衡器会存储 cookie 信息,可以将后端服务器池中的节点与某个特定会话绑定。节点的 cookie 存储为一个自定义的名字。这里,我们使用的是 "lbn",你可以指定其他的名称。后端节点会保存这个 cookie 的会话。
上面是我们的 web 服务器节点的定义。服务器有由内部名称(如web01,web02),ip 地址和唯一的 cookie 字符串表示。cookie 字符串可以自定义,我这里使用的是简单的 node1,node2 ... node(n)
如果你完成了配置,现在启动 haproxy 并验证是否运行正常。
让 haproxy 开机自启,使用下面的命令
# chkconfig haproxy on
# service haproxy start
当然,防火墙需要开放 80 端口,像下面这样
# firewallcmd permanent zone=public addport=80/tcp
# firewallcmd reload
把下面内容加至 /etc/sysconfig/iptables 中的 ":output accept" 段中
a input m state state new m tcp p tcp dport 80 j accept
重启iptables:
# service iptables restart
启动 haproxy
不要忘了防火墙开放 80 端口,在 /etc/iptables.up.rules 中加入:
a input p tcp dport 80 j accept
让 haproxy 开机自动启动在 /etc/default/haproxy 中配置
enabled=1
启动 haproxy:
防火墙开放 80 端口:
# ufw allow 80
检查 haproxy 是否工作正常,我们可以这样做
首先准备一个 test.php 文件,文件内容如下
<?php
header('content-type: text/plain');
echo "server ip: ".$_server['server_addr'];
echo "\nx-forwarded-for: ".$_server['http_x_forwarded_for'];
?>
这个 php 文件会告诉我们哪台服务器(如负载均衡)转发了请求,哪台后端 web 服务器实际处理了请求。
将这个 php 文件放到两个后端 web 服务器的 web 根目录中。然后用 curl 命令通过负载均衡器(192.168.100.4)访问这个文件
$ curl http://192.168.100.4/test.php
我们多次运行这个命令此时,会发现交替的输出下面的内容(因为使用了轮询算法):
server ip: 192.168.100.2
x-forwarded-for: 192.168.100.4
server ip: 192.168.100.3
如果我们停掉一台后端 web 服务,curl 命令仍然正常工作,请求被分发至另一台可用的 web 服务器。
现在你有了一个完全可用的负载均衡器,以轮询的模式对你的 web 节点进行负载均衡。还可以去实验其他的配置选项以适应你的环境。希望这个教程可以帮助你们的 web 项目有更好的可用性。
你可能已经发现了,这个教程只包含单台负载均衡的设置。这意味着我们仍然有单点故障的问题。在真实场景中,你应该至少部署 2 台或者 3 台负载均衡以防止意外发生,但这不是本教程的范围。
如果你有任何问题或建议,请在评论中提出,我会尽我的努力回答。
原文发布时间:2015-01-28
本文来自云栖合作伙伴“linux中国”