HA Proxy

kv key-value

  取模法

  一致性哈希算法:consistent hashing

    偏斜:虚拟节点

haproxy_第1张图片

LB:按工作方法分类

  基于tcp调度:

    lvs,haproxy(模拟实现,未突破套接字限制),nginx

  基于application layer调度:

    http:haproxy,nginx,ats,apache

    mysql:mysl-proxy


haproxy_第2张图片

web arch:haproxy

  mode:http,tcp在用户空间模拟tcp服务进行调度(https,mysql)

HAProxy:不提供任何HA功能,只提供代理proxy

  代理:(http)掮客(broker)

    正向代理:

    反向代理:

    代理的作用:web缓存(加速)、反向代理、内容路由(根据流量及内容类型等,将请求转发至特定服务器)、转码器(前段压缩)

      在代理服务器上添加via首部

haproxy_第3张图片

  缓存作用:

    减少冗余内容的传输:

    节省带宽、缓解网络瓶颈

    降低对原始服务器的请求压力

    降低传输延迟

HAProxy:只是http协议的反向代理,不提供反向代理,但额外支持对基于tcp通信的应用做LB

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

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

Big O: 评判数据结构复杂度

    O(1): 

    O(logN): 红黑树

    O(n)

    O(n^2)

    O(2^n)

haproxy: 弹性二叉树

    数据结构:

Remote Desktop Protocol

    Windows: 3389

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):适用于托管环境;

性能:

HAProxy借助于OS上几种常见的技术来实现性能的最大化。

  单进程、事件驱动模型显著降低了上下文切换的开销及内存占用。

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

  在任何可用的情况下,单缓冲(single buffering)机制能以不复制任何数据的方式完成读写操作,这会节约大量的CPU时钟周期及内存带宽;

  借助于Linux 2.6 (>= 2.6.27.19)上的splice()系统调用,HAProxy可以实现零复制转发(Zero-copy forwarding),在Linux 3.5及以上的OS中还可以实现零复制启动(zero-starting);

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

  树型存储:侧重于使用作者多年前开发的弹性二叉树,实现了以O(log(N))的低开销来保持计时器命令、保持运行队列命令及管理轮询及最少连接队列;

  优化的HTTP首部分析:优化的首部分析功能避免了在HTTP首部分析过程中重读任何内存区域;

  精心地降低了昂贵的系统调用,大部分工作都在用户空间完成,如时间读取、缓冲聚合及文件描述符的启用和禁用等;

所有的这些细微之处的优化实现了在中等规模负载之上依然有着相当低的CPU负载,甚至于在非常高的负载场景中,5%的用户空间占用率和95%的系统空间占用率也是非常普遍的现象,这意味着HAProxy进程消耗比系统空间消耗低20倍以上。因此,对OS进行性能调优是非常重要的。即使用户空间的占用率提高一倍,其CPU占用率也仅为10%,这也解释了为何7层处理对性能影响有限这一现象。由此,在高端系统上HAProxy的7层性能可轻易超过硬件负载均衡设备。

在生产环境中,在7层处理上使用HAProxy作为昂贵的高端硬件负载均衡设备故障故障时的紧急解决方案也时长可见。硬件负载均衡设备在“报文”级别处理请求,这在支持跨报文请求(request across multiple packets)有着较高的难度,并且它们不缓冲任何数据,因此有着较长的响应时间。对应地,软件负载均衡设备使用TCP缓冲,可建立极长的请求,且有着较大的响应时间。

可以从三个因素来评估负载均衡器的性能:

  会话率

  会话并发能力

  数据率

nginx:

server {                   每个server相当一个前端

}

server {

location ~* \.php$   定义条件

   proxy_pass        代理

location / {

}

}

proxy_pass:

upstream {                 代理的后端服务器列表

leastconn            最少连接算法

server               后端服务器

server

}

upstream {

}

haproxy:

  frontend              前端(监听的端口等)

      use_backend       与后端建立关联(条件式请求)

      default_backend   默认后端

  backend               

      balancer          指明调度方法

      server

      server

  若前后端不分离,通常用于定义单个后端的情况

  listen:            监听

      server

  default  为以上三项提供默认参数

配置文件:/etc/haproxy/haproxy.cfg

  全局配置:

  代理配置

现有三台机器(CentOS7)分别为www(IP192.168.2.16),web1(IP192.168.2.18),localhost(IP192.168.2.60)

首先在www主机上安装haproxy

[root@www ~]# yum install haproxy -y

[root@www ~]# rpm -ql haproxy    #查看生成的文件

在web1和localhost上分别安装httpd并提供主页文件

[root@web1 ~]# yum install httpd

[root@web1 ~]# echo "

web1

" > /var/www/html/index.html

[root@localhost ~]# echo "

web2

" > /var/www/html/index.html

[root@web1 ~]# systemctl start httpd.service

[root@web1 ~]# ss -tnlp

配置haproxy:

[root@www ~]# cd /etc/haproxy/

[root@www haproxy]# vim haproxy.cfg

haproxy_第4张图片

目前下面的配置文件没用,删除上图以下的配置文件

[root@www haproxy]# systemctl start haproxy.service

[root@www haproxy]# systemctl status haproxy.service -l    #查看运行状态

wKioL1Y8ulXABJ7cAAB-5Dqv_Qg779.jpg

尝试访问,效果为轮询,因balance为roundrobin

haproxy_第5张图片

看是否能实现健康状态检查:

[root@web1 ~]# systemctl stop httpd.service

haproxy_第6张图片

<<<<<<<<<<<<<<<<<部分解释>>>>>>>>>>>>>>

global:

    log         127.0.0.1 local2    记录日志,通过日志server

    chroot      /var/lib/haproxy    将根目录切换至此目录安全运行

    pidfile     /var/run/haproxy.pid    PID文件位置

    maxconn     4000                最大连接数

    user        haproxy             运行进程的用户

    group       haproxy             

    daemon                          启动为守护进程

    # turn on stats unix socket

    stats socket /var/lib/haproxy/stats    本地访问统计数据时可以基于共享内存方式

    nbproc    启动haproxy的进程个数,只能用于守护进程时

    ulimit-n  设定每个进程打开的的最大文件数量,默认自行计算

    spread-checks

<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>

常需要调整的值:log,nbproc,maxconn,spread-checks

下面来配置一下日志:

haproxy_第7张图片

[root@www haproxy]# systemctl restart rsyslog.service    #重启日志服务

[root@www ~]# systemctl status rsyslog.service

[root@www ~]# ss -unlp    #查看514端口是否监听

[root@web1 ~]# systemctl start httpd.service    启动web1上的httpd

再次尝试访问查看是否可轮询

haproxy_第8张图片

wKiom1Y8uqfxRh8oAADABE1uOoI679.jpg

查看后端服务器的日志:(实际生产中应记录实际访问的客户端IP才有意义)

haproxy_第9张图片

总结:

  HAProxy:

    http协议反向代理

    tcp层的LB

    特性:event-driven(事件驱动),ebtree(弹性二叉树)

  配置:/etc/haproxy/haproxy.cfg(主配置文件)

    /usr/sbin/haproxy(主程序)

  启动方式:

    CentOS 6: /etc/rc.d/init.d/haproxy (调用脚本)

    CentOS 7: haproxy.service    (unit file)

    配置分为两段:

      global:

        log

        maxconn  最大并发连接

        ...

      proxies  (代理相关)

        defaults,frontednd,bakcend,listen

    

HAProxy(2)

代理参数:

  balance:指明负载均衡的调度算法

    动态:权重可动态调整(服务器自行调整)

    静态:调整权重不会实时生效

    roundrobin:加权轮询,动态算法,每个后端主机最多支持4128个连接

    static-rr:轮询,静态算法,每个后端主机支持的数量无上限

    leastconn:根据后端主机的负载数量(最少连接)进行调度,仅适用于长连接的会话,动态,不适于http

    source:源地址hash,基于后端服务器的权重总数,不过当后端服务器数量或权重变化时,后果...

      hash-type:hash类型

        map-based:取模法,静态

        consistent:一致性哈希法,动态

uri:

    hash-type:

      map-based:取模法,静态

      consistent:一致性哈希法,动态

url_param:根据url中的param参数的值进行调度,把值进行hash计算,并除以总权重:(比如基于username)

    hash-type:

      map-based:取模法,静态

      consistent:一致性哈希法,动态


hdr()根据请求报文中指定的header(如user-agent,referer,hostname)进行调度,把指定的header的值进行hash计算(如根据客户端浏览器类型调度)

[root@www haproxy]# vim haproxy.cfg

haproxy_第10张图片

haproxy_第11张图片

[root@www haproxy]# vim haproxy.cfg

haproxy_第12张图片

[root@www ~]# systemctl reload haproxy.service

[root@www ~]# systemctl status haproxy.service

[root@web1 ~]# for i in {1..10}; do echo "

Page $i Web1

" > /var/www/html/text$i.html; done

[root@web1 ~]# ls /var/www/html/

[root@localhost ~]# for i in {1..10}; do echo "

Page $i Web2

" > /var/www/html/text$i.html; done

此时更换不同客户端进行测试,对同一个uri的请求一定会调度到同一httpd服务器响应,此时若其中一个服务器宕机,则根据规定的算法向后轮询且剩下的服务访问依然遵循uri调度,因本次环境不具备不演示

[root@www haproxy]# vim haproxy.cfg

haproxy_第13张图片

[root@www ~]# systemctl reload haproxy.service

haproxy_第14张图片

bind:

  只能用于frontend,listen

[root@www haproxy]# vim haproxy.cfg

haproxy_第15张图片

[root@www ~]# systemctl restart haproxy.service

[root@www ~]# systemctl status haproxy.service

haproxy_第16张图片

mode:

  HAProxy的工作模式,默认为TCP,只有在服务端和客户端都为http协议时才可使用http

    tcp, http, health

log:

maxcoon:最大连接数

default_backend:

    为frontend指明使用的默认后端

    use_backend:条件式后端调用

        K.I.S.S:Keep it simple,stupid

server:

    server  [:port] [settings...]

      settings:

        backup: 设定当前server为backup server;

        check: 健康状态检测;

            inter :健康状态检测时间间隔;单位为ms, 默认为2000; 

            fall: up --> down, soft state, soft state, hard state; 

            rise:down --> up, 

        cookie 

        maxconn: 此服务器接受的并发连接的最大数量;

        maxqueue: 请求队列的最大长度;

        observe: 根据流量判断后端server的健康状态;

        weight: 指定权重,默认为1,最大为256;0表示不被调度;

        redir : 重定向;所有发往此服务器的GET和HEAD请求均以302响应;

    后端为http服务器做健康状态检测时的检测方法:

        option httpchk

[root@www haproxy]# vim haproxy.cfg

haproxy_第17张图片

[root@www ~]# systemctl reload haproxy.service

haproxy_第18张图片

基于浏览器cookie实现session sticky:

    backend websrvs

        balance     roundrobin

        cookie SERVERID insert nocache indirect

        server web1 172.16.100.68:80 check weight 1 cookie websrv1

        server web2 172.16.100.69:80 check weight 3 cookie websrv2

[root@www haproxy]# vim haproxy.cfg

haproxy_第19张图片

[root@www ~]# systemctl reload haproxy.service

haproxy_第20张图片

    要点:

        (1) 每个server有自己惟一的cookie标识;

        (2) 在backend中定义为用户请求调度完成后操纵其cookie

启用stats:

  listen statistics 

    bind *:9090

    stats enable

    stats hide-version

    #stats scope .

    stats uri /haproxyadmin?stats

    stats realm "HAPorxy\ Statistics"

    stats auth admin:mageedu

    stats admin if TRUE


[root@www haproxy]# vim haproxy.cfg

haproxy_第21张图片

[root@www ~]# systemctl restart haproxy.service

[root@www ~]# systemctl status haproxy.service

wKioL1Y8vOTjGfSDAAB8nt1PcyA628.jpg

haproxy_第22张图片

[root@www haproxy]# vim haproxy.cfg

haproxy_第23张图片

[root@www ~]# systemctl reload haproxy.service

haproxy_第24张图片

haproxy_第25张图片

显示的内容好像比刚才少了,这是因为我们没有赋予当前账户管理权限:

[root@www haproxy]# vim haproxy.cfg

haproxy_第26张图片

[root@www ~]# systemctl reload haproxy.service

haproxy_第27张图片

haproxy_第28张图片

向日志中记录额外信息:

  capture request header

  capture response header

当mode为http时,记录详细的日志信息(默认已启用)

启用或禁用提前将HTTP请求记入日志

  [no] option logasap

[root@localhost ~]# vim /etc/httpd/conf/httpd.conf

haproxy_第29张图片

[root@localhost ~]# systemctl reload httpd.service

haproxy_第30张图片

错误页面重定向

  errorfile:使用haproxy主机本地文件进行响应

  errorloc,errorloc302:使用指定的url进行响应,响应状态码为302,不适用与GET以外的其他方法

访问控制:

    http_request

    tcp_request

添加请求或响应报文首部:

    reqadd

    rspadd

[root@www haproxy]# vim haproxy.cfg

haproxy_第31张图片

[root@www ~]# systemctl reload haproxy.service

haproxy_第32张图片

option: http-server-close 长连接server端断开

option http-pretend-keepalive 假装haproxy向server请求为保持连接

ACL:

    定义及调用


补充:动静分离的示例:

    frontend  main

        bind *:80

        bind *:8080

        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             appsrvs


    #---------------------------------------------------------------------

    # static backend for serving up p_w_picpaths, stylesheets and such

    #---------------------------------------------------------------------

    backend static

        balance roundrobin

        server static1 172.16.100.11 check

        server static2 172.16.100.12 check


    backend appsrvs

        balance     roundrobin

        option forwardfor except 127.0.0.1 header X-Client

        option httpchk

        cookie SERVERID insert indirect nocache

        server  web1 172.16.100.7:80 check cookie web1

        server  web2 172.16.100.8:80 check cookie web2