zoukankan      html  css  js  c++  java
  • HAproxy + keepalived 实现双机热备

    一、HAProxy简介:


    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


    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;

    若要获得最高性能,需要在Linux 2.6或打了epoll补丁的Linux 2.4上运行haproxy 1.2.5以上的版本。haproxy 1.1l默认使用的polling系统为select(),其处理的文件数达数千个时性能便会急剧下降。1.2和1.3版本默认的为poll(),在有些操作系统上可会也会有性能方面的问题,但在Solaris上表现相当不错。HAProxy 1.3在Linux 2.6及打了epoll补丁的Linux 2.4上默认使用epoll,在FreeBSD上使用kqueue,这两种机制在任何负载上都能提供恒定的性能表现。

    在较新版本的Linux 2.6(>=2.6.27.19)上,HAProxy还能够使用splice()系统调用在接口间无复制地转发任何数据,这甚至可以达到10Gbps的性能。

    基于以上事实,在x86或x86_64平台上,要获取最好性能的负载均衡器,建议按顺序考虑以下方案。
    Linux 2.6.32及之后版本上运行HAProxy 1.4;
    打了epoll补丁的Linux 2.4上运行HAProxy 1.4;
    FreeBSD上运行HAProxy 1.4;
    Solaris 10上运行HAProxy 1.4;


    性能:

    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);
    MRU内存分配器在固定大小的内存池中可实现即时内存分配,这能够显著减少创建一个会话的时长;
    树型存储:侧重于使用作者多年前开发的弹性二叉树,实现了以O(log(N))的低开销来保持计时器命令、保持运行队列命令及管理轮询及最少连接队列;
    优化的HTTP首部分析:优化的首部分析功能避免了在HTTP首部分析过程中重读任何内存区域;
    精心地降低了昂贵的系统调用,大部分工作都在用户空间完成,如时间读取、缓冲聚合及文件描述符的启用和禁用等;

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

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

    可以从三个因素来评估负载均衡器的性能:
    会话率
    会话并发能力
    数据率

    集合Haproxy,Keepalived双主双机高可用模型,不论是Haproxy还是Keepalived甚至是上游服务器均提高生产力并增强可用性,也就是如下架构中Haproxy,Keepalived,Httpd服务器任意宕机一台服务还是可以正常运行的

    组件及实现的功能

    • Keepalived:实现对Haproxy服务的高可用,并采用双主模型配置;

    • Haproxy:实现对Nginx的负载均衡和读写分离;

    • Nginx:实现对HTTP请求的高速处理;

     

    架构设计图

    wKiom1Ni8taDxbQnAANjCL8rEcc897.jpg

     

    部署配置

    Keepalived部署

    配置

    yum -y install keepalived # 两节点都需部署
    # 172.16.25.109
    # vi /etc/keepalived/keepalived.conf
    ! Configuration File for keepalived
    global_defs {
       notification_email {
             root@localhost
       }
       notification_email_from admin@lnmmp.com
       smtp_connect_timeout 3
       smtp_server 127.0.0.1
       router_id LVS_DEVEL
    }
    vrrp_script chk_maintaince_down {
       script "[[ -f /etc/keepalived/down ]] && exit 1 || exit 0"
       interval 1
       weight 2
    }
    vrrp_script chk_haproxy {
        script "killall -0 haproxy"
        interval 1
        weight 2
    }
    vrrp_instance VI_1 {
        interface eth0
        state MASTER
        priority 100
        virtual_router_id 125
        garp_master_delay 1
        authentication {
            auth_type PASS
            auth_pass 1e3459f77aba4ded
        }
        track_interface {
           eth0
        }
        virtual_ipaddress {
            172.16.25.10/16 dev eth0 label eth0:0
        }
        track_script {
            chk_haproxy
        }
        notify_master "/etc/keepalived/notify.sh master 172.16.25.10"
        notify_backup "/etc/keepalived/notify.sh backup 172.16.25.10"
        notify_fault "/etc/keepalived/notify.sh fault 172.16.25.10"
    }
    vrrp_instance VI_2 {
        interface eth0
        state BACKUP
        priority 99
        virtual_router_id 126
        garp_master_delay 1
        authentication {
            auth_type PASS
            auth_pass 7615c4b7f518cede
        }
        track_interface {
           eth0
        }
        virtual_ipaddress {
            172.16.25.11/16 dev eth0 label eth0:1
        }
        track_script {
            chk_haproxy
    chk_maintaince_down
        }
        notify_master "/etc/keepalived/notify.sh master 172.16.25.11"
        notify_backup "/etc/keepalived/notify.sh backup 172.16.25.11"
        notify_fault "/etc/keepalived/notify.sh fault 172.16.25.11"
    }
    # 172.16.25.110
    # vi /etc/keepalived/keepalived.conf
    ! Configuration File for keepalived
    global_defs {
       notification_email {
             root@localhost
       }
       notification_email_from admin@lnmmp.com
       smtp_connect_timeout 3
       smtp_server 127.0.0.1
       router_id LVS_DEVEL
    }
    vrrp_script chk_maintaince_down {
       script "[[ -f /etc/keepalived/down ]] && exit 1 || exit 0"
       interval 1
       weight 2
    }
    vrrp_script chk_haproxy {
        script "killall -0 haproxy"
        interval 1
        weight 2
    }
    vrrp_instance VI_1 {
        interface eth0
        state BACKUP
        priority 99
        virtual_router_id 125
        garp_master_delay 1
        authentication {
            auth_type PASS
            auth_pass 1e3459f77aba4ded
        }
        track_interface {
           eth0
        }
        virtual_ipaddress {
            172.16.25.10/16 dev eth0 label eth0:0
        }
        track_script {
            chk_haproxy
    chk_maintaince_down
        }
        notify_master "/etc/keepalived/notify.sh master 172.16.25.10"
        notify_backup "/etc/keepalived/notify.sh backup 172.16.25.10"
        notify_fault "/etc/keepalived/notify.sh fault 172.16.25.10"
    }
    vrrp_instance VI_2 {
        interface eth0
        state MASTER
        priority 100
        virtual_router_id 126
        garp_master_delay 1
        authentication {
            auth_type PASS
            auth_pass 7615c4b7f518cede
        }
        track_interface {
           eth0
        }
        virtual_ipaddress {
            172.16.25.11/16 dev eth0 label eth0:1
        }
        track_script {
            chk_haproxy
        }
        notify_master "/etc/keepalived/notify.sh master 172.16.25.11"
        notify_backup "/etc/keepalived/notify.sh backup 172.16.25.11"
        notify_fault "/etc/keepalived/notify.sh fault 172.16.25.11"
    }
    # vi /etc/keepalived/notify.sh
    #!/bin/bash
    # Author: Jason.Yu <admin@lnmmp.com>
    # description: An example of notify script
    #
    contact='root@localhost'
    notify() {
        mailsubject="`hostname` to be $1: $2 floating"
        mailbody="`date '+%F %H:%M:%S'`: vrrp transition, `hostname` changed to be $1"
        echo $mailbody | mail -s "$mailsubject" $contact
    }
    case "$1" in
        master)
            notify master $2
            /etc/rc.d/init.d/haproxy start
            exit 0
        ;;
        backup)
            notify backup $2
            /etc/rc.d/init.d/haproxy stop
            exit 0
        ;;
        fault)
            notify fault $2
            /etc/rc.d/init.d/haproxy stop
            exit 0
        ;;
        *)
            echo 'Usage: `basename $0` {master|backup|fault}'
            exit 1
        ;;
    esac
    vrrp_script chk_haproxy {
        script "/etc/keepalived/chk_haproxy.sh"  # 检查脚本
        interval 2
        weight 2
    
    # 刚才两个节点 均要有 的监测脚本文件 , 防止 haproxy 停止而 keepalived 不切换的情况
    # vim /etc/keepalived/chk_haproxy.sh
    #
    #
    #!/bin/bash
    #
    if ! `pidof haproxy &> /dev/null`; then
        /etc/rc.d/init.d/haproxy  start
    fi
    sleep 2
    if ! `pidof haproxy &> /dev/null`; then
        /etc/rc.d/init.d/keepalived stop
    fi

    启动服务

    service keepalived start # 在两个节点上都需要启动

    Haproxy部署

    安装配置

    yum -y install haproxy # 两节点都需部署
    vi /etc/haproxy/haproxy.cfg # 两节点配置一致
    global
        log         127.0.0.1 local2
        chroot      /var/lib/haproxy
        pidfile     /var/run/haproxy.pid
        maxconn     4000
        user         haproxy
        group       haproxy
        daemon # 以后台程序运行;
    defaults
        mode                   http # 选择HTTP模式,即可进行7层过滤;
        log                     global
        option                  httplog # 可以得到更加丰富的日志输出;
        option                  dontlognull
        option http-server-close # server端可关闭HTTP连接的功能;
        option forwardfor except 127.0.0.0/8 # 传递client端的IP地址给server端,并写入“X-Forward_for”首部中;
        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                 30000
    listen stats
        modehttp
        bind0.0.0.0:1080 # 统计页面绑定1080端口;
        stats enable # 开启统计页面功能;
        stats hide-version # 隐藏Haproxy版本号;
        stats uri     /haproxyadmin?stats # 自定义统计页面的访问uri;
        stats realm   Haproxy\ Statistics # 统计页面密码验证时的提示信息;
        stats auth    admin:admin # 为统计页面开启登录验证功能;
        stats admin if TRUE # 若登录用户验证通过,则赋予管理功能;
    frontend http-in
        bind*:80
        mode http
        log global
        option httpclose
        option logasap
        option dontlognull
        capture request  header Host len 20
        capture request  header Referer len 60
        acl url_static       path_beg       -i /static /images /javascript /stylesheets
        acl url_static       path_end       -i .jpg .jpeg .gif .png .css .js .html
        use_backend static_servers if url_static # 符合ACL规则的,请求转入后端静态服务器
        default_backend dynamic_servers # 默认请求转入后端动态服务器
    backend static_servers
        balance roundrobin
        server imgsrv1 192.168.0.25:80 check maxconn 6000 # 静态服务器,可配置多台,还可设置权重weight;
    backend dynamic_servers
        balance source
        server websrv1 192.168.0.35:80 check maxconn 1000 # 动态服务器,可配置多台,还可设置权重weight;

    keepalived双主模型启动

    wKiom1Ni8zqzXsjWAAXwJZi3ekQ403.jpg

    Nginx部署

    见博客    http://www.cnblogs.com/xiaocen/p/3704192.html

    访问验证

    Haproxy统计页面测试

    wKioL1Ni9hjzYDblAAV2-8X-c8A579.jpg

    wKiom1Ni9A3StmxDABW-x0u1MF0209.jpg

    动静分离测试

    wKiom1Ni9mOD6XOsAAkk3jT07PM766.jpg

    wKioL1Ni9lST0rDAAAj4DLjLm2I967.jpg

     

  • 相关阅读:
    Qt之重启应用程序
    Qt之密码框不可选中、复制、粘贴、无右键菜单等
    Qt之国际化(系统文本-QMessageBox按钮、QLineEdit右键菜单等)
    HTTP全部报文首部字段
    工厂模式
    《Qt 实战一二三》
    Qt之国际化
    Java如何读取XML文件 具体实现
    href脱离iframe显示
    iframe并排横着显示
  • 原文地址:https://www.cnblogs.com/xiaocen/p/3704258.html
Copyright © 2011-2022 走看看