haproxy-负载均衡介绍

参考:http://www.iyunv.com/thread-252539-1-1.html

负载均衡介绍

复制代码
四层和七层负载均衡的区别
  四层
  所谓的四层就是ISO参考模型中的第四层。四层负载均衡也称为四层交换机,它主要是 通过分析IP层及TCP/UDP层的流量实现的基于IP加端口的负载均衡。常见的基于四层的负载均衡器有LVS、F5等。   以常见的TCP应用为例,负载均衡器在接收到第一个来自客户端的SYN请求时,会通过设定的负载均衡算法选择一个最佳的后端服务器,同时将报文中目标IP地址修改为后端服务器IP,然后直接转发给该后端服务器,这样一个负载均衡请求就完成了。
从这个过程来看,一个TCP连接是客户端和服务器直接建立的,而负载均衡器只不过完成了一个类似路由器的转发动作。在某些负载均衡策略中,为保证后端服务器返回的报文可以正确传递给负载均衡器,在转发报文的同时可能还会对报文原来的源地址进行修改。

  七层   同理,七层负载均衡器也称为七层交换机,位于 OSI 的最高层,即应用层,此时负载均衡器支持多种应用协议,常见的有 HTTP、FTP、SMTP 等。七层负载均衡器可以根据报文内容,再配合负载均衡算法来选择后端服务器,因此也称为“内容交换器”。
  比如,对于 Web 服务器的负载均衡,七层负载均衡器不但可以根据“IP+端口”的方式进行负载分流,还可以根据网站的 URL、访问域名、浏览器类别、语言等决定负载均衡的策略。
  例如,有两台 Web 服务器分别对应中英文两个网站,两个域名分别是 A、B,要实现访问 A 域名时进入中文网站,访问 B 域名时进入英文网站,这在四层负载均衡器中几乎是无法实现的,而七层负 载均衡可以根据客户端访问域名的不同选择对应的网页进行负载均衡处理。
  常见的七层负载均衡器有 HAproxy、Nginx 等。 HAProxy支持两种主要的代理模式:   TCP 即4层 (大多用于邮件服务器、内部协议通信服务器等)。在4层模式 下,HAProxy仅在客户端和服务器之间转发双向流量。   HTTP 即7层模式,HAProxy会分析协议,并且能通过允许、拒绝、交换、增加、修改或者***请求 (request)或者回应(response)里指定内容来控制协议,
     这种操作要基于特定规则。(新的1.3之后的版本引入了frontend,backend指令;frontend根据任意HTTP请求头内容做规则匹配,然后把请求定向到相关的backend.)   这里仍以常见的TCP应用为例,由于负载均衡器要获取到报文的内容,因此只能先代替后端服务器和客户端建立连接,接着,才能收到客户端发送过来的报文内容,然后再根据该报文中特定字段加上负载均衡器中设置的负载均衡算法来决定最终选择的内部服务器。
  纵观 整个过程,七层负载均衡器在这种情况下类似于一个代理服务器。整个过程如下图所示。
对比四层负载均衡和七层负载均衡运行的整个过程,可以看出,
  七层负载均衡模式下,负载均衡器与客户端及后端的服务器会分别建立一次TCP连接
  四层负载均衡模式下, 仅建立一次TCP连接。
由此可知,七层负载均衡对负载均衡设备的要求更高,而七层负载均 衡的处理能力也必然低于四层模式的负载均衡。 HAProxy与LVS的异同 下面就这两种负载均衡软件的异同做一个简单总结:   1)两者都是软件负载均衡产品,但是LVS是基于Linux操作系统内核实现的一种软负载均衡,而HAProxy是基于第三应用实现的软负载均衡。   2)LVS是基于四层的IP负载均衡技术,而HAProxy是基于四层和七层技术、可提供TCP和HTTP应用的负载均衡综合解决方案。   3)LVS工作在ISO模型的第四层,因此其状态监测功能单一,而HAProxy在状态监测方面功能强大,可支持端口、URL、脚本等多种状态检测方式。   4)HAProxy虽然功能强大,但是整体处理性能低于四层模式的LVS负载均衡,而LVS拥有接近硬件设备的网络吞吐和连接负载能力。 综上所述,HAProxy和LVS各有优缺点,没有好坏之分,要选择哪个作为负载均衡器,要以实际的应用环境来决定。
HAProxy主要在于它有以下优点,总结如下:   1、HAProxy是支持虚拟主机的,通过frontend指令来实现   2、能够补充Nginx的一些缺点比如Session的保持,Cookie的引导等工作   3、支持url检测后端的服务器出问题的检测会有很好的帮助。   4、它跟LVS一样,本身仅仅就只是一款负载均衡软件;单纯从效率上来讲HAProxy更会比Nginx有更出色的负载均衡速度,在并发处理上也是优于Nginx的。   5、HAProxy可以对Mysql读进行负载均衡,对后端的MySQL节点进行检测和负载均衡,不过在后端的MySQL slaves数量超过10台时性能不如LVS,所以向大家推荐LVS+Keepalived。   6、能对请求的url和header中的信息做匹配,有比lvs有更好的7层实现
复制代码
安装HAProxy
复制代码
可以在HAProxy的官网http://www.haproxy.org/下载HAProxy的源码包,这里以操作系统Centos6.6 X64版本为例,下载的HAProxy是haproxy-1.6.9.tar.gz,安装过程如 下:
#tar -zxvf haproxy-1.6.9.tar.gz
#cd haproxy-1.6.9
#make TARGET=linux26 PREFIX=/usr/local/haproxy    #此处TARGET=linux26是填写系统内核版本 uname -r ,如版本是2.6.32-504.el6.x86_64, 直接填写26即可。
#make install PREFIX=/usr/local/haproxy
#ls /usr/local/haproxy/
doc  sbin  share

创建配置文件目录及log目录(pid文件)
#mkdir  /usr/local/haproxy/conf   
#mkdir  /usr/local/haproxy/log      
#cp examples/option-http_proxy.cfg  /usr/local/haproxy/conf/haproxy.cfg
#haproxy安装完成后,默认安装目录中没有配置文件,这里是将源码包里面的示例配置文件拷贝到配置文件目录
这样,HAProxy就安装完成了。
复制代码

haproxy配置详解 http://cbonte.github.io/haproxy-dconv/1.6/configuration.html#4.2

复制代码
HAProxy配置中分五大部分:
  global:  全局配置参数,进程级的,用来控制Haproxy启动前的一些进程及系统设置
  defaults: 配置一些默认的参数,可以被frontend,backend,listen段继承使用
  frontend: 用来匹配接收客户所请求的域名,uri等,并针对不同的匹配,做不同的请求处理
  backend:  定义后端服务器集群,以及对后端服务器的一些权重、队列、连接数等选项的设置,我将其理解为Nginx中的upstream块
  listen:   frontend和backend的组合体

复制代码
复制代码
global
maxconn 4096
    # 定义每个haproxy进程的最大连接数 ,由于每个连接包括一个客户端和一个服务器端,所以单个进程的TCP会话最大数目将是该值的两倍
chroot /usr/local/haproxy
    #修改haproxy的工作目录至指定目录并在放弃权限前执行chroot()操作,可以提升haproxy安全级别,
    #
user nobody
group nobody
    #设置运行haproxy的用户和组,也可使用uid,gid关键字替代之,可以创建haproxy用户
daemon
    #以守护进程的方式运行
nbproc 1
    # 设置haproxy启动时的进程数,根据官方文档的解释,我将其理解为:该值的设置应该和服务器的CPU核心数一致,即常见的2颗8核心CPU的服务器,即共有16核心,
    #则可以将其值设置为:<=16 ,创建多个进程数,可以减少每个进程的任务队列,但是过多的进程数也可能会导致进程的崩溃。这里我设置为16
pidfile /usr/local/haproxy/logs/haproxy.pid
    # 定义haproxy的pid
log 127.0.0.1 local0 info
    # log语法:log [max_level_1]
    # 全局的日志配置,使用log关键字,指定使用127.0.0.1上的syslog服务中的local0日志设备,记录日志等级为info的日志
#ulimit -n 65536
    # 设置最大打开的文件描述符数,在1.4的官方文档中提示,该值会自动计算,所以不建议进行设置

复制代码
复制代码
时间格式,默认为毫秒
us    微秒1/1000000秒 
ms    毫秒1/1000秒  
s     秒          
m     分钟
h     小时  
d     天
复制代码
复制代码
defaults (类似common)
mode http
    # mode语法:mode {http|tcp|health} 。http是七层模式,tcp是四层模式,health是健康检测,返回OK
log 127.0.0.1 local3 err
    # 使用127.0.0.1上的syslog服务的local3设备记录错误信息
retries 3
    # 定义连接后端服务器的失败重连次数,连接失败次数超过此值后将会将对应后端服务器标记为不可用
option httplog
    # 启用日志记录HTTP请求,默认haproxy日志记录是不记录HTTP请求的,只记录“时间[Jan 5 13:23:46] 日志服务器[127.0.0.1]
    #实例名已经pid[haproxy[25218]] 信息[Proxy http_80_in stopped.]”,日志格式很简单。
option redispatch
    # 当使用了cookie时,haproxy将会将其请求的后端服务器的serverID插入到cookie中,以保证会话的SESSION持久性;而此时,如果后端的服务器宕掉了,但是客户端的cookie是不会刷新的,
    #如果设置此参数,将会将客户的请求强制定向到另外一个后端server上,以保证服务的正常。#
option abortonclose
    # 当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接
option dontlognull
    # 启用该项,日志中将不会记录空连接。所谓空连接就是在上游的负载均衡器或者监控系统为了探测该服务是否存活可用时,需要定期的连接或者获取某一固定的组件或页面,或者探测扫描端口是否在监听或开放等动作被称为空连接;
    #官方文档中标注,如果该服务上游没有其他的负载均衡器的话,建议不要使用该参数,因为互联网上的恶意扫描或其他动作就不会被记录下来#
option httpclose
    # 这个参数我是这样理解的:使用该参数,每处理完一个request时,haproxy都会去检查http头中的Connection的值,如果该值不是close,haproxy将会将其删除,如果该值为空将会添加为:Connection: close。
    #使每个客户端和服务器端在完成一次传输后都会主动关闭TCP连接。与该参数类似的另外一个参数是“option forceclose”,该参数的作用是强制关闭对外的服务通道,因为有的服务器端收到Connection: close时,也不会自动关闭TCP连接,
    #如果客户端也不关闭,连接就会一直处于打开,直到超时。##
contimeout 5000
    # 设置成功连接到一台服务器的最长等待时间,默认单位是毫秒,新版本的haproxy使用timeout connect替代,该参数向后兼容
clitimeout 3000
    # 设置连接客户端发送数据时的成功连接最长等待时间,默认单位是毫秒,新版本haproxy使用timeout client替代。该参数向后兼容
srvtimeout 3000
    # 设置服务器端回应客户度数据发送的最长等待时间,默认单位是毫秒,新版本haproxy使用timeout server替代。该参数向后兼容
option forwardfor  except 127.0.0.0/8


复制代码
复制代码
frontend front_www_server
bind *:80 
    #http_80_in定义前端部分监听的套接字 vip,可以bind ip:80 mode http
    #定义为HTTP模式 option httplog
    # 启用日志记录HTTP请求,默认haproxy日志记录是不记录HTTP请求的,只记录“时间[Jan 5 13:23:46] 日志服务器[127.0.0.1] 实例名已经pid[haproxy[25218]] 信息[Proxy http_80_in stopped.]”,日志格式很简单。可加到default模块 option forwardfor
    # 启用X-Forwarded-For,在requests头部插入客户端IP发送给后端的server,使后端server获取到客户端的真实IP option httpclose
    #这个参数我是这样理解的:使用该参数,每处理完一个request时,haproxy都会去检查http头中的Connection的值,如果该值不是close,haproxy将会将其***,如果该值为空将会添加为:Connection: close。
    #使每个客户端和服务器端在完成一次传输后都会主动关闭TCP连接。与该参数类似的另外一个参数是“option forceclose”,该参数的作用是强制关闭对外的服务通道,因为有的服务器端收到Connection: close时,
    #也不会自动关闭TCP连接,如果客户端也不关闭,连接就会一直处于打开,直到超时。 log global
    #继承global中log的定义 option dontlognull
    # 启用该项,日志中将不会记录空连接。所谓空连接就是在上游的负载均衡器或者监控系统为了探测该服务是否存活可用时,需要定期的连接或者获取某一固定的组件或页面,或者探测扫描端口是否在监听或开放等动作被称为空连接;
    #官方文档中标注,如果该服务上游没有其他的负载均衡器的话,建议不要使用该参数,因为互联网上的恶意扫描或其他动作就不会被记录下来
 
default_backend  www_server

#acl host_wwwhdr_dom(host) -i www.zb.com #acl host_imghdr_dom(host) -i img.zb.com #use_backendhtmpool if host_www #use_backendimgpool if host_img ==========可选配参数 acl static_down nbsrv(static_server) lt 1     # 定义一个名叫static_down的acl,当backend static_sever中存活机器数小于1时会被匹配到 acl php_web url_reg /*.php$     #acl php_web path_end .php # 定义一个名叫php_web的acl,当请求的url末尾是以.php结尾的,将会被匹配到,上面两种写法任选其一     acl static_web url_reg /*.(css|jpg|png|jpeg|js|gif)$ #acl static_web path_end .gif .png .jpg .css .js .jpeg     # 定义一个名叫static_web的acl,当请求的url末尾是以.css、.jpg、.png、.jpeg、.js、.gif结尾的,将会被匹配到,上面两种写法任选其一 use_backend php_server if static_down     # 如果满足策略static_down时,就将请求交予backend php_server use_backend php_server if php_web     # 如果满足策略php_web时,就将请求交予backend php_server use_backend static_server if static_web     # 如果满足策略static_web时,就将请求交予backend static_server ==========


frontend front_www_server
bind *:80
mode http  
option httplog   
option forwardfor  
option httpclose
log  global   
option dontlognull
default_backend www_server
复制代码
复制代码
backend back_www_server
mode http    
    #设置为http模式 option redispatch
    # 当使用了cookie时,haproxy将会将其请求的后端服务器的serverID插入到cookie中,以保证会话的SESSION持久性;而此时,如果后端的服务器宕掉了,但是客户端的cookie是不会刷新的,如果设置此参数,将会将客户的请求强制定向到另外一个后端server上,以保证服务的正常,可定义到default模块 option abortonclose
    # 当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接 balance static-rr
    # 设置haproxy的调度算法为源地址static-rr cookie SERVERID
    #允许向cookie插入SERVERID,每台服务器的SERVERID可在下面用cookie关键字定义 option httpchk GET /index.html
    # 开启对后端服务器的健康检测,通过GET /test/index.php来判断后端服务器的健康情况option httpchk HEAD / HTTP/1.0也可以,但是日志好像有点多啊
server  node81 192.168.0.81:80 [cookie server1] weight 6 check inter 2000 rise 2 fall 3 server  node82 192.168.0.82:80 [cookie server2] weight 3 check inter 2000 rise 2 fall 3
=================================================== server php_server_1 10.12.25.68:80 cookie 1 check inter 2000 rise 3 fall 3 weight 2 server php_server_2 10.12.25.72:80 cookie 2 check inter 2000 rise 3 fall 3 weight 1 server php_server_bak 10.12.25.79:80 cookie 3 check inter 1500 rise 3 fall 3 backup # server语法:server [:port] [param*] # 使用server关键字来设置后端服务器;为后端服务器所设置的内部名称[php_server_1],该名称将会呈现在日志或警报中、后端服务器的IP地址,支持端口映射[10.12.25.68:80]、指定该 服务器的SERVERID为1[cookie 1]、接受健康监测[check]、监测的间隔时长,单位毫秒[inter 2000]、监测正常多少次后被认为后端服务器是可用的[rise 3]、监测失败多少次后被认为后端服务器是不可用的[fall 3]、分发的权重[weight 2]、最为备份用的后端服务器,当正常的服务器全部都宕机后,才会启用备份服务器[backup] ================================================== backend imgpool mode http option redispatch option abortonclose balance static-rr cookie SERVERID option httpchk GET /index.jsp server host236 192.168.81.236:8080 cookie server1 weight 6 check inter 2000 rise 2 fall 3


复制代码
复制代码
listen admin_stats
                 # 定义一个名为status的部分,可以在listen指令指定的区域中定义匹配规则和后端服务器ip,相当于需要在其中配置frontend,backend的功能。一般做tcp转发比较合适,不用太多的规则匹配
bind 0.0.0.0:9188         # 定义监听的套接字
mode http             # 定义为HTTP模式
log 127.0.0.1 local0 err      #定义log
stats refresh 30s            # stats是haproxy的一个统计页面的套接字,该参数设置统计页面的刷新间隔为30s
stats uri /haproxy-status             #  设置统计页面的uri为/haproxy-status
stats realm welcome login Haproxy     # 设置统计页面认证时的提示内容stats realm Private lands
stats auth  admin:admin~!@           # 设置统计页面认证的用户和密码,如果要设置多个,另起一行写入即可stats auth admin:password
stats hide-version                 # 隐藏统计页面上的haproxy版本信息
stats admin if TRUE

http://ip:9188/haproxy-status
复制代码
复制代码
===================日志配置
# vi /etc/rsyslog.conf    取消注释,增加一条
# Provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514
local0.*        /usr/local/haproxy/logs/haproxy.log   (对后端的访问日志也在)
# vi /etc/sysconfig/rsyslog
SYSLOGD_OPTIONS="-r -m 0 -c 2"
===================日志配置
复制代码
复制代码
启动与测试haproxy的负载均衡功能
1、启动与管理haproxy
启动服务:
  # /usr/local/haproxy/sbin/haproxy -f      /usr/local/haproxy/conf/haproxy.cfg
重启服务:
  # /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/conf/haproxy.cfg -st `cat /usr/local/haproxy/log/haproxy.pid`
停止服务:
  # killall haproxy
复制代码
复制代码
HAProxy负载均衡器算法
  1、HAProxy支持的负载均衡算法
    roundrobin,表示简单的轮询,基于权重负载均衡基础算法(支持慢速启动,运行时调整)
          server  node81 192.168.0.81:80 check weight 3
          server  node82 192.168.0.82:80 check weight 1     static-rr,表示根据权重     leastconn,表示最少连接者先处理(不适用web)     source,表示根据请求源IP(会话保持,此方法动静还要取决于hash-type,map-based静态,consistent动态)     uri,表示根据请求的URI;(用于缓存服务器)     url_param,表示根据请求的URl参数来进行调度     hdr(name),表示根据HTTP请求头来锁定每一次HTTP请求;     rdp-cookie(name),表示根据据cookie(name)来锁定并哈希每一次TCP请求。   2、集群中的session处理     session保持     session复制     session共享
复制代码
复制代码
通过HAProxy的ACL规则实现智能负载均衡
由于HAProxy可以工作在七层模型下,因此,要实现HAProxy的强大功能,一定要使用强大灵活的ACL规则,通过ACL规则可以实现基于HAProxy的智能负载均衡系统。
HAProxy 通过ACL规则完成两种主要的功能,分别是:
1)通过设置的ACL规则检查客户端请求是否合法。如果符合ACL规则要求,那么就将放行,反正,如果不符合规则,则直接中断请求.
2)符合ACL规则要求的请求将被提交到后端的backend服务器集群,进而实现基于ACL规则的负载均衡。

HAProxy中的ACL规则经常使用在frontend段中,使用方法如下:
acl     自定义的acl名称  acl方法  -i     [匹配的路径或文件]
其中:
acl:是一个关键字,表示定义ACL规则的开始。后面需要跟上自定义的ACL名称。
acl方法:这个字段用来定义实现ACL的方法,HAProxy定义了很多ACL方法,经常使用的方法有hdr_reg(host)、hdr_dom(host)、hdr_beg(host)、url_sub、url_dir、 path_beg、path_end等。
-i:表示忽略大小写,后面需要跟上匹配的路径或文件或正则表达式。
与ACL规则一起使用的HAProxy参数还有use_backend,use_backend后面需要跟上一个backend实例名,表示在满足ACL规则后去请求哪个backend实例,与 use_backend对应的还有default_backend参数,它表示在没有满足ACL条件的时候默认使用哪个后端backend。

下面列举几个常见的ACL规则例子:
acl www_policy      hdr_reg(host)         -i       ^(www.z.cn|z.cn)
acl bbs_policy       hdr_dom(host)         -i       bbs.z.cn
acl url_policy        url_sub               -i     buy_sid=

use_backend    server_www    if  www_policy 
use_backend    server_app    if  url_policy    
use_backend    server_bbs    if  bbs_policy    
default_backend  server_cache  

复制代码
复制代码
使用socat工具在线管理haproxy
Unix Socket command
sroot@test86 ~]# yum install -y socat
[root@test86 conf]# vi haproxy.cfg
global
        stats socket /var/run/haproxy.sock mode 600 level admin
        stats timeout 2m

重启服务:
# /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/conf/haproxy.cfg -st `cat /usr/local/haproxy/logs/haproxy.pid`

To access the socket, an external utility such as "socat" is required. Socat is
a swiss-army knife to connect anything to anything. We use it to connect
terminals to the socket, or a couple of stdin/stdout pipes to it for scripts.
The two main syntaxes we'll use are the following :
    # socat /var/run/haproxy.sock stdio
    # socat /var/run/haproxy.sock readline

[root@test86 conf]# echo "help" | socat /var/run/haproxy.sock stdio
  clear counters : clear max statistics counters (add 'all' for all counters)
  clear table    : remove an entry from a table
  help           : this message
  prompt         : toggle interactive mode with prompt
  quit           : disconnect
  show backend   : list backends in the current running config
  show info      : report information about the running process
  show pools     : report information about the memory pools usage
  show stat      : report counters for each proxy and server
  show stat resolvers [id]: dumps counters from all resolvers section and
                            associated name servers
  show errors    : report last request and response errors for each proxy
  show sess [id] : report the list of current sessions or dump this session
  show table [id]: report table usage stats or dump this table's contents
  show servers state [id]: dump volatile server information (for backend <id>)
  get weight     : report a server's current weight
  set weight     : change a server's weight
  set server     : change a server's state, weight or address
  set table [id] : update or create a table entry's data
  set timeout    : change a timeout setting
  set maxconn    : change a maxconn setting
  set rate-limit : change a rate limiting value
  disable        : put a server or frontend in maintenance mode
  enable         : re-enable a server or frontend which is in maintenance mode
[root@test86 conf]# echo "disable server htmpool/237server " | socat /var/run/haproxy.sock stdio
[root@test86 conf]# echo "enable server htmpool/237server " | socat /var/run/haproxy.sock stdio
  shutdown       : kill a session or a frontend (eg:to release listening ports)
  show acl [id]  : report available acls or dump an acl's contents
  get acl        : reports the patterns matching a sample for an ACL
  add acl        : add acl entry
  del acl        : delete acl entry
  clear acl <id> : clear the content of this acl
  show map [id]  : report available maps or dump a map's contents
  get map        : reports the keys and values matching a sample for a map
  set map        : modify map entry
  add map        : add map entry
  del map        : delete map entry
  clear map <id> : clear the content of this map
  set ssl <stmt> : set statement for ssl
复制代码
原文地址:https://www.cnblogs.com/tianciliangen/p/7986585.html