本文发布于Cylon的收藏册,转载请著名原文链接~


haproxy 介绍

haproxy是一个开源的、高性能的基于TCP和HTTP应用代理的高可用的、负载均衡服务软件,它支持双机热备、高可用、负载均衡、虚拟主机、基于TCP和HTTP的应用代理、图形界面查看信息等功能。其配置简单、维护方便,而且拥有很好的对服务器节点的健康检查功能(相当于keepalived健康检查),当其代理的后端服务器出现故障时,haproxy会自动的将该故障服务器摘除,当故障的服务器恢复后,haproxy还会自动将该服务器自动加入进来提供服务。

LVS/NGINX对比

haproxy 特别适用于那些高负载、访问量很大,但又需要会话保持及七层应用代理的业务应用。haproxy运行在今天的普通的服务器硬件上,几乎不需要进行任何的优化就可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单、轻松、安全的整合到各种己有的网站架构中,同时,haproxy的代理模式,可以使得所有应用服务器不会暴露到公共网络上,即后面的节点服务器不需要公网IP地址。

从1.3版本起,haproxy软件引入了frontend,backend的功能,frontend (ad规则匹配)可以让运维管理人员根据任意HTTP请求头内容做规则匹配,然后把请求定向到相关的backend(这个是事先定义好的多个server pools,等待前端把请求转过来的服务器组)。通过frontend和backend,我们可以很容易的买现haproxy的各种7层应用代理功能。

haproxy代理模式

haproxy支持两种主要代理模式:

1、基于4层的tcp应用代理(例如:可用于邮件服务、内部协议通信服务器、MySQL、HTTPS服务等)。

2、基于7层的http代理。在4层tcp代理模式下,haproxy仅在客户端和服务器之间进行流量转发。但是在7层http代理模式下,haproxy会分析应用层协议,并且能通过允许、拒绝、交换、增加、修改或者删除请求(request)或者回应(response)里指定内容来控制协议。

官方网站:www.haproxy.org

haproxy 解决方案拓扑图

haproxy L4负载均衡应用架构拓扑

haproxy软件的四层tcp应用代理非常优秀,且配置非常简单、方便,比LVS和Nginx的配置要简单很多,首先,配置haproxy不需要在RS端做任何特殊配置 (只要对应服务开启就OK)就可以实现应用代理,其次,haproxy的配置语法和增加虚拟主机功能等也比lvs/nginx简单。并且和商业版的NS (Netscaler)、F5, A10等负载均衡硬件的使用方法和在架构中的位置一模一样。下面是haproxy的Layer4层应用代理的拓扑结构图:


说明:由于haproxy软件采用的是类NAT模式(本质不同)的应用代理,数据包来去都会经过haproxy,因此,在流量特别大的情况下(门户级别的流量),其效率和性能不如LVS的DR模式负载均衡。


在一般的中小型公司,建议采用haproxy做负载均衡,而不要使用LVS或Nginx。为什么强调中小型公司呢?换句话说,千万PV级别以下直接使用haproxy做负载均衡,会让我们负责维护的运维管理人员配置简单、快速、维护方便,出问题好排查。

haproxy L7负载均衡应用架构拓扑

haproxy软件的最大优势在于其7层的根据URL请求头应用过滤的功能以及sesson会话功能,在门户网站的高并发生产架构中,haproxy软件一般用在4层LVS负载均衡软件的下一层,或者像haproxy官方推荐的也可以挂在硬件负载均衡althon, NS, F5, A10下使用,其表现非常好。从2009年起taobao,京东商城的业务也大面积使用了haproxy作为7层CACHE应用代理。

安装haproxy

模拟真实环境

搭建合适的模拟环境是一个人学习能力的重要体现。例如:人类第一次上太空也没有真正的环境,但是想去太空就是要自己动手去搭建逼真的模拟环境。实验多了就是经验,自然就有解除生产环境的机会了。

名称 接口 IP 用途
MASTER eth0 10.0.0.7 外网管理IP用于WAN数据转发
eth1 172.16.1.7 内网管理IP,用于LAN数据转发
eth2 10.0.10.7 用于服务器间心跳连接(直连)
VIP 10.0.0.17 用于提供应用程序A挂载服务
BACKUP eth0 10.0.0.8 外网管理IP,用于WAN数据转发
eth1 172.16.1.8 内网管理IP,用于LAN数据转发
eth2 10.0.10.8 用于服务器间心跳连接(直连)
VIP 10.0.0.8 用于提供应用程序B挂载服务

下载安装haproxy

下载地址:http://www.haproxy.org/download/

文档地址:http://www.haproxy.org/download/1.7/doc/configuration.txt

编译haproxy

make TARGET=linux2628 ARCH=x86_64  # <==64位编译配置
make TARGET=linux2628 ARCH=i386    # <==32位编译配置
make PREFIX=/app/haproxy-1.7.5 install 
ln -s /app/haproxy-1.7.5/ /app/haproxy

配置内核转发功能

net.ipv4_forward=1  # <==基于NAT模式的负载均衡器都需要打开系统转发功能
sysctl -p

haproxy启动命令

直接运行命令查看帮助

$ /app/haproxy/sbin/haproxy
HA-Proxy version 1.7.5 2017/04/03
Copyright 2000-2017 Willy Tarreau <willy@haproxy.org>

Usage : haproxy [-f <cfgfile|cfgdir>]* [ -vdVD ] [ -n <maxconn> ] [ -N <maxpconn> ]
        [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]
        -v displays version ; -vv shows known build options.
        -d enters debug mode ; -db only disables background mode.
        -dM[<byte>] poisons memory with <byte> (defaults to 0x50)
...

命令选项

选项 说明
-D 以后台守护进程启动服务
-f 指定配置文件
-c 检查配置文件语法
-n 设置最大连接数,一般在配置文件中指定
-q 启动时不显示警告
-m 限制使用的内存量
-p 将pid写入文件
-sf 平滑重启
-st 强制重启

注意 -sf-st 重启时需要指定配置文件

haproxy服务脚本

在下载解压目录中有默认的启动脚本

$ ll /root/tools/haproxy-1.7.5/examples/haproxy.init
/root/tools/haproxy-1.7.5/examples/haproxy.init

自定义启动脚本

#!/bin/sh
BASE=/app/haproxy
COMM=$BASE/sbin/haproxy
PIDFILE=$BASE/var/run/haproxy.pid
CONF_FILE=$BASE/conf/haproxy.conf1
case "$1" in
	'start'|'START')
		if [ ! -f $PIDFILE ];then
				$COMM -f $CONF_FILE -D
		else
				echo 'haproxy has been started'
		fi
		;;
	'status'|'STATUS')
		if [ ! -f $PIDFILE ];then
			echo 'haproxy is not running'
			exit 1
		fi
		for pid in $(cat $PIDFILE);do
			kill -0 $pid
			RETVAL=$?
			if [ $RETVAL == 0 ];then
				echo 'process '$pid ' not running'
			fi
		done
		echo 'haproxy is running'
		;;
	'restart'|'RESTART')
		$COMM -f $CONF_FILE -sf $(cat $PIDFILE)
		;;
	'stop'|'STOP')
		kill $(cat $PIDFILE)
		rm -f $PIDFILE
		;;
	'check'|'CHECK')
		$COMM -f $CONF_FILE -c
		;;
	*)
		echo "USAGE $0 start|stop|restart|status|check|"
		exit 1
		;;
esac

haproxy配置文件

haproxy 的默认配置文件在下载解压目录下

/root/tools/haproxy-1.7.5/examples

aproxy的配置文件可以分为5部分

  • global:全局配置参数段,主要用来控制haproxy启动前的进程及系统相关设置。

  • default:配置一些默认参数,如果frontend,backend,listen等段未设置则使用default段配置。

  • listen:

  • frontend:用来匹配接受客户所请求的域名,uri等,并针对不同配置,做不同的请求处理。

  • backend:定义后端服务器集群,以及对后端 服务器的一切权重、队列、连接数等选项的设置。

配置文件示例注释说明

global #<==全局配置, 用于设定义全局参数, 属于进程级的配置, 通常与操作系统配置有关
	chroot  /app/haproxy/var/chroot #<==运行路径
	daemon #<==以守护方式运行haproxy
	user    haproxy #<==运行haproxy用户/组, 或者使用关键字uid/gid
    group   haproxy
log		127.0.0.1 local0 debug 
# 全局日志配置指定127.0.0.1:514的syslog服务中local0日志设备。
# 与记录日志的模式[err warning info debug]
    pidfile /app/haproxy/var/run/haproxy.pid
    
maxconn	2000 
#设置每haproxy进程的最大并发连接数, 其等同于命令行选项“-n”; 
# “ulimit -n”自动计算的结果参照此参数设定.
    
    nbproc  1 #<==启动的haproxy进程数量, 只能用于守护进程模式。应该设置为cup核数
    
# ulimit-n 655350  
# 设置每进程所能够打开的最大文件描述符数目。
# 默认情况其会自动进行计算, 因此不推荐修改此选项.    
    
  defaults #<==默认配置

    mode http  #<==默认的模式【tcp:4层; http:7层; health:只返回OK】
    
    log global #<==继承全局的日志定义输出
      
    #option httplog #<==日志类别, httplog
   
    # 如果后端服务器需要记录客户端真实ip, 需要在HTTP请求中添加”X-Forwarded-For”字段;
# 但haproxy自身的健康检测机制访问后端服务器时, 不应将记录访问日志。
# 可用except来排除127.0.0.0,即haproxy本身.
    #option forwardfor except 127.0.0.0/8
option forwardfor

option httpclose 
# 开启http协议中服务器端关闭功能每个请求完毕后主动关闭http通道。
# 使得支持长连接,使得会话可以被重用,使得每一个日志记录都会被记录.
 
    option dontlognull #<==如果产生了一个空连接,那这个空连接的日志将不会记录.
    
    option redispatch	#<==当与后端服务器的会话失败(服务器故障或其他原因)时, 把会话重新分发到其他健康的服务器上; 当故障服务器恢复时, 会话又被定向到已恢复的服务器上;
    
	retries 3  #<==在判定会话失败时的尝试连接的次数
      
    option abortonclose #<==当haproxy负载很高时, 自动结束掉当前队列处理比较久的连接.
   
    timeout http-request 10s #<==默认http请求超时时间
	
    timeout queue 1m	#<==默认队列超时时间, 后端服务器在高负载时, 会将haproxy发来的请求放进一个队列中.
    
    timeout connect 5s	#<==haproxy与后端服务器连接超时时间.
    
    timeout client 1m	#<==客户端与haproxy连接后, 数据传输完毕, 不再有数据传输, 即非活动连接的超时时间.
    
    timeout server 1m	#<==haproxy与后端服务器非活动连接的超时时间.
    
    timeout http-keep-alive 10s #<==默认新的http请求连接建立的超时时间,时间较短时可以尽快释放出资源,节约资源.
    
    timeout check 10s	#<==心跳检测超时时间
      
    maxconn 2000	#<==最大并发连接数
      
    #设置默认的负载均衡方式
    #balance source 
    #balnace leastconn

  listen admin_status 
  # 统计页面配置, frontend和backend的组合体。
  # 监控组的名称可按需自定义
    
    mode http #<==监控运行模式
      
    bind 0.0.0.0:80	#<==统计页面访问端口
      
    maxconn 10  #<==统计页面默认最大连接数
      
    option httplog  #<==#http日志格式
      
    stats enable   #<==开启web统计
      
    stats hide-version 	#<==隐藏统计页面上的haproxy版本信息
      
    stats refresh 30s	#<==监控页面自动刷新时间
      
    stats uri /admin?status #<==统计页面访问url
    
	stats auth admin:111	#<==监控页面的用户和密码:admin, 可设置多个用户名
    
    stats realm hellow world #<==统计页面密码框提示文本
    
    stats admin if TRUE	#<==手工启动/禁用后端服务器, 可通过web管理节点
    
	#设置haproxy错误页面
    #errorfile 400 /usr/local/haproxy/errorfiles/400.http
    #errorfile 403 /usr/local/haproxy/errorfiles/403.http
    #errorfile 408 /usr/local/haproxy/errorfiles/408.http
    #errorfile 500 /usr/local/haproxy/errorfiles/500.http
    #errorfile 502 /usr/local/haproxy/errorfiles/502.http
    #errorfile 503 /usr/local/haproxy/errorfiles/503.http
    #errorfile 504 /usr/local/haproxy/errorfiles/504.http
	
	option forwardfor #<==将用户的IP转发给监控的IP
	option httpchk HEAD /check.html HTTP/1.0 #<==http的健康检查
	
  frontend  WEB_SITE  #<==vip
	bind    *:80
	mode    http
	log     global
	option  httplog    
	option  httpclose  <== http7层代理专用
	default_backend WWW
  backend WWW #<==real server
	option forwardfor header X-REAL-IP
	option httpchk HEAD / HTTP/1.0  <==检查real server是否存活的方式,[get post head]
	server web1 10.0.0.3:80 check inter 2000 rise 30 fall 15  
	server web2 www.test.com check inter 2000 rise 30 fall 15  
# inter为检查间隔 rise为连续30次检查成功则认为有效的。
# fall为连续15次检查失败则认为宕机

haproxy日志配置

CentOS 5.X

编辑/etc/syslog.conf增加如下配置

local0.* /app/haproxy/logs/haproxy.log

CentOS 6 & 7

local0.* -/app/haproxy/logs/haproxy.log 
# 将local0设备的日志定向到haproxy.log因为haproxy使用的local0

注:使用了local0设备需要将 local0 在 /var/log/message 里制空,否则会记录双份


*.info;mail.none;authpriv.none;cron.none;local0.none;    /var/log/messages

修改/etc/sysconfig/syslog

#-r enables logging from remote machines
# -x disables DNS lookups on messages recieved with -r
SYSLOGD_OPTIONS="-m 0 -r -c 2"

重启后生效

/etc/init.d/syslog restart  # <== CentOS 5
/etc/init.d/rsyslog restart # <== CentOS 6
systemctl restart rsyslog   # <== CentOS 7

http://www.cnblogs.com/aaa103439/p/3537163.html

http://www.cnblogs.com/MacoLee/p/5853413.html

基于权重的轮训round robin

server web1 10.0.0.2 check  weight 3
server web1 10.0.0.3 check  weight 1
for n in {0..20};do curl 10.0.02;sleep 1 done

leastconn–> 类似于 lvs中 的 wlc

不过这里只考虑活动连接数,即选择活动连接数少的。另外,最好在长连接会话中使用,如sql,ldap

image-20221213234451180

负载模式实验

环境准备

IP 地位
10.0.0.2 haproxy
10.0.0.1 real server 1
10.0.0.3 real server 2

TCP负载模式配置

frontend  WEB_SITE  #<==vip
  bind *:80
  mode    tcp
  log     global
  default_backend WWW
backend WWW #<==real server
  server web1 10.0.0.3:52113 check inter 2000 rise 3 fall 5
  server web2 10.0.0.1:52113 check inter 2000 rise 3 fall 5

注意:listen可以看做是frontend与bankend的集合,顾如果使用tcp模式代理的话,不要开启web监控


image-20221213234451180

TCP代理所出现的问题

tcp模式开启web监控页面出现负载准问题

开启web监控页面的haproxy日志

May 19 22:41:02 127.0.0.1 haproxy[2579]: Connect from 192.168.2.1:50820 to 10.0.0.2:80 (WEB_SITE/TCP)
May 19 22:41:02 127.0.0.1 haproxy[2579]: Connect from 192.168.2.1:50820 to 10.0.0.2:80 (WEB_SITE/TCP)
May 19 22:41:02 127.0.0.1 haproxy[2578]: 192.168.2.1:50821 [19/May/2017:22:41:02.405] admin_status admin_status/<STATS> 0/0/0/0/1 200 16975 - - LR-- 0/0/0/0/0 0/0 "GET /admin?status HTTP/1.1"
May 19 22:41:02 127.0.0.1 haproxy[2579]: Connect from 192.168.2.1:50822 to 10.0.0.2:80 (WEB_SITE/TCP)
May 19 22:41:02 127.0.0.1 haproxy[2579]: Connect from 192.168.2.1:50822 to 10.0.0.2:80 (WEB_SITE/TCP)
May 19 22:41:02 127.0.0.1 haproxy[2579]: 192.168.2.1:50823 [19/May/2017:22:41:02.816] admin_status admin_status/<STATS> 0/0/0/0/1 200 16996 - - LR-- 0/0/0/0/0 0/0 "GET /admin?status HTTP/1.1"

代理ssh负载出现如下问题

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
11:f2:f1:05:1e:80:0a:bf:9f:09:20:3f:02:e1:12:b8.
Please contact your system administrator.
Add correct host key in /root/.ssh/known_hosts to get rid of this message.
Offending RSA key in /root/.ssh/known_hosts:1
RSA host key for [10.0.0.2]:80 has changed and you have requested strict checking.
Host key verification failed.

出现此问题是因为,登陆ssh时使用的是vip,而真正的server是两个,当登陆第一台server时,将指纹保存到vip,当轮训到第二台时,因为已经保存过其他server的指纹了,会提示指纹改变。所以这个不算是问题

L7代理实验

frontend  WEB_SITE  #<==vip
  bind *:80
  mode    http
  option  httplog
  option  httpclose
  log     global
  default_backend WWW
backend WWW #<==real server
  server web1 10.0.0.3:52113 check inter 2000 rise 3 fall 5
  server web2 10.0.0.1:52113 check inter 2000 rise 3 fall 5

image-20221213234451180

ACL

ACL名称必须由 大小写字母、数字、”-“(破折号)、“_”(下划线)、“.”(点)和 ”:“(冒号)。 ACL名称区分大小写,这意味着 “my_acl” 和 “My_Acl” 是两个不同的ACL。ACL的数量没有强制限制。未使用的不影响性能,他们只是消耗少量的内存。


注:在http代理模式中uri的请求会被分配到real server的实体路径中


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

参数说明:

  • <aclname> <==ACL名称;

  • <criterion>:测试标准,即对什么信息发起测试;测试方式可以由 [flags] 指定的标志进行调整;而有些测试标准也可以需要为其在之前指定一个操作符 [operator];

ACL的flag:

  • -i:在匹配所有后续模式时忽略大小写。
  • -f:从文件加载模式。
  • -m:使用特定的模式匹配方法
  • -n:禁止DNS解析
  • -M:像地图文件一样加载-f指向的文件。
  • – :强制结束标志。 当字符串看起来像其中一个标志时很有用。
  • -u:强制ACL的唯一ID

<value>:acl测试条件支持的值有以下四类:

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

常用的测试标准(criteria)

be_sess_rate(backend) <integer>

用于测试指定的backend上会话创建的速率(即每秒创建的会话数)是否满足指定的条件;常用于在指定backend上的会话速率过高时将用户请求转发至另外的backend,或用于阻止攻击行为。

例如:

acl being_scanned be_sess_rate gt 50  # <==此方案是定义在backend里的
redirect location /error_pages/denied.html if being_scanned

sd

fe_sess_rate(frontend) <integer>

用于测试指定的frontend(或当前frontend)上的会话创建速率是否满足指定的条件;

常用于为frontend指定一个合理的会话创建速率的上限以防止服务被滥用。例如下面的例子限定入站邮件速率不能大于50封/秒,所有在此指定范围之外的请求都将被延时50毫秒。

frontend mail
    bind :25
    mode tcp
    maxconn 500
    acl too_fast fe_sess_rate ge 50
    tcp-request inspect-delay 50ms
    tcp-request content accept if ! too_fast
    tcp-request content accept if WAIT_END

hdr <string>

用于测试请求报文中的所有首部或指定首部是否满足指定的条件;指定首部时,其名称不区分大小写,且在括号 “()” 中不能有任何多余的空白字符。测试服务器端的响应报文时可以使用 shdr()。例如下面的例子用于测试首部Connection的值是否为close。

acl url_bao hdr(Host) -i www.baidu.com

method <string>

测试HTTP请求报文中使用的方法。

front test
  use_backend front
  acl me method get
  default_backend back
backend front
  server web01 10.0.0.1:8080 check port 8080 inter 5000 fall 5
backend back
  server w1 10.0.0.3:8080 check port 8080 inter 5000 fall 5

image-20221214000225672

path_beg <string>

用于测试请求的URL是否以指定的模式开头。

下面的例子用于测试URL是否以/static、/images、/javascript或/stylesheets头。

acl url_static path_beg -i /static /images /javascript /stylesheets

path_end <string>

用于测试请求的URL是否以指定的模式结尾。

例如,下面的例子用户测试URL是否以jpg、gif、png、css或js结尾

acl url_static path_end -i .jpg .gif .png .css .js

hdr_beg <string>

用于测试请求报文的指定首部的开头部分是否符合指定的模式。

例如,下面的例子用记测试请求是否为提供静态内容的主机img、video、download或ftp。

acl host_static hdr_beg(host) -i img. video. download. ftp.

请求uri中包含static

acl timetask_req url_dir -i timetask

请求头长度

acl cl hdr_cnt(Content-length) eq 0

web stats

添加一个 frontend

frontend stats
	# 必填参数,默认无法访问
    mode http   
    
    # 统计页面访问端口
    bind 0.0.0.0:1080
    
    # 统计页面默认最大连接数
    maxconn 10
    
    # http日志格式
    option httplog
    
    # 开启web统计
    stats enable
    # 隐藏统计页面上的haproxy版本信息
    stats hide-version
    
    # 监控页面自动刷新时间
    stats refresh 30s
    
    # 统计页面访问url
    stats uri /admin?status
    
    # 监控页面的用户和密码:admin, 可设置多个用户名
    stats auth admin:111
    
    # 统计页面密码框提示文本,某些浏览器不适合中文
    stats realm mCloud\ Haproxy
    
    # 手工启动/禁用后端服务器, 可通过web管理节点
    stats admin if TRUE

img

image-20221214000411609

socat动态操作haproxy

socat是一个多功能的网络工具软件,名字来由是”Socket CAT”,功能与netcat类似,可以看做netcat的加强版。

配置haproxy

stats socket /app/haproxy/var/run/haproxy.sock mode 600 level admin
stats timeout 2m

安装socat

yum install socat -y

远程操作haproxy

socat帮助

echo help|socat stdio /app/haproxy/var/run/haproxy.sock

上线测试摘取集群节点

echo disable server back/w1 |socat stdio /app/haproxy/var/run/haproxy.sock
echo enable server back/w1 |socat stdio /app/haproxy/var/run/haproxy.sock

image-20221213234451180

本文发布于Cylon的收藏册,转载请著名原文链接~

链接:https://www.oomkill.com/2017/11/haproxy/

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」 许可协议进行许可。