前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >HAProxy负载均衡器用法详解

HAProxy负载均衡器用法详解

作者头像
小土豆Yuki
发布2020-06-15 17:09:25
13.1K0
发布2020-06-15 17:09:25
举报
文章被收录于专栏:洁癖是一只狗洁癖是一只狗

上一篇我们介绍了四层的负载均衡器LVS, 这次我们我们介绍另外一种负载均衡器HAProxy。

一、HAProxy简介

HAProxy是一种高效、可靠、免费的高可用及负载均衡解决方案,非常适合于高负载站点的七层数据请求。因为HAProxy实现了一种事件驱动、单一进程模型,此模型支持非常大的并发连接数。客户端通过HAProxy代理服务器获得站点页面,而代理服务器收到客户请求后根据负载均衡的规则将请求数据转发给后端真实服务器。HAProxy还支持Session的保持和Cookie的引导。

同一客户端访问服务器,HAProxy保持会话的三种方案:

1、 HAProxy将客户端ip进行Hash计算并保存,由此确保相同IP访问时被转发到同一真实服务器上。( 配置:balance source)

2、 HAProxy依靠真实服务器发送给客户端的cookie信息进行会话保持。

3、 HAProxy保存真实服务器的session及服务器标识,实现会话保持功能。

二、HAProxy工作原理

HAProxy有前端(frontend)和后端(backend),前端和后端都可以有多个。也可以只有一个listen块来同时实现前端和后端。这里主要讲一下frontend和backend工作模式。 前端(frontend)区域可以根据HTTP请求的header信息来定义一些规则,然后将符合某规则的请求转发到相应后端(backend)进行处理。因此HAProxy可以实现动静分离(动静分离简单来说就是指将静态请求转发到对应的静态资源服务器,将动态请求转发到动态资源服务器),我们上篇说过的LVS 就没有此功能。

三、HAProxy详解配置文件

主程序:/usr/sbin/haproxy 配置文件:/etc/haproxy/haproxy.cfg Unit file:/usr/lib/systemd/system/haproxy.service

配置文件/etc/haproxy/haproxy.cfg主要由两部分组成:global 和 proxies 配置段。

下面我们详细说明这两个配置段都有哪些内容和其对应的含义。

global:全局配置段 包含的内容如下:

进程及安全配置相关的参数 性能调整相关参数 Debug参数

#以下为默认全局配置端信息:

代码语言:javascript
复制
global    
    log         127.0.0.1 local2  #全局日志配置,日志将被记录在本机的local2设施中。chroot      /var/lib/haproxy  #chroot运行路径,增加安全性    
    pidfile     /var/run/haproxy.pid  #HAProxy的pid存放路径    
    maxconn     4000   #默认的最大连接数    
    user        haproxy  #运行haproxy的用户    
    group       haproxy  #运行haproxy用户所属的组    
    daemon   #以守护进程的方式工作与后台    
    # turn on stats unix socket    
    stats socket /var/lib/haproxy/stats   #基于本地的文件传输

proxies:代理配置段 包含的内容如下:

defaults:为frontend, backend, listen提供默认配置
fronted:前端,相当于nginx, server {}

backend:后端,相当于nginx, upstream {} listen:同时拥有前端和后端,适用于一对一环境

#以下为默认的代理配置段的信息

代码语言:javascript
复制
defaults
    mode                    http  #默认的模式mode { tcp|http|health },tcp是4层,http是7层,health只会返回OK
    log                     global  #应用全局的日志配置
    option                  httplog   # 启用日志记录HTTP请求,默认haproxy日志记录是不记录HTTP请求日志
    option                  dontlognull   # 启用该项,日志中将不会记录空连接。所谓空连接就是在上游的负载均衡器或者监控系统为了探测该服务是否存活可用时,需要定期的连接或者获取某一固定的组件或页面,或者探测扫描端口是否在监听或开放等动作被称为空连接;官方文档中标注,如果该服务上游没有其他的负载均衡器的话,建议不要使用该参数,因为互联网上的恶意扫描或其他动作就不会被记录下来
    option http-server-close   #每次请求完毕后主动关闭http通道
    option forwardfor       except 127.0.0.0/8  #如果服务器上的应用程序想记录发起请求的客户端的IP地址,需要在HAProxy上配置此选项, 这样 HAProxy会把客户端的IP信息发送给服务器,在HTTP请求中添加"X-Forwarded-For"字段。启用X-Forwarded-For,在requests头部插入客户端IP发送给后端的server,使后端server获取到客户端的真实IP。
    option                  redispatch  #当使用了cookie时,haproxy将会将其请求的后端服务器的serverID插入到cookie中,以保证会话的SESSION持久性;而此时,如果后端的服务器宕掉了,但是客户端的cookie是不会刷新的,如果设置此参数,将会将客户的请求强制定向到另外一个后端server上,以保证服务的正常。
    retries                 3  # 定义连接后端服务器的失败重连次数,连接失败次数超过此值后将会将对应后端服务器标记为不可用
    timeout http-request    10s  #http请求超时时间
    timeout queue           1m  #一个请求在队列里的超时时间
    timeout connect         10s  #连接超时
    timeout client          1m  #客户端超时
    timeout server          1m  #服务器端超时
    timeout http-keep-alive 10s  #设置http-keep-alive的超时时间
    timeout check           10s  #检测超时
    maxconn                 3000  #每个进程可用的最大连接数

frontend  main *:5000  #监听地址为5000
    #定义了动静态分离
    #请求URL是以/static, /images, /javascript或 /stylesheets 开头的都将请求转到backend static。也就是将请求转到静态服务器。
    acl url_static       path_beg       -i /static /images /javascript /stylesheets
    #请求URL是以.jpg, .gif, .png, .css, .js结尾的请求也都转到backend static。也就是将请求转到静态服务器。
    acl url_static       path_end       -i .jpg .gif .png .css .js

    use_backend static          if url_static 
    #如果不满足上述动态请求条件,则会将该请求转向default_backend, 名为app.
    default_backend             app   

#---------------------------------------------------------------------
# static backend for serving up images, stylesheets and such
#---------------------------------------------------------------------
#backend static(用于转发静态请求)具体定义如下:算法为轮询,将静态请求转到静态web服务器为127.0.0.1的4331端口。
backend static
    balance     roundrobin  ##负载均衡算法
    server      static 127.0.0.1:4331 check   ##定义的后端

#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
#backend app (用于转发动态请求)具体定义如下:算法为轮询,将动态请求转到以下四台服务器的任意一台
backend app
    balance     roundrobin   ##负载均衡算法
    server  app1 127.0.0.1:5001 check   ##定义的多个后端
    server  app2 127.0.0.1:5002 check   ##定义的多个后端
    server  app3 127.0.0.1:5003 check   ##定义的多个后端
    server  app4 127.0.0.1:5004 check   ##定义的多个后端

四、HAProxy 常用功能介绍及实验演练 HAProxy server: 192.168.1.102 Web server1: 192.168.1.105 Web server1: 192.168.1.106

1. 搭建一台HAProxy 服务器和 两台Apache服务器, 实现负载均衡。

准备工作:

1)在HAProxy server 上面安装haproxy:

代码语言:javascript
复制
yum -y install haproxy

2)在Web server1 和 Web server2 上面先安装httpd:

代码语言:javascript
复制
yum -y install httpd

3)配置网页:

Web server1 的默认网页内容为Web1. Web server2 的默认网页内容为Web2.

代码语言:javascript
复制
[root@workernode1 html]# pwd
/var/www/html
[root@workernode1 html]# cat index.html
Web1
[root@worknode2 html]# pwd
/var/www/html
[root@worknode2 html]# cat index.html
Web2
[root@worknode2 html]#

4)在Web server1 和 Web server2 上面启动httpd服务:

代码语言:javascript
复制
systemctl start httpd

5)使用curl http://localhost:80 访问页面查看访问内容分别为Web1 和 Web2:

代码语言:javascript
复制
[root@workernode1 html]# curl http://localhost:80
Web1
[root@worknode2 html]# curl http://localhost:80
Web2

‍下面我们开始真正的配置:

1)修改haproxy的主配置文件 vim /etc/haproxy/haproxy.cfg

代码语言:javascript
复制
[root@manager haproxy]# vim /etc/haproxy/haproxy.cfg
#修改内容如下:
frontend  main *:80
    default_backend             webservers

backend webservers
    balance     roundrobin
    server  app1 192.168.1.105:80 check
    server  app2 192.168.1.106:80 check

[root@manager haproxy]

2)重启haproxy服务,查看haproxy监听的端口:

代码语言:javascript
复制
[root@manager ~]# systemctl restart haproxy
[root@manager ~]# systemctl status haproxy
● haproxy.service - HAProxy Load Balancer
   Loaded: loaded (/usr/lib/systemd/system/haproxy.service; enabled; vendor preset: disabled)
   Active: active (running) since Sun 2020-05-24 05:18:38 EDT; 4s ago
  Process: 103437 ExecReload=/bin/kill -USR2 $MAINPID (code=exited, status=0/SUCCESS)
 Main PID: 111840 (haproxy-systemd)
    Tasks: 3
   CGroup: /system.slice/haproxy.service
           ├─111840 /usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
           ├─111841 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
           └─111842 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds

May 24 05:18:38 manager systemd[1]: Started HAProxy Load Balancer.
May 24 05:18:38 manager haproxy-systemd-wrapper[111840]: haproxy-systemd-wrapper: executing /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
[root@manager ~]# netstat -antup | grep -i haproxy
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      111842/haproxy
tcp        0      0 0.0.0.0:90              0.0.0.0:*               LISTEN      111842/haproxy
udp        0      0 0.0.0.0:33435           0.0.0.0:*                           111841/haproxy
[root@manager ~]#

3)访问下服务器地址 如下图所示:访问HAProxy server的80端口, 在Web1 和 Web2 跳跃

也可以写一个循环来测试:

while [ TURE ]; do curl http://192.168.1.102:80; sleep 2; done

2. 配置haproxy的日志功能

代码语言:javascript
复制
#1.配置haproxy的日志功能
vim /etc/resyslog.conf
加入下面的几个参数,启用udp和tcp模块,加入haproxy.log的路径

[root@manager log]# cat /etc/rsyslog.conf | tail -n 5
$ModLoad imtcp
$InputTCPServerRun 514

local2.*      /var/log/haproxy.log
[root@manager log]#

#2.重启日志服务
[root@manager log]# systemctl restart rsyslog

#3.重新载入haproxy
[root@manager log]# systemctl reload haproxy

#4.查看日志的输出
[root@manager log]# tail -f /var/log/haproxy.log
May 23 04:00:27 localhost haproxy[22496]: Proxy main started.
May 23 04:00:27 localhost haproxy[22496]: Proxy webservers started.
May 23 04:00:27 localhost haproxy[22136]: Stopping frontend main in 0 ms.
May 23 04:00:27 localhost haproxy[22136]: Stopping backend webservers in 0 ms.
May 23 04:00:27 localhost haproxy[22136]: Proxy main stopped (FE: 4 conns, BE: 0 conns).
May 23 04:00:27 localhost haproxy[22136]: Proxy webservers stopped (FE: 0 conns, BE: 4 conns).
May 23 04:05:40 localhost haproxy[22497]: 127.0.0.1:43980 [23/May/2020:04:05:40.640] main webservers/app1 0/0/2/3/5 200 263 - - ---- 1/1/0/0/0 0/0 "GET / HTTP/1.1"
May 23 04:05:41 localhost haproxy[22497]: 127.0.0.1:43988 [23/May/2020:04:05:41.398] main webservers/app2 0/0/0/3/3 200 263 - - ---- 1/1/0/1/0 0/0 "GET / HTTP/1.1"
May 23 04:05:42 localhost haproxy[22497]: 127.0.0.1:43996 [23/May/2020:04:05:42.112] main webservers/app1 0/0/0/6/6 200 263 - - ---- 1/1/0/0/0 0/0 "GET / HTTP/1.1"

日志输出结果如下图所示:

1)更改配置文件:

代码语言:javascript
复制
vim /etc/haproxy/haproxy.cfg

frontend websrv
    bind *:80
    default_backend     webservers

2)重新载入haproxy:

代码语言:javascript
复制
systemctl reload haproxy

3)查看监听的端口:

代码语言:javascript
复制
[root@manager ~]# netstat -antup | grep -i 80
tcp        0      0 0.0.0.0:80              0.0.0.0:*     

4)查看测试页

(也就是我们在简介里面说的实现会话保持的第一种方法:基于source算法,确保相同IP访问时被转发到同一真实服务器上。)

1)把balance调度算法改为source:

vim /etc/haproxy/haproxy.cfg

2)重新载入 haproxy:

3)查看测试页面:可以看到来自于同一IP的请求,始终定向至同一台:

5. uri的机制,对同一个uri的请求,始终定义至同一个server上 (配置: balance uri)

1)首先我们现在Web server1 和Web server2 上面多定义几个测试页面:

2)在haproxy server 上面修改调度算法为uri:

3)重新加载haproxy服务:

4)访问测试页:

在Firefox 浏览器访问test1.html 指向的是web2节点

我们换一个浏览器,用IE访问test1.html 也指向的是web2节点

在Firefox 浏览器访问test2.html 指向的是web1节点

我们换一个浏览器,用IE访问test2.html 也指向的是web1节点

由此可见,uri的机制,对同一个uri的请求,始终定义至同一个server上。也就是上述实现的无论从哪个客户端访问test1.html, 都指向的是web2上面的test1.html;无论从哪个客户端访问test2.html, 都指向的是web1上面的test2.html。

6. 设置session会话绑定

也就是我们在简介中提到的第二种设置会话保持的方法,HAProxy依靠真实服务器发送给客户端的cookie信息(也就是浏览器端的缓存信息中会包含服务器的node信息, 如web1 或者 是web2, 从而该浏览器下次访问时还会访问之前访问过的web服务器。)进行会话保持。

1)编辑配置文件:

vim /etc/haproxy/haproxy.cfg

2)重新加载haproxy

3)在浏览器中可以看到cookie的方式:

node=node1, 也就是web1

7. 配置服务状态查看

1)编辑配置文件:

vim /etc/haproxy/haproxy.cfg

2)重新加载haproxy

3)访问状态的链接http://192.168.1.102/haproxy?stats:出现如下图所示的页面:

可以通过该页面查看到forntend 和 backend 的信息和当前状态等。

8. 启用haproxy管理接口 1)编辑配置文件haproxy.cfg 加入下面所示的参数 stats admin if TRUE

2)重新加载haproxy

3)查看下面界面,发现多了管理功能:

功能如下:可以通过此管理功能,管理几个节点

9. 定义haproxy的动静分离 1)编辑配置文件haproxy.cfg,加入下面的代码

代码语言:javascript
复制
frontend  websrvs    
  bind  *:80    
  acl url_static       path_beg       -i /static /images /javascript /stylesheets    
  acl url_static       path_end       -i .jpg .gif .png .css .js .html    
  acl host_static     hdr_beg(host)  -i img. video. download. ftp. imgs. videos.    
  acl url_php         path_end       -i .php    
  use_backend static          if url_static or host_static    
  use_backend dynamic     if url_php    
  default_backend             dynamic

backend static    
    balance    roundrobin    
    server      node1 192.168.20.11:80  check maxconn 30000

backend dynamic    
    balance    roundrobin    
    server      node2 192.168.20.12:80  check maxconn 1000

2)通过acl 访问规则来实现的:

3)修改完配置文件后重新载入配置文件

演示效果为: 访问静态页面都落到node1上

访问动态页面都落到node2上

现在我们来想一个问题, 如果后端的web 服务器挂了怎么办?

其实HAProxy支持后端web服务器状态检查,当其代理的后端服务器出现故障时,Haproxy会自动将该故障服务器摘除,当故障的服务器恢复后,Haproxy还会自动的将该服务器自动加入进来提供服务。下面我们来详细介绍该功能。

五、HAProxy后端web服务器状态检测

HAProxy有三种状态检测方式: 1).基于四层的传输端口做状态监测 2).基于指定的uri做状态监测 3).基于指定的URI的resquest请求头部内容做状态监测

1. 基于四层的传输端口做状态监测

通过监听端口进行健康检测。这种检测方式,haproxy只会去检查后端server的端口,并不能保证服务的真正可用。有时候服务端口和进程都是存在的,但是就是不正常提供服务,尤其是Java程序很容易出现类似的案例,这个时候如果我们使用基于端口的监听方式明显就不太合适了。

示例: 1)修改配置文件 vim /etc/haproxy/haproxy.cfg

2)加载haproxy:

3)先查看状态页面http://192.168.1.102:90/haproxy?stats,目前web1 web2 都正常:

4)测试: 将web1的nginx服务停止

5)再次查看状态页面http://192.168.1.102:90/haproxy?stats,发现web1 down 了。

6)通过访问HAProxy 的80 端口,发现一直将请求转到到web server2。

2. 基于指定的uri做状态监测

检测方式,是用GET后端server的的web页面,基本上可以代表后端服务的可用性。是模拟客户端去访问服务端,如果响应码是正常的说明服务端处于正常工作状态,从而避免了基于端口监控的弊端。

示例:

1)修改配置文件

vim /etc/haproxy/haproxy.cfg

2)加载haproxy:

3)先查看状态页面http://192.168.1.102:90/haproxy?stats,目前web1 web2 都正常:

4)测试: 将web1的nginx服务停止

5)再次查看状态页面http://192.168.1.102:90/haproxy?stats,发现web1 down 了。

3. 基于指定的URI的resquest请求头部内容做状态监测

和上面所说的"基于指定URI做状态监测"原理一样,只不过它做了一个优化操作,就是不要消息体(body)部分,只返回给haproxy响应头部(head)信息即可,从而节省了后端web服务器的网络I/O。在生产环境中我们更推荐使用这种方法。

示例:

1)修改配置文件

vim /etc/haproxy/haproxy.cfg

2)加载haproxy:

3)先查看状态页面http://192.168.1.102:90/haproxy?stats,目前web1 web2 都正常:

4)测试:

我们不停服务,只是修改index.html的名字, 让HAProxy 找不到index.html网页:

5)我们看到当前的端口还是正在监听的.

6)再次查看状态页面http://192.168.1.102:90/haproxy?stats,发现web1 和 web2都down 了。

7)我们再将网页名字改回到index.html, 再次查看状态页面:

发现web1 和 web2 显示正常:

今天我们先介绍到这里。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-05-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 洁癖是一只狗 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • global:全局配置段 包含的内容如下:
  • defaults:为frontend, backend, listen提供默认配置
  • fronted:前端,相当于nginx, server {}
  • 1. 基于四层的传输端口做状态监测
相关产品与服务
负载均衡
负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档