HAProxy负载均衡

## HAProxy

  • haproxy是属于基于七层代理的负载均衡代理方案,同样支持对四层模拟TCP的负载,功能强大;其中七层应用层是基于Http协议进行代理调度,四层是基于tcp四层协议层进行调度,支持(TLS的https和Mysql调度)
  • 提供高可用性、负载均衡以及基于TCP和HTTP应用代理、免费、开源、可靠解决方案。适用于负载大web站点
  • 实现了基于事件驱动、单一进程模型,此模型支持数千级别的并发连接
  • haproxy不能实现ha高可用,但是可以基于健康检查,来进行监控后端节点的状态。
  • haproxy只是httpd协议的反向代理,不提供缓存加速功能。但是反向代理功能强大,额外支持四层负载
  • HAProxy 相对其他负载均衡器主要优点:
    • HAProxy 是支持虚拟主机,通过 frontend 指令来实现
    • 能够补充 Nginx 的一些缺点,比如 Session 的保持,Cookie 引导等工作(请求引导到同一台服务器)
    • 支持 url 检测,后端的服务器出问题的检测会有很好的帮助
    • 跟 LVS 一样,本身仅仅就只是一款负载均衡软件;单纯从效率上来讲 HAProxy 更会比Nginx 有更出色的负载均衡速度,在并发处理上也是优于 Nginx。
    • HAProxy 可以对 Mysql 读进行负载均衡,对后端的 MySQL 节点进行检测和负载均衡,不过在后端的 MySQL slaves 数量超过 10 台时性能不如 LVS,所以更推荐 LVS+Keepalived。
    • 能对请求的 url 和 header 中的信息做匹配,有比 lvs 有更好的 7 层实现
      注:haproxy基于七层(应用层)负载,实现反向代理,必须监听在与之对应的应用程序端口上。和Nginx代理一样,基于多前端、交叉的方式、调度后端的调度方式
  • 安装方式
    • yum方式进行安装
    • 源代码编译安装
  • 相关配置文件
    • /etc/haproxy haproxy的相关配置路径
    • /etc/haproxy/haproxy.cfg 主配置文件
    • /usr/sbin/haproxy 主程序所在文件

HAProxy的安装

  • 实验环境

    • HAProxy server:Centos7 192.168.10.122 192.168.20.200
    • LAMP server1:Centos7 192.168.10.10
    • LAMP server2:Centos7 192.168.10.11
    • nginx server:Centos7 192.168.10.124
    • client:win10 192.168.20.250
  • 为haproxy服务器添加网卡并配置ip
    image-20191118152832420
    image-20191118152939887
    image-20191118153027777
    image-20191118153104139

  • 使用本地yum源进行安装
    image-20191118141736417

  • 修改配置,实现http服务的负载均衡
    image-20191118141940347
    image-20191118142014721
    image-20191118142036082
    image-20191118153556807

    global  #全局配置
    	# to have these messages end up in /var/log/haproxy.log you will
    	# need to:
    	#
    	# 1) configure syslog to accept network log events.  This is done
    	#    by adding the '-r' option to the SYSLOGD_OPTIONS in
    	#    /etc/sysconfig/syslog
    	#
    	# 2) configure local2 events to go to the /var/log/haproxy.log
    	#   file. A line like the following can be added to
    	#   /etc/sysconfig/syslog
    	#
    	#    local2.*                       /var/log/haproxy.log
    	#注释信息提示添加自定义日志的方法
    log         127.0.0.1 local2 #定义日志
    
    	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 <number>:指定启动的haproxy守护进程的个数,不加此选项默认一个
    	#ulimit -n:设定每个进程能打开的最大文件句柄数(相当于ulimit -n)
    #spread-check <0..50>:在haproxy后端有很多服务器场景,在精确的时间间隔后统一对众多服务器进行状态检查,会集中消耗大量带宽,这个选项可以在检查的时间间隔长度上增加或减少一定的随机时长
    
    #-------------------------------------------------------------------
    # common defaults that all the 'listen' and 'backend' sections will
    # use if not designated in their block
    #-------------------------------------------------------------------
    defaults #默认配置
    	mode                    http #指定运行模式为应用层http代理,也可以为tcp四层代理、health健康状态监测,与后台服务保持一致
    	log                     global #日志配置应用到全局
    	option                  httplog #
    	option                  dontlognull #不记录为空的访问请求
    	option http-server-close #请求结束主动关闭连接
    	option forwardfor       except 127.0.0.0/8 #除本地访问请求其余请求记录真实访问地址
    	option                  redispatch 当绑定cookie的请求对应的真实服务器出现故障,强制将请求重定向至状态正常的RS进行响应
    	retries                 3 #服务连接失败重试次数
    	timeout http-request    10s #http请求超时时长
    	timeout queue           1m #请求在队列中的超时时长
    	timeout connect         10s #连接超时时长
    	timeout client          1m #客户端超时时长
    	timeout server          1m #服务端超时时长
    	timeout http-keep-alive 10s #保持连接超时时长
    	timeout check           10s #检查超时时长
    	maxconn                 3000 #单个进程最大连接数
    #-------------------------------------------------------------------
    # main frontend which proxys to the backends
    #-------------------------------------------------------------------
    frontend  main 192.168.20.200:80 #监听地址和端口,*表示所有
    #    acl url_static       path_beg       -i /static /images /javascript /stylesheets
    #    acl url_static       path_end       -i .jpg .gif .png .css .js
    
    #    use_backend static          if url_static
    #use_backend 条件式后端调用    
    	default_backend             webserver #定义名为webserver的前端,与后面backend对应
    #bind 绑定监听的ip和端口
    #-------------------------------------------------------------------
    # static backend for serving up images, stylesheets and such
    #-------------------------------------------------------------------
    #backend static
    #    balance     roundrobin
    #    server      static 127.0.0.1:4331 check
    
    #-------------------------------------------------------------------
    # round robin balancing between the various backends
    #-------------------------------------------------------------------
    backend webserver #使用定义的前端进行配置
    	balance     roundrobin #指定负载均衡算法roundrobin 轮转
    	server  web1 192.168.10.10:80 check #定义后端真实服务器 RS
    	server  web2 192.168.10.10:80 check
    server  web3 192.168.10.100:80 backup #backup为备份服务器
    
    #server常用参数    
    	#check 启用健康状态检查
    		#inter<delay>  指定检查时间间隔(ms)
    		#fall up切换至down状态需要确认的次数
    		#rise down切换至up状态需要确认的次数
    	#backup 指定当前server为备份服务器
    	#cookie 为server设定cookie的值以实现会话绑定、持久连接
    	#maxconn:此server接受的并发连接的最大数量
         #maxqueue:请求队列的最大长度
         #observer:根据流量判断后端server的健康状态
         #weight:权重,默认为1,最大值256,0表示不参与负载均衡
    	#redir <prefix>:启用重定向功能,将发往此服务器的GET和HEAD请求以302状态码响应,需要注意prefix后不能使用/和相对地址,以免造成语法错误和循环
    	
    #cookie格式:cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ] [ postonly ] [ preserve ] [ httponly ] [ secure ] [ domain <domain> ]* [ maxidle <idle> ] [ maxlife <life> ]
    	#insert命令,表示在将响应报文交给客户端之前,先插入一个属性名为"name"的cookie
    	#使用rewrite模式时,haproxy将重写cookie的值为后端服务器的标识符。
    	#使用prefix的时候,cookie指令设置的cookie名必须和后端设置的cookie一样
    
    #调度算法:
    	#roundrobin:加权动态轮询,支持权重的运行时调整,支持慢启动;每个后端中最多支持4095个
    	#static-rr:加权静态轮询,不支持权重的运行时调整及慢启动;后端主机数量无上限
    	#leastconn:加权最小连接,动态算法,最少连接的后端服务器优先分配接收新连接,相同连接时轮询,适用于长连接场景,例如 MySQL、LDAP等,不适合http
    	#first:根据服务器在列表中的位置,自上而下进行调度;前面服务器的连接数达到上限,新请求才会分配给下一台服务
    	#source:源地址hash(默认为静态算法可使用hash-type指定为动态算法)
    		#hash-type <method> <function> <modifier> #指定hash类型
    			#method:
    				#map-based:除权取余法,哈希数据结构是静态数组(不支持权重动态调整)
    				#consistent:一致性哈希,动态hash
    			#<function> : 哈希函数
    				#如sdbm、djb2、wt6
    	#uri:对URI的左半部分或整个uri做hash计算,并除以服务器总权重取模,以后派发至某挑出的服务器,适用于后端缓存服务器,将访问同一个URI的请求指定访问到同一台服务器,支持hash-type
    	#url_param:根据url中指定的参数值进行调度,把值做hash计算支持hash-type
    	#hdr(<name>):根据请求报文中的header进行调度,包括(user_agent,referer,hostname)支持hash-type
    
  • 配置两台LAMP服务器
    过程参考LAMP环境搭建详细流程

  • 修改测试页
    image-20191118152303189
    image-20191118152314870
    image-20191118152244809
    image-20191118152231965

  • 启动服务
    image-20191118152423801
    image-20191118152441700
    image-20191118151630179

  • 测试(使用浏览器访问会因为缓存与长连接导致无法看到轮询效果)
    image-20191118153702836

自定义日志

  • 修改haproxy主配置文件如下
    image-20191118151052192
    image-20191118151033695
  • 修改日志配置文件
    image-20191118151132107
    image-20191118151536718
  • 重启服务
    image-20191118153748489
  • 访问后查看指定的日志文件是否进行日志收集
    image-20191118153959662

启用状态监控

  • 修改haproxy配置文件
    image-20191118154222811
    image-20191118154636789

    listen status #监听配置
    	bind *:1080 #绑定网卡及端口
    	stats enable #开启监听
    	stats hide-version #隐藏版本号
    	stats uri /haproxyadmin?stats #指定访问监听页面的路径
    	stats realm Haproxy\ Statistics #定义新的登录账号密码的提示页面
    	stats auth admin:12345 #账号认证登录,并指定账号密码
    	stats admin if TRUE #认证成功后拥有管理员权限(开启时要注释stats scope选项)
    #注:需要stats enable开启状态监控,该参数可以在default/listen/backend中,
    #开启后下面参数拥有的默认值:
    	#stats uri : /haproxy?stats 
    	#stats realm : "HAProxy Statistics"
    	#stats auth : no authentication
    	#stats scope : no restriction
    

- 重启服务
	![image-20191118155123526](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214023736-706153077.png)
- 访问测试
	![image-20191118155328409](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214023506-230408893.png)
	![image-20191118155352144](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214023141-1238614449.png)

### ACL访问控制配置

- 修改haproxy配置文件如下
	![image-20191118162010931](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214022783-1513722340.png)
	![image-20191118210120991](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214022550-1603974729.png)

	```shell
	frontend  main 192.168.20.200:80
		http-request deny
		acl nagios src 192.168.20.250 #acl定义匹配条件,名称为nagios,匹配来自192.168.20.250的请求
		acl local_net src 192.168.10.0/24 #local_net匹配规则定义匹配来自192.168.10.0/24网段的请求
		http-request deny if nagios #当nagios匹配条件为真则拒绝该请求
		http-request allow if local_net #允许local_net中定义的请求
		http-request deny #默认拒绝访问
	#注:acl访问控制还可以对tcp进行进行控制tcp-request <alllow | deny>
	#参数格式:acl <aclname> <criterion> [flag] [operator] <value> 
		#aclname 匹配规则的名称,区分大小写,只能包括大小写字母、数字,连接线、下划线、点号、冒号
		#criterion:测试标准,表示检查那些数据或内容,常用: 
		#src:ip 源IP
		#src_port:integer 源端口
		#dst:ip 目标IP
		#dst_port:integer 目标端口
		#flag:acl标志位,定义控制条件,例如是否区分字符大小写等,可选参数如下:
		#    -i 忽略字符大小写
		#    -m 启用特定的匹配方式,一般不用
		#    -n 禁止DNS反向解析
		#    -u 不允许aclname重复,默认是可以重名的,当两个acl的名称相同时,运算为或机制。
		#operator:判断匹配条件,与<criterion>相比较的操作
		#    匹配整数值:eq,ge,gt,le,lt
		#value:测试的数据值,访问控制的具体内容或值
		#	   boolean:布尔值
		#    integer or integer range:整数或整数范围
		#    IP address/network:网络地址
		#    string(exact, substring, suffix, prefix, subdir, domain):字符串
		#    regular expression:正则表达式
	#常用的criterion
		#be_sess_rate:用于测试指定的backend会话创建的速率(即每秒创建的会话数)
			#例如:
			#backend dynamic
			#mode http
			#acl being_scanned be_sess_rate gt 100
			#redirect location /error_page/denied.html if being_scanned
		#fe_sess_rate:用于测试指定的frontend会话创建的速率(即每秒创建的会话数)
			#例如
			#frontend mail
			#bind *:25
			#mode tcp
			#maxconn 5000
			#acl too_fast fe_sess_rate gt 100
			#tcp-request inspect-delay 500ms  延迟500毫秒
			#tcp-request content accept if ! too_fast
			#tcp-request content accept if WAIT_END
		#hdr: 根据请求报文中的header进行调度,包括(user_agent,referer,hostname)
		#method:根据请求的方法进行匹配
		#path_beg:根据请求URL路径的开头来匹配 
			#例如:acl  url_static path_beg -i /static、/images、/javascript、/stylesheets   location
		#path_end:根据URL路径请求的结尾    
			#例如:acl  url_static path_beg -i .jpg  .gif  .png  .css  .js
	```

- 重启服务
	![image-20191118164639523](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214022276-1860676059.png)	

- 访问测试
	![image-20191118191319251](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214022006-540343784.png)
	192.168.10.1主机访问时被拒绝

### HAProxy动静分离

- 添加一台nginx服务器作为静态网页处理服务器(参考[Nginx初识](https://www.cnblogs.com/lastyear/p/11838912.html))

- 添加测试页
	![image-20191118193332401](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214021738-2145323517.png)

- 修改两台LAMP的测试主页为动态php页面
	![image-20191118193527871](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214021478-1305253255.png)
	![image-20191118193551022](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214021242-454056582.png)
	![image-20191118193618089](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214021019-396974319.png)
	![image-20191118193649630](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214020786-1527702028.png)
	![image-20191118194012736](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214020572-228707000.png)
	![image-20191118200920849](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214020319-1141613897.png)
	![image-20191118194227830](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214020063-227301550.png)
	![image-20191118200950277](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214019833-2005762753.png)

- 重启服务
	![image-20191118193847671](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214019593-392908101.png)
	![image-20191118193941758](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214019338-873424875.png)
	![image-20191118193950411](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214019100-826050930.png)

- 修改haproxy主配置文件,将nginx服务器添加到负载均衡中
	![image-20191118195227413](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214018865-1824842634.png)
	![image-20191118195215479](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214018628-456292205.png)

- 重启服务
	![image-20191118194956433](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214018361-1541372014.png)

- 访问测试(使用浏览器访问会因为缓存与长连接导致无法看到轮询效果)
	![image-20191118201038508](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214018120-34317000.png)
	![image-20191118195729058](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214017893-697338292.png)
	![image-20191118201026419](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214017648-437218004.png)

- 修改配置,启用动静分离
	![image-20191118195923021](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214017410-1352170034.png)
	![image-20191118200728164](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214017135-490400372.png)

	```shell
		frontend  main 192.168.20.200:80    
			acl url_static       path_beg       -i /img /static /images 
			#定义匹配规则,匹配以/img、/static、/images开始的请求命名为url_static
			acl url_static       path_end       -i .jpg .gif .png .css .js .html
			#匹配.jpg、.gif、.png、.css、.js、.html结尾的请求,命名为url_static 
			acl url_dynamic      path_end       -i .php 
			#匹配以.php结尾的请求命名为url_dynamic
	
			use_backend static          if url_static
			#若url_static匹配条件为真则由static中的服务器进行响应
			use_backend webserver       if url_dynamic
			#若url_dynamic匹配条件为真则由webserver中的服务器进行响应
			default_backend             webserver
			#默认使用webserver中的后台服务器进行响应
		backend static #静态web处理服务器
			balance     roundrobin
			server      static1 192.168.10.124:80 check
	
		backend webserver #动态web处理服务器
			balance     roundrobin
			server  web1 192.168.10.10:80 check
			server  web2 192.168.10.11:80 check
			server  web3 192.168.10.100:80 backup
	```

- 重启服务
	![image-20191118200537547](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214016842-1224334603.png)

- 测试动静分离
	![image-20191118201104217](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214016599-1292268295.png)

### 收集客户真实地址

- 修改haproxy配置文件如下
	![image-20191118201358983](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214016309-852207420.png)
	![image-20191118201347506](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214016047-1187367364.png)
- 重启服务
	![image-20191118201418652](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214015773-1504003277.png)
- 修改LAMP服务器中httpd服务日志格式
	![image-20191118201647701](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214015528-1310382246.png)
	![image-20191118201908361](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214015272-660046161.png)
	另一台LAMP也做相同配置
- 重启服务
	![image-20191118202050467](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214014943-2038729262.png)
	![image-20191118202059550](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214014709-1204204059.png)
- 修改nginx日志配置(yum安装无需修改)
	![image-20191118203622318](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214014474-245549628.png)
	![image-20191118203635599](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214014244-1809133197.png)
	![image-20191118203701279](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214013995-936359278.png)
	![image-20191118203835022](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214013756-46751987.png)
	![image-20191118203908073](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118214013513-1819065160.png)
- 重启服务
	![image-20191118203934290](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118213954689-549147301.png)
- 访问几次后查看日志文件可以看到真实ip已经被记录
	httpd服务的日志真实客户ip地址在最前面
	![image-20191118202939955](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118213954409-460571378.png)
	nginx服务的日志中真实客户地址在后面
	![image-20191118203542118](https://img2018.cnblogs.com/blog/1241092/201911/1241092-20191118213954050-1989365528.png)
posted @ 2019-11-18 21:45  MirL  阅读(643)  评论(0编辑  收藏  举报