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

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


  HAProxy是免费、极速且可靠的用于为TCP和基于HTTP应用程序提供高可用、负载均衡和代理服务的解决方案,尤其适用于高负载且需要持久连接或7层处理机制的web站点。

HAProxy目前主要有两个版本:

1.4——提供较好的弹性:衍生于1.2版本,并提供了额外的新特性,其中大多数是期待已久的。
  客户端侧的长连接(client-side keep-alive)
  TCP加速(TCP speedups)
  响应池(response buffering)
  RDP协议
  基于源的粘性(source-based stickiness)
  更好的统计数据接口(a much better stats interfaces)
  更详细的健康状态检测机制(more verbose health checks)
  基于流量的健康评估机制(traffic-based health)
  支持HTTP认证
  服务器管理命令行接口(server management from the CLI)
  基于ACL的持久性(ACL-based persistence)
  日志分析器

1.3——内容交换和超强负载:衍生于1.2版本,并提供了额外的新特性。
  内容交换(content switching):基于任何请求标准挑选服务器池;
  ACL:编写内容交换规则;
  负载均衡算法(load-balancing algorithms):更多的算法支持;
  内容探测(content inspection):阻止非授权协议;
  透明代理(transparent proxy):在Linux系统上允许使用客户端IP直接连入服务器;
  内核TCP拼接(kernel TCP splicing):无copy方式在客户端和服务端之间转发数据以实现数G级别的数据速率;
  分层设计(layered design):分别实现套接字、TCP、HTTP处理以提供更好的健壮性、更快的处理机制及便捷的演进能力;
  快速、公平调度器(fast and fair scheduler):为某些任务指定优先级可实现理好的QoS;
  会话速率限制(session rate limiting):适用于托管环境;

支持的平台及OS:
  x86、x86_64、Alpha、SPARC、MIPS及PARISC平台上的Linux 2.4;
  x86、x86_64、ARM (ixp425)及PPC64平台上的Linux2.6;
  UltraSPARC 2和3上的Sloaris 8/9;
  Opteron和UltraSPARC平台上的Solaris 10;
  x86平台上的FreeBSD 4.1-8;
  i386, amd64, macppc, alpha, sparc64和VAX平台上的OpenBSD 3.1-current;


二、haproxy的性能

1.haproxy使用单进程,事件驱动模型降低了上下午切换的开销及内存的占用

2.事件查看器(event checker)允许其在高并发连接中对任何连接的任何事件实现即时探测

3.单缓冲机制,不会复制任何数据,节约CPU时钟周期

4.可以实现零复制转发,在Linux kernel 3.5以上还支持零复制启动

5.MRU内存分配器在固定大小的内存池中可实现即时内存分配,这能够显著减少创建一个会话的时长

6.采用树型存储

7.大部分工作都在用户空间完成,如时间读取、缓冲聚合及文件描述符的启用和禁用等


三、haproxy的安装以及生成的文件:

#yum install haproxy -y
#rpm -ql haprxoy                #查看安装生成的文件
/etc/haproxy
/etc/haproxy/haproxy.cfg        #haproxy的配置文件
/etc/logrotate.d/haproxy
/etc/rc.d/init.d/haproxy        #haproxy的服务脚本文件
/usr/bin/halog
/usr/bin/iprange
/usr/sbin/haproxy
/usr/share/haproxy
/usr/share/haproxy/400.http         #400错误的状态码页面
/usr/share/haproxy/403.http         #403错误的状态码页面
/usr/share/haproxy/408.http         #408错误的状态码页面
/usr/share/haproxy/500.http         #500错误的状态码页面
/usr/share/haproxy/502.http         #502错误的状态码页面
/usr/share/haproxy/503.http         #503错误的状态码页面
/usr/share/haproxy/504.http         #504错误的状态码页面
/usr/share/man/man1/halog.1.gz      #可直接使用man halog查看命令的使用语法
/usr/share/man/man1/haproxy.1.gz    #可直接使用man haproxy查看命令的使用语法
/var/lib/haproxy
......

注:由于yum安装haproxy生成的文件略多,上述仅对部分文件说明。


四、haproxy的配置文件说明:

#---------------------------------------------------------------------
# Example configuration for a possible web application.  See the
# full configuration options online.
#
#   http://haproxy.1wt.eu/download/1.4/doc/configuration.txt
#
#---------------------------------------------------------------------

#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global   #配置段,用于设定全局配置参数
    # to have these messages end up in /var/log/haproxy.log you will
    # need to:   #配置日志
    #
    # 1) configure syslog to accept network log events.  This is done
    #    by adding the '-r' option to the SYSLOGD_OPTIONS in
    #    /etc/sysconfig/syslog    #修改syslog的配置文件
    #
    # 2) configure local2 events to go to the /var/log/haproxy.log
    #   file. A line like the following can be added to
    #   /etc/sysconfig/syslog      #定义日志设备
    #
    #    local2.*                       /var/log/haproxy.log
    #
    log         127.0.0.1 local2

    chroot      /var/lib/haproxy   #修改haproxy的工作目录至指定的目录
    pidfile     /var/run/haproxy.pid #指定pid文件的路径
    maxconn     4000   #设定每个haproxy进程所接受的最大并发连接数,
    user        haproxy #以指定的用户运行服务
    group       haproxy #以指定的用户组运行服务
    daemon      #让haproxy以守护进程的方式工作于后台

    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats

#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
    mode                    http      #设定实例的运行模式或协议
    log                     global    #为每个实例启用事件和流量日志
    option                  httplog   #详细记录http日志
    option                  dontlognull    #不记录空日志
    option http-server-close                #启用http-server-close
    option forwardfor       except 127.0.0.0/8   #来自这些信息的都不forwardfor
    option                  redispatch           #重新分发
    retries                 3                    #3次连接失败则认为服务不可用
    timeout http-request    10s                  #默认http请求超时时长
    timeout queue           1m                   #默认队列超时时长
    timeout connect         10s                  #默认连接超时时间
    timeout client          1m       #默认客户端超时时长
    timeout server          1m       #默认服务器超时时长
    timeout http-keep-alive 10s      #默认持久连接超时时长
    timeout check           10s      #默认检查时间间隔
    maxconn                 3000     #最大连接数

#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend  main *:5000
    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    #调用后端服务器并检查ACL规则是否被匹配
    default_backend             app              #客户端访问时默认调用后端服务器地址池

#---------------------------------------------------------------------
# static backend for serving up p_w_picpaths, stylesheets and such
#---------------------------------------------------------------------
backend static  #定义后端服务器
    balance     roundrobin    #定义算法;基于权重进行轮询
    server      static 127.0.0.1:4331 check  #check:启动对后端server的健康状态检测

#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend app
    balance     roundrobin
    server  app1 127.0.0.1:5001 check
    server  app2 127.0.0.1:5002 check
    server  app3 127.0.0.1:5003 check
    server  app4 127.0.0.1:5004 check

配置文件参数的补充说明:

全局配置:
 ----------------“global”配置中的参数为进程级别的参数,且通常与其运行的OS相关。

- chroot <jail dir>:修改haproxy的工作目录至指定的目录并在放弃权限之前执行chroot()操作,可以提升haproxy的安全级别,不过需要注意的是要确保指定的目录为空目录且任何用户均不能有写权限;
- daemon:让haproxy以守护进程的方式工作于后台,其等同于“-D”选项的功能,当然,也可以在命令行中以“-db”选项将其禁用;

- gid <number>:以指定的GID运行haproxy,建议使用专用于运行haproxy的GID,以免因权限问题带来风险;

- group <group name>:同gid,不过指定的组名;

- log  <address> <facility> [max level [min level]]:定义全局的syslog服务器,最多可以定义两个;

- log-send-hostname [<string>]:在syslog信息的首部添加当前主机名,可以为“string”指定的名称,也可以缺省使用当前主机名;
- nbproc <number>:指定启动的haproxy进程的个数,只能用于守护进程模式的haproxy;默认只启动一个进程,鉴于调试困难等多方面的原因,一般只在单进程仅能打开少数文件描述符的场景中才使用多进程模式;

- uid:以指定的UID身份运行haproxy进程;

- ulimit-n:设定每进程所能够打开的最大文件描述符数目,默认情况下其会自动进行计算,因此不推荐修改此选项;
- user:同uid,但使用的是用户名;

- stats:基于程序编译时默认设置的统计报告

- node:定义当前节点的名称,用于HA场景中多haproxy进程共享同一个IP地址时; - description:当前实例的描述信息;

- maxconn <number>:设定每个haproxy进程所接受的最大并发连接数,其等同于命令行选项“-n”;“ulimit -n”自动计算的结果正是参照此参数设定的;

代理相关的配置可以如下配置段中:
 - defaults <name>
 - frontend <name>
 - backend  <name>
 - listen   <name>

 “defaults”段用于为所有其它配置段提供默认参数,这配置默认配置参数可由下一个“defaults”所重新设定。
 “frontend”段用于定义一系列监听的套接字,这些套接字可接受客户端请求并与之建立连接。
 “backend”段用于定义一系列“后端”服务器,代理将会将对应客户端的请求转发至这些服务器。
 “listen”段通过关联“前端”和“后端”定义了一个完整的代理,通常只对TCP流量有用。
 所有代理的名称只能使用大写字母、小写字母、数字、-(中线)、_(下划线)、.(点号)和:(冒号)。此外,ACL名称会区分字母大小写。


配置文件中的关键字:

balance:

  定义负载均衡算法,可用于“defaults”、“listen”和“backend”。<algorithm>用于在负载均衡场景中挑选一个server,其仅应用于持久信息不可用的条件下或需要将一个连接重新派发至另一个服务器时。支持的算法有:
  roundrobin:基于权重进行轮叫;此算法是动态的,每个后端服务器仅能最多接受4128个连接;
  static-rr:基于权重进行轮叫,与roundrobin类似,但是为静态方法,在运行时调整其服务器权重不会生效;不过,其在后端服务器连接数上没有限制;
  leastconn:新的连接请求被派发至具有最少连接数目的后端服务器;
  source:将请求的源地址进行hash运算,并由后端服务器的权重总数相除后派发至某匹配的服务器;
  uri:对URI的左半部分(“问题”标记之前的部分)或整个URI进行hash运算,并由服务器的总权重相除后派发至某匹配的服务器;此算法仅应用于HTTP后端服务器场景;
  url_param:通过<argument>为URL指定的参数在每个HTTP GET请求中将会被检索;如果找到了指定的参数且其通过等于号“=”被赋予了一个值,那么此值将被执行hash运算并被服务器的总权重相除后派发至某匹配的服务器;此算法可以通过追踪请求中的用户标识进而确保同一个用户ID的请求将被送往同一个特定的服务器,除非服务器的总权重发生了变化;如果某请求中没有出现指定的参数或其没有有效值,则使用轮叫算法对相应请求进行调度;
  hdr(<name>):对于每个HTTP请求,通过<name>指定的HTTP首部将会被检索;如果相应的首部没有出现或其没有有效值,则使用轮叫算法对相应请求进行调度;

bind:
  bind [<address>]:<port_range> [, ...]
  bind [<address>]:<port_range> [, ...] interface <interface>
此指令仅能用于frontend和listen区段,用于定义一个或几个监听的套接字。

mode:

mode { tcp|http|health }
设定实例的运行模式或协议。当实现内容交换时,前端和后端必须工作于同一种模式(一般说来都是HTTP模式),否则将无法启动实例。

hash-type:
hash-type <method>
定义用于将hash码映射至后端服务器的方法;其不能用于frontend区段;可用方法有map-based和consistent,在大多数场景下推荐使用默认的map-based方法。

log:
log global
log <address> <facility> [<level> [<minlevel>]]
为每个实例启用事件和流量日志,因此可用于所有区段。每个实例最多可以指定两个log参数,不过,如果使用了“log global”且"global"段已经定了两个log参数时,多余了log参数将被忽略。

maxconn:
maxconn <conns>
设定一个前端的最大并发连接数,因此,其不能用于backend区段。对于大型站点来说,可以尽可能提高此值以便让haproxy管理连接队列,从而避免无法应答用户请求。当然,此最大值不能超出“global”段中的定义。此外,需要留心的是,haproxy会为每个连接维持两个缓冲,每个缓冲的大小为8KB,再加上其它的数据,每个连接将大约占用17KB的RAM空间。这意味着经过适当优化后,有着1GB的可用RAM空间时将能维护40000-50000并发连接。
如果为<conns>指定了一个过大值,极端场景下,其最终占据的空间可能会超出当前主机的可用内存,这可能会带来意想不到的结果;因此,将其设定了一个可接受值方为明智决定。其默认为2000。

default_backend:
default_backend <backend>
在没有匹配的"use_backend"规则时为实例指定使用的默认后端,因此,其不可应用于backend区段。在"frontend"和"backend"之间进行内容交换时,通常使用"use-backend"定义其匹配规则;而没有被规则匹配到的请求将由此参数指定的后端接收。
<backend>:指定使用的后端的名称;
server:
server <name> <address>[:port] [param*]
为后端声明一个server,因此,不能用于defaults和frontend区段。

stats enable:
启用基于程序编译时默认设置的统计报告,不能用于“frontend”区段。只要没有另外的其它设定,它们就会使用如下的配置:
  - stats uri   : /haproxy?stats
  - stats realm : "HAProxy Statistics"
  - stats auth  : no authentication
  - stats scope : no restriction

ACL:
  haproxy的ACL用于实现基于请求报文的首部、响应报文的内容或其它的环境状态信息来做出转发决策,这大大增强了其配置弹性。其配置法则通常分为两步,首先去定义ACL,即定义一个测试条件,而后在条件得到满足时执行某特定的动作,如阻止请求或转发至某特定的后端。定义ACL的语法格式如下。

  acl <aclname> <criterion> [flags] [operator] <value> ...

<aclname>:ACL名称,区分字符大小写,且其只能包含大小写字母、数字、-(连接线)、_(下划线)、.(点号)和:(冒号);haproxy中,acl可以重名,这可以把多个测试条件定义为一个共同的acl;
<criterion>:测试标准,即对什么信息发起测试;测试方式可以由[flags]指定的标志进行调整;而有些测试标准也可以需要为其在<value>之前指定一个操作符[operator];
[flags]:目前haproxy的acl支持的标志位有3个:
    -i:不区分<value>中模式字符的大小写;
    -f:从指定的文件中加载模式;
    --:标志符的强制结束标记,在模式中的字符串像标记符时使用;

<value>:acl测试条件支持的值有以下四类:
    整数或整数范围:如1024:65535表示从1024至65535;仅支持使用正整数(如果出现类似小数的标识,其为通常为版本测试),且支持使用的操作符有5个,分别为eq、ge、gt、le和lt;
    字符串:支持使用“-i”以忽略字符大小写,支持使用“\”进行转义;如果在模式首部出现了-i,可以在其之前使用“--”标志位;
    正则表达式:其机制类同字符串匹配;
    IP地址及网络地址

   同一个acl中可以指定多个测试条件,这些测试条件需要由逻辑操作符指定其关系。条件间的组合测试关系有三种:“与”(默认即为与操作)、“或”(使用“||”操作符)以及“非”(使用“!”操作符)。