一、HAproxy简介

HAProxy提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保持或七层处理。HAProxy运行在时下的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单安全的整合进您当前的架构中, 同时可以保护你的web服务器不被暴露到网络上。

HAProxy实现了一种事件驱动、单一进程模型,此模型支持非常大的并发连接数。多进程或多线程模型受内存限制 、系统调度器限制以及无处不在的锁限制,很少能处理数千并发连接。事件驱动模型因为在有更好的资源和时间管理的用户端(User-Space) 实现所有这些任务,所以没有这些问题。此模型的弊端是,在多核系统上,这些程序通常扩展性较差。这就是为什么他们必须进行优化以 使每个CPU时间片(Cycle)做更多的工作。

二、安装配置

安装

yum install haproxy -y


HAproxy简介_第1张图片

配置说明:

### 主配置文件是/etc/haproxy/haproxy.conf
### 配置文件主要有:
global settings: 全局配置段
  主要用于定义haproxy进程自身的工作特性;
proxies: 代理配置段
  backend: 后端服务器组
  frontend: 定义面向客户的监听的地址和端口,以及关联到的后端服务器组;
  listen: 组合方式直接定义frontend及相关的backend的一种机制;
defaults: 定义默认配置
#################################################################################
gloab的默认选项:
log         127.0.0.1 local2  
# 记录日志,此时要借助于本机的rsyslod的日志服务,需要开启udp端口监听
chroot      /var/lib/haproxy
pidfile     /var/run/haproxy.pid
maxconn     4000
user        haproxy
group       haproxy
daemon
stats socket /var/lib/haproxy/stats
#################################################################################
defaults配置选项:
mode                    http    # 工作模式,有TCP和http,代表4层代理、7层代理
log                     global
option                  httplog
option                  dontlognull
option http-server-close
option forwardfor       except 127.0.0.0/8
option                  redispatch
retries                 3       # 重试次数
timeout http-request    10s
timeout queue           1m
timeout connect         10s
timeout client          1m
timeout server          1m
timeout http-keep-alive 10s
timeout check           10s
maxconn                 3000   # 最大并发连接数

一、简单的实现负载均衡

实验主机 安装软件
172.16.10.9 haproxy,反向代理的前端
172.16.10.77 httpd,后端主机
172.16.10.1 httpd,后端主机
## 配置过程:
在172.16.10.1和172.16.10.77上:
yum install httpd -y
创建测试页面:
echo "[email protected]" > /var/www/html/index.html
echo "[email protected]" > /var/www/html/index.html
##############################################################

## 在172.16.10.9上配置,在配置文件中添加以下内容,就可以实现:
frontend  http *:80
    default_backend             web 
backend web 
    balance     roundrobin
    server  web1 172.16.10.77:80
    server  web2 172.16.10.1:80 
###############################################################

此时会出现负载均衡的效果:

HAproxy简介_第2张图片

此时查看后端web日志:

HAproxy简介_第3张图片

解决办法:

编辑http的配置文件中,修改以下内容:(修改记录的http的头部信息)
LogFormat "%h  %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
修改为:
LogFormat "\"%{X-Forwarded-For}i\"  %l %u %t \"%r\" %>s %b \"%{Referer}i\" 
\"%{User-Agent}i\"" combined

二、负载均衡算法介绍

在上面的的使用中,使用到了balance关键字,这个关键字的作用是指定负载均衡算法的。

### haproxy使用的调度算法:常用的
### 使用范围:defaults forntend backend listen
1、roundrobin: 相当于lvs的 wrr, 是一种dynamic调度算法,支持weight指定权重。所谓的动态是
可以再服务器运行中调整,慢启动。对后端服务器数目由限制 4096
2、static-rr: wrr, static调度算法,对后端服务器数目没有限制
3、leastconn: 类似于lvs的wlc, dynamic方法
4、source: 建议用于基于TCP模式调度,且不支持使用cookie插入模式时使用;
  由hash-type参数决定其为dynamic或者static等价于ipvs: sh,nginx: ip_hash
5、uri: 基于请求报文中的uri的左半部分(查询条件之前的部分)或全部的URI进行调度;
  常用于backend server为cache server的场景中;由hash-type参数决定其为dynamic或者static
6、url_params: 常用于后端服务器需要对用户进行认证的场景中;
  由hash-type参数决定其为dynamic或者static
7、hdr():根据用户请求报文中,指定的http首部的值进行调度
  hdr(host):常用于实现将对同一个虚拟主机的请求始终发往同个backend server;
  use_domain_only: 在计算hash值时仅使用域名;由hash-type参数决定其为dynamic或者static

hash_type的取值有:

map-based:hash表是一个包含了所有在线服务器的静态数组。

挑选服务器是根据其在数组中的位置进行的,因此,当一台服务器宕机或添加了一台新的服务器时,
    大多数连接将会被重新派发至一个与此前不同的服务器上。

    对于缓存服务器的工作场景来说,此方法不适用。

consistent:hash表是一个由各服务器填充而成的树状结构;

基于hash键在hash树中查找相应的服务器时,最近的服务器将被选中。此方法是动态的,
    支持在运行时修改服务器权重。
    
添加一个新的服务器时,仅会对一小部分请求产生影响,因此,尤其适用于后端服务器为cache的
  场景。
  
不过,此算法不甚平滑,派发至各服务器的请求未必能达到理想的均衡效果,因此,
  可能需要不时的调整服务器的权重以获得更好的均衡性。

cookie实现根据客户端cooike信息来实现持久连接。实现的原理:

HAproxy简介_第4张图片

cookie关键字用法说明:
nocacahe:将附加cookie信息的资源不缓存于缓存服务器中
insert:插入cooike信息
rewrite:重写cookie
prefix:作为前缀

测试:修改haproxy的配置文件

backend web 
    balance     roundrobin
    cookie webser insert nocache
    server  web1 172.16.10.77:80 cookie web1 
    server  web2 172.16.10.1:80 cookie web2

测试:

HAproxy简介_第5张图片

三、HAproxy的状态页

### 在配置文件中添加:
listen stats
    mode http
    bind 0.0.0.0:1080
    stats enable
    stats hide-version
    stats uri     /haproxyadmin?stats
    stats realm   Haproxy\ Statistics
    stats auth    admin:admin
    stats admin if TRUE

HAproxy简介_第6张图片

HAproxy简介_第7张图片

四、后端监控状态检测

### 修改配置文件,如下:
backend web 
    balance     roundrobin
    server  web1 172.16.10.77:80  check port 80 inter 2 fall 2 rise 1 
    server  web2 172.16.10.1:80 check port 80 inter 2 fall 2 rise 1
    server  back 172.16.10.9:8080 backup

当后端主机全都不在线时,测试:

HAproxy简介_第8张图片

一旦手段主机重新上线,访问恢复:

HAproxy简介_第9张图片

五、利用haproxy实现动态分离

此时要利用到haproxy的ACL机制:

haproxy的ACL用于实现基于请求报文的首部、响应报文的内容或其它的环境状态信息来做出转发决
  策,这大大增强了其配置弹性。其配置法则通常分为两步,首先去定义ACL,即定义一个测试条件,
  而后在条件得到满足时执行某特定的动作,如阻止请求或转发至某特定的后端。
  
定义ACL的语法格式如下。
	acl   [flags] [operator]  ...
:ACL名称,区分字符大小写,且其只能包含大小写字母、数字、-(连接线)、_(下划线)、
.(点号)和:(冒号);haproxy中,acl可以重名,这可以把多个测试条件定义为一个共同的acl;
:测试标准,即对什么信息发起测试;测试方式可以由[flags]指定的标志进行调整;
而有些测试标准也可以需要为其在之前指定一个操作符[operator];
[flags]:目前haproxy的acl支持的标志位有3个:
-i:不区分中模式字符的大小写;
-f:从指定的文件中加载模式;
--:标志符的强制结束标记,在模式中的字符串像标记符时使用;
:acl测试条件支持的值有以下四类:
    整数或整数范围:如1024:65535表示从1024至65535;仅支持使用正整数(如果出现类似小数的标
    识,其为通常为版本测试),且支持使用的操作符有5个,分别为eq、ge、gt、le和lt;
    字符串:支持使用“-i”以忽略字符大小写,支持使用“\”进行转义;
    如果在模式首部出现了-i,可以在其之前使用“--”标志位;
    正则表达式:其机制类同字符串匹配;
    IP地址及网络地址
同一个acl中可以指定多个测试条件,这些测试条件需要由逻辑操作符指定其关系。
条件间的组合测试关系有三种:“与”(默认即为与操作)、“或”(使用“||”操作符)以及
“非”(使用“!”操作符)。

示例:

acl url_static       path_beg       -i /static /p_w_picpaths /javascript /stylesheets
acl url_static       path_end       -i .jpg .gif .png .css .js
acl host_static hdr_beg(host) -i img. video. download. ftp.
acl being_scanned be_sess_rate gt 50

实验环境:

HAproxy简介_第10张图片

在172.16.10.9:

1、提供haproxy的配置文件,内容如下:
global
    log         127.0.0.1 local2

    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon

    stats socket /var/lib/haproxy/stats

defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000
listen stats
    mode http
    bind 0.0.0.0:1080
    stats enable
    stats hide-version
    stats uri     /haproxyadmin?stats
    stats realm   Haproxy\ Statistics
    stats auth    admin:admin
    stats admin if TRUE

frontend  http
    bind *:80
    acl url_static       path_beg       -i /static /p_w_picpaths /javascript /stylesheets
    acl url_static       path_end       -i .jpg .gif .png .css .js 

    use_backend static          if url_static
    default_backend             web

backend static
    balance     roundrobin
    server      static 172.16.10.122 check

backend web
    balance     roundrobin
    server  web1 172.16.10.77:80  check port 80 inter 2 fall 2 rise 1 
    server  web2 172.16.10.1:80 check port 80 inter 2 fall 2 rise 1
    server  back 172.16.10.9:8080 backup
###################################################################################
2、提供nfs服务
mkdir /data
setfacl -m d:u:48:rwx /data/
###################################################################################
3、提供Discuzz的数据库授权用户
mysql> GRANT ALL ON discuzz.* TO disuser@'172.16.10.%' IDENTIFIED BY 'dispass';
mysql> FLUSH PRIVILEGES;
##################################################################################
启动服务:
service nfs start
service haproxy restart

在172.16.10.1、172.16.10.77上:

yum install php php-mysql -y 
mkdir /var/www/html/discuzz 
service httpd restart


在172.16.10.122上:

这个节点上只需响应静态页面,可以不安装php php-mysql。直接挂载

在任意一台上,挂载nfs,开始安装discuzz.这里以172.16.10.77为例:

大致步骤:
1、mount -t nfs 172.16.10.9:/data/ /var/www/html/discuzz/
2、解压discuzz安装包,将解压后的upload中的所有文件复制到/var/www/html/discuzz/
3、开始安装:http;//172.16.10.77/discuzz/install/index.php

按照提示解决问题并安装,最关键的是数据库信息的填写:

HAproxy简介_第11张图片

安装完成后,在172.16.10.122和172.16.10.1上:mount -t nfs 172.16.10.9:/data/ /var/www/html/discuzz/ 开始测试:

HAproxy简介_第12张图片

HAproxy简介_第13张图片

前端调度:

HAproxy简介_第14张图片

此时,将静态页面服务器172.16.10.122停止,结果:

HAproxy简介_第15张图片

实现了一定程度上的动静分离。

关于haproxy更多,更详细的内容,参考官方文档。