HAProxy 代理负载均衡


 

                        HAProxy

    HAProxy是免费 高效 可靠的高可用及负载均衡解决方案,该软件非常适合于处理高负载
站点的七层数据请求,HAProxy的工作模式使其可以非常容易且安全地集成到我们现有的站点
架构中。使用类似的代理软件还可以对外屏蔽内部真实Web服务器,防止内部服务器遭受外部攻击

 

Haproxy有8种负载均衡算法(balance),分别如下:

1.balance roundrobin # 轮询,软负载均衡基本都具备这种算法

2.balance static-rr # 根据权重,建议使用

3.balance leastconn # 最少连接者先处理,建议使用

4.balance source # 根据请求源IP,建议使用

5.balance uri # 根据请求的URI

6.balance url_param,# 根据请求的URl参数'balance url_param' requires an URL parameter name

7.balance hdr(name) # 根据HTTP请求头来锁定每一次HTTP请求

8.balance rdp-cookie(name) # 根据据cookie(name)来锁定并哈希每一次TCP请求

 

由于负载请求分发到不同服务器,可能导致Session会话不同步的问题,若想实现会话共享或保持,可采用如下3种方式:

1.用户IP 识别

haroxy 将用户IP经过hash计算后 指定到固定的真实服务器上(类似于nginx 的IP hash 指令)

配置指令

balance source

2.Cookie 识别

haproxy 将WEB服务端发送给客户端的cookie中插入(或添加加前缀)haproxy定义的后端的服务器COOKIE ID。

配置指令例举

cookie SESSION_COOKIE insert indirect nocache

用firebug可以观察到用户的请求头的cookie里 有类似” Cookie jsessionid=0bc588656ca05ecf7588c65f9be214f5; SESSION_COOKIE=app1” SESSION_COOKIE=app1就是haproxy添加的内容

3.Session 识别

haproxy 将后端服务器产生的session和后端服务器标识存在haproxy中的一张表里。客户端请求时先查询这张表。

配置指令例举

appsession JSESSIONID len 64 timeout 5h request-learn

 

 

 

安装部署HAProxy

 

环境准备:两台机器

linux-node1.example.com     192.168.56.11

linux-node2.example.com     192.168.56.12

 

第一台

[root@linux-node1 ~]# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) [root@linux-node1 ~]# uname -r 3.10.0-327.el7.x86_64 关闭防火墙及SELIUNX #systemctl disable firewalld #systemctl disable NetworkManager # cat /etc/selinux/config SELINUX=disabled 安装依赖包epel rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
yum -y install net-tools vim lrzsz tree screen lsof tcpdump nc mtr nmap wget gcc glibc gcc-c++ make 

 

第二台

[root@linux-node2 ~]# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) [root@linux-node2 ~]# uname -r 3.10.0-327.el7.x86_64 关闭防火墙及SELIUNX #systemctl disable firewalld #systemctl disable NetworkManager # cat /etc/selinux/config SELINUX=disabled 安装系统依赖包 #rpm -ivh http://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
#yum -y install net-tools vim lrzsz tree screen lsof tcpdump nc mtr nmap wget gcc glibc gcc-c++ make 


 

 

部署应用

在两台机器部署apache作为RS

linux-node1.example.com

[root@linux-node1 ~]# yum -y install httpd [root@linux-node1 ~]# vim /etc/httpd/conf/httpd.conf ServerName 192.168.56.11 Listen 8080 [root@linux-node1 ~]# systemctl enable httpd [root@linux-node1 ~]# systemctl start httpd [root@linux-node1 ~]# echo "chuck-test1" > /var/www/html/index.html [root@linux-node1 ~]# netstat -tunlp | grep httpd tcp6 0      0 :::8080                 :::*                    LISTEN      2836/httpd [root@linux-node1 ~]# curl http://192.168.56.11:8080
chuck-test1

 

linux-node2.example.com

[root@linux-node2 ~]# yum -y install httpd [root@linux-node2 ~]# vim /etc/httpd/conf/httpd.conf ServerName 192.168.56.12 Listen 8080 [root@linux-node2 ~]# systemctl enable httpd [root@linux-node2 ~]# systemctl start httpd [root@linux-node2 ~]# echo "chuck-test2" > /var/www/html/index.html [root@linux-node2 ~]# netstat -tunlp | grep httpd tcp6 0      0 :::8080                 :::*                    LISTEN      2836/httpd [root@linux-node2 ~]# curl http://192.168.56.12:8080
chuck-test2

 

Linux-node1上面安装HAProxy软件

[root@linux-node1 ~]# cd /usr/local/src/ [root@linux-node1 src]# wget http://www.haproxy.org/download/1.6/src/haproxy-1.6.3.tar.gz
[root@linux-node1 src]# tar zxf haproxy-1.6.3.tar.gz [root@linux-node1 src]# cd haproxy-1.6.3 [root@linux-node1 haproxy-1.6.3]# make TARGET=linux2628 PREFIX=/usr/local/haproxy-1.6.3 [root@linux-node1 haproxy-1.6.3]# make install [root@linux-node1 haproxy-1.6.3]# cp /usr/local/sbin/haproxy /usr/sbin/ [root@linux-node1 haproxy-1.6.3]# haproxy -v HA-Proxy version 1.6.3 2015/12/25 Copyright 2000-2015 Willy Tarreau <willy@haproxy.org>

 

编辑haproxy启动脚本

[root@linux-node1 haproxy-1.6.3]# cd /usr/local/src/haproxy-1.6.3 [root@linux-node1 haproxy-1.6.3]# cp examples/haproxy.init /etc/init.d/haproxy [root@linux-node1 haproxy-1.6.3]# chmod 755 /etc/init.d/haproxy

 

针对配置文件下的路径创建目录

[root@linux-node1 ~]# useradd -r haproxy [root@linux-node1 ~]# mkdir /etc/haproxy [root@linux-node1 ~]# mkdir /var/lib/haproxy [root@linux-node1 ~]# mkdir /var/run/haproxy

 

编辑haproxy配置文件,配置log,并启动

[root@linux-node1 ~]# cd /etc/haproxy/ [root@linux-node1 haproxy]# cat haproxy.cfg global #全局配置,在所有配置段中都生效 log 127.0.0.1 local3 info #记录日志 chroot /var/lib/haproxy user haproxy group haproxy daemon defaults #默认配置,可以被前端和后端继承 log global #使用global的log设置 mode http #使用http模式,也可以使用tcp模式 option httplog #启动http请求的log option dontlognull #在日志中不记录空连接(空连接:健康检查的链接) timeout connect 5000 #长连接超时时间 timeout client 50000 #客户端连接超时 timeout server 50000 #RS连接超时 frontend www_chuck-blog_com #前端配置 + 一个配置段的名字(最好不要乱写,和项目直接相关最佳) mode http #使用http模式,也可以使用tcp模式 bind *:80 #监听80端口 stats uri /haproxy?stats #状态页面dashboard default_backend www_chuck-blog_com_backend #对应的backend名称 backend www_chuck-blog_com_backend #对应的frontend的default_backend #source cookie SERVERID option httpchk GET /index.html #设置检测url的详细的页面 balance roundrobin #使用rr负载均衡方式 server linux-node1 192.168.56.11:8080 check inter 2000 rise 3 fall 3 weight 5 server linux-node2 192.168.56.12:8080 check inter 2000 rise 3 fall 3 weight 1 #RS健康检测时间间隔2秒,重试三次,失败三次不可用,权重1

 

打开rsyslog配置文件的注释

[root@linux-node1 haproxy]# vim /etc/rsyslog.conf 15 $ModLoad imudp #打开注释 16 $UDPServerRun 514 #打开注释 local7.* /var/log/boot.log #在此行的下面添加如下内容 local3.* /var/log/haproxy.log #local3的路径

 

启动HAProxy

[root@linux-node1 haproxy]# systemctl restart rsyslog.service [root@linux-node1 haproxy]# /etc/init.d/haproxy start

 

检查是否成功

查看检测状态

 

 通过ACL设置虚拟主机

 

通过acl设置虚拟主机,一个前端可以对应多个后端

[root@linux-node1 haproxy]# cat haproxy.cfg global log 127.0.0.1 local3 info chroot /var/lib/haproxy user haproxy group haproxy daemon defaults log global mode http option httplog option dontlognull timeout connect 5000 timeout client 50000 timeout server 50000 frontend www_chuck-blog_com mode http bind *:80 stats uri /haproxy?stats
   #默认的backend default_backend www_chuck
-blog_com_backend acl is_other_chuck-blog_com hdr_end(host) other.chuck-blog.com
  #is_other_chuck-blog_com:给此acl起一个名字;hdr(host):固定格式,用来识别host,如果没有匹配到acl,即访问default的bankcend use_backend other_chuck
-blog_com_backend if is_other_chuck-blog_com
  #use_backend:关键词,使用哪个banckend;other_chuck-blog_com_backend:指定哪个backend的名称;if is_other_chuck-blog_com:用来判断acl backend www_chuck
-blog_com_backend option forwardfor header X-REAL-IP option httpchk GET /index.html balance roundrobin server linux-node1 192.168.56.11:8080 check inter 2000 rise 3 fall 3 weight 1 backend other_chuck-blog_com_backend option forwardfor header X-REAL-IP option httpchk GET /index.html balance roundrobin server linux-node2 192.168.56.12:8080 check inter 2000 rise 3 fall 3 weight 1

 

重启

[root@linux-node1 ~]# systemctl reload haproxy

 

在本地电脑使用host解析

192.168.56.11 www.chuck-blog.com other.chuck-blog.com

 

通过浏览器访问不同的域名

在fortend添加acl,根据静态文件,设置不同的backend(类似于location),注释的两行和前两行的意义相同

分别是通过url正则匹配和url的后缀匹配

acl is_static_reg url_reg /*.(css|jpg|png|js|jpeg|gif)$ use_backend other_chuck-blog_com_backend if is_static_reg #acl is_static_path path_end .gif .png .css .jpg .jpeg #use_backend other_chuck-blog_com_backend if is_static_path

[root@linux-node2 ~]# echo "This is a static test page " >/var/www/html/abc.js
[root@linux-node1 ~]# /etc/init.d/haproxy restart

 

打开浏览器查看

其它ACL  可以查看百度

acl is_do_path url_reg /chuck.do use_backend other_chuck-blog_com_backend if is_do_path acl is_UA_path hdr_reg(User-Agent) -i andriod #基于安卓手机 use_backend other_chuck-blog_com_backend if is_UA_path

 

 

HAProxy动态维护

在配置文件添加socket

[root@linux-node1 haproxy]# head -8 haproxy.cfg global log 127.0.0.1 local3 info chroot /var/lib/haproxy user haproxy group haproxy daemon  stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
  #指定socket文件路径,权限,管理级别 stats timeout 2m
  #指定超时时间

 

重启服务生效

[root@linux-node1 haproxy]# /etc/init.d/haproxy restart

 

安装socat连接haproxy.sock文件

[root@linux-node1 ~]yum install -y socat

 

使用help查看socat的事情

[root@linux-node1 haproxy]# echo "help" |socat stdio /var/lib/haproxy/haproxy.sock Unknown command. Please enter one of the following commands only : 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 #查看所有poll show stat : report counters for each proxy and server #显示状态 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 #改变一个server的转态权重或地址
  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 #将一个server或者fortend置于维护模式 enable : re-enable a server or frontend which is in maintenance mode #启用一个维护状态的server或者frontend shutdown : kill a session or a frontend (eg:to release listening ports) show acl [id] : report avalaible 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 avalaible 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

 

 设置监控

查看info信息,内容值可以利用来监控

[root@linux-node1 haproxy]# echo "show info" |socat stdio /var/lib/haproxy/haproxy.sock Name: HAProxy Version: 1.6.3 Release_date: 2015/12/25 Nbproc: 1 Process_num: 1 Pid: 6778 Uptime: 0d 0h16m20s Uptime_sec: 980 Memmax_MB: 0 Ulimit-n: 4033 Maxsock: 4033 Maxconn: 2000 Hard_maxconn: 2000 CurrConns: 0 CumConns: 10 CumReq: 12 Maxpipes: 0 PipesUsed: 0 PipesFree: 0 ConnRate: 0 ConnRateLimit: 0 MaxConnRate: 2 SessRate: 0 SessRateLimit: 0 MaxSessRate: 2 CompressBpsIn: 0 CompressBpsOut: 0 CompressBpsRateLim: 0 Tasks: 8 Run_queue: 1 Idle_pct: 100 node: linux-node1.example.com description: 

 

关闭主机

关闭linux-node2主机

 

[root@linux-node1 haproxy]# echo "disable server other_chuck-blog_com_backend/linux-node2" |socat stdio /var/lib/haproxy/haproxy.sock [root@linux-node1 haproxy]# Message from syslogd@localhost at Dec  4 13:31:37 ... haproxy[6778]: backend other_chuck-blog_com_backend has no server available!

可以看到 linux -node2  进入了维护maintain状态 

 

开启主机

打开linux-node2主机(只对现有的server生效,不能用来新增节点)

[root@linux-node1 haproxy]# echo "enable server other_chuck-blog_com_backend/linux-node2" |socat stdio /var/lib/haproxy/haproxy.sock

可以看到linux-node2恢复正常

 

 

生产问题

haproxy的本地端口可能用尽,解决方案

1)更改local的端口范围,调整内核参数

[root@linux-node1 haproxy]# cat /proc/sys/net/ipv4/ip_local_port_range 32768    61000

 

2)调整timewait的端口复用,设置为1

[root@linux-node1 haproxy]# cat /proc/sys/net/ipv4/tcp_tw_reuse 0

 

3)缩短tcp_wait的时间,并不建议修改

[root@linux-node1 haproxy]# cat /proc/sys/net/ipv4/tcp_fin_timeout 60

 

4)终极方案:增加为多个ip,自然端口数就够了

 

haproxy对比nginx

 

nginx

优点:

1 web服务器,应用比较广泛

2 7层负载均衡,location设置复杂的基于HTTP的负载均衡

3 性能强大,网络依赖小

4 安装配置简单

缺点

1 监控检查单一

2 负载均衡算法少

3 不能动态管理

4 没有集群upstream的状态页面

 

haproxy

优点

1 专门做负载均衡

2 负载均衡算法多

3 性能>=nginx

4 通过和haproxy socker通信进行动态管理

5 有比较丰富的dashboard页面

6 强大的7层代理

 

缺点

1 配置没有nginx简单

2 应用没有nginx广泛

 

提示:很多CDN会使用LVS+Haproxy来做负载均衡

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM