haproxy安装与功能特性介绍

haproxy安装与功能特性介绍

安装

yum

[root@host1 ~]# yum install -y haproxy
[root@host1 ~]# rpm -qi haproxy
Name        : haproxy
Version     : 1.5.18
# yum直接安装即可,base仓库就有,版本较低,一般都需要编译安装需要的版本

# yum安装目录结构
[root@host1 ~]# rpm -ql haproxy
/etc/haproxy
/etc/haproxy/haproxy.cfg 
# 配置文件
/etc/logrotate.d/haproxy
# 日志轮替配置
/etc/sysconfig/haproxy
# 服务脚本的参数文件
/usr/bin/halog
/usr/bin/iprange
# 程序文件
/usr/lib/systemd/system/haproxy.service
# 服务脚本
/usr/sbin/haproxy
# 主程序
/usr/sbin/haproxy-systemd-wrapper
/usr/share/doc/haproxy-1.5.18
...
# doc和man等帮助文档
/var/lib/haproxy
# 数据目录

编译

1、下载源码包,解压,进入解压后目录
wget https://www.haproxy.org/download/1.7/src/haproxy-1.7.12.tar.gz
tar -xf haproxy-1.7.12.tar.gz
cd haproxy-1.7.12

2、安装编译工具、依赖包
[root@host2 haproxy-1.7.12]# yum install -y gcc gcc++ pcre pcre-devel


3、
2步走
编译:
	[root@host2 haproxy-1.7.12]# make TARGET=linux2628 USE_PCRE=1 ARCh=x86_64 prefix=/usr/local/haproxy
	需要指明硬件架构、os平台、安装目录、辅助功能如pcre、openssl、zlib等

安装:
	[root@host2 haproxy-1.7.12]# make install PREFIX=/usr/local/haproxy
	安装也需要再次指定目录,且prefix要大写,不然不会安装到对应的目录下
	

安装后目录

# 安装后目录结构:
[root@host2 haproxy-1.7.12]# ll /usr/local/haproxy/
total 0
drwxr-xr-x 3 root root 21 Sep 14 16:50 doc
drwxr-xr-x 2 root root 21 Sep 14 16:50 sbin
drwxr-xr-x 3 root root 17 Sep 14 16:50 share

# 不需要配置PATH和MANPATH,安装后即可找到haproxy的程序文件和man文件
# 程序文件,只有一个haproxy主程序

服务脚本、参数文件

​ 服务脚本,要修改2项:

  • 主程序路径
  • 主程序启动时,传入的参数,(不同版本不同)注意根据当前版本的主程序的命令参数然后调整
[root@host1 ~]# scp /usr/lib/systemd/system/haproxy.service 192.168.80.101:/usr/lib/systemd/system/
[root@host1 ~]# scp /etc/sysconfig/haproxy 192.168.80.101:/etc/sysconfig/

[root@host2 haproxy-1.7.12]# systemctl daemon-reload
[root@host2 haproxy-1.7.12]# systemctl status haproxy


# 从host1拷贝一份yum安装后的服务脚本,及其参数文件
# 对服务脚本进行修改,

[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target

[Service]
EnvironmentFile=/etc/sysconfig/haproxy
ExecStartPre=/usr/local/haproxy/sbin/haproxy -f /etc/haproxy/haproxy.cfg   -c -q
ExecStart=/usr/local/haproxy/sbin/haproxy -Ds -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
ExecReload=/bin/kill -USR2 $MAINPID
KillMode=mixed

[Install]
WantedBy=multi-user.target

配置文件

​ 配置文件,注意不同版本的语法兼容问题

[root@host2 haproxy-1.7.12]# mkdir /etc/haproxy
[root@host1 ~]# scp /etc/haproxy/haproxy.cfg 192.168.80.101:/etc/haproxy/
# 创建目录,从别的机器拷贝一份配置文件;
# 可以从examples目录下找,或者从yum安装的版本中复制一份配置文件并做修改,注意不同版本的配置文件兼容性问题;

# 如下:是编译安装1.7.12采用yum安装的1.5.18的配置文件的修改过程
# 创建了haproxy用户、修改了bind指令
# 再次语法检查,即通过
[root@host3 haproxy-1.7.12]# haproxy -c -f /etc/haproxy/haproxy.cfg 
[ALERT] 259/115328 (1567) : parsing [/etc/haproxy/haproxy.cfg:31] : cannot find user id for 'haproxy' (0:Success)
[ALERT] 259/115328 (1567) : parsing [/etc/haproxy/haproxy.cfg:32] : cannot find group id for 'haproxy' (0:Success)
[ALERT] 259/115328 (1567) : parsing [/etc/haproxy/haproxy.cfg:63] : 'frontend' cannot handle unexpected argument '*:5000'.
[ALERT] 259/115328 (1567) : parsing [/etc/haproxy/haproxy.cfg:63] : please use the 'bind' keyword for listening addresses.
[ALERT] 259/115328 (1567) : Error(s) found in configuration file : /etc/haproxy/haproxy.cfg
[ALERT] 259/115328 (1567) : Fatal errors found in configuration.

[root@host3 haproxy-1.7.12]# useradd haproxy
[root@host3 haproxy-1.7.12]# haproxy -c -f /etc/haproxy/haproxy.cfg 
[ALERT] 259/115346 (1573) : parsing [/etc/haproxy/haproxy.cfg:63] : 'frontend' cannot handle unexpected argument '*:5000'.

[ALERT] 259/115346 (1573) : parsing [/etc/haproxy/haproxy.cfg:63] : please use the 'bind' keyword for listening addresses.
[ALERT] 259/115346 (1573) : Error(s) found in configuration file : /etc/haproxy/haproxy.cfg
[ALERT] 259/115346 (1573) : Fatal errors found in configuration.
[root@host3 haproxy-1.7.12]# vim /etc/haproxy/haproxy.cfg 
[root@host3 haproxy-1.7.12]# haproxy -c -f /etc/haproxy/haproxy.cfg 
Configuration file is valid


# 启动时,报错,查看为目录不存在问题
# 创建/var/lib/haproxy目录后再启动即可
[root@host3 ~]# systemctl status haproxy
....
Sep 16 14:30:53 host3.b.com haproxy[1817]: [ALERT] 259/143053 (1817) : Starting frontend GLOBAL: cannot bind UNIX socket [/var/lib/haproxy/stats]
[root@host3 ~]# mkdir /var/lib/haproxy

haproxy主程序

[root@host2 haproxy-1.7.12]# haproxy -h
HA-Proxy version 1.7.12 2019/10/25
Copyright 2000-2019 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)
        -V enters verbose mode (disables quiet mode)
        -D goes daemon ; -C changes to <dir> before loading files.
        -q quiet mode : don't display messages
        -c check mode : only check config files and exit
        -n sets the maximum total # of connections (2000)
        -m limits the usable amount of memory (in MB)
        -N sets the default, per-proxy maximum # of connections (2000)
        -L set local peer name (default to hostname)
        -p writes pids of all children to this file
        -de disables epoll() usage even when available
        -dp disables poll() usage even when available
        -dS disables splice usage (broken on old kernels)
        -dR disables SO_REUSEPORT usage
        -dr ignores server address resolution failures
        -dV disables SSL verify on servers side
        -sf/-st [pid ]* finishes/terminates old pids.

haproxy -D -f /etc/haproxy/haproxy.cfg 
# 命令行启动haproxy,

注意点

  • haproxy不同版本时,配置文件的语法兼容问题
  • haproxy不同版本时,主程序可接收参数不同,导致的服务脚本的参数文件要随之修改传入的启动参数;
  • 编译安装,修改服务脚本时,主程序路径问题

特性介绍

​ haproxy一款开源的负载均衡软件,支持4层,7层的负载,支持会话保持,ssl加密,官网:http://www.haproxy.org/,类似于nginx,也有haproxy的商业版,具有一些高级特性

官方文档

https://cbonte.github.io/haproxy-dconv/

​ haproxy每个版本都有三类文档:starter guide、configuration manual、management guide,不同版本的文档大体相同,

https://cbonte.github.io/haproxy-dconv/1.7/configuration.html

​ 以1.7版本的配置文档为例,大致包含:http事务介绍,haproxy基础配置,全局参数,proxy代理参数(包含各类指令的语法汇总),acl配置,日志配置等;

特性官方介绍

https://cbonte.github.io/haproxy-dconv/1.7/intro.html#3

​ 在stater guide中介绍了haproxy的各类特性,基础特性、高级特性、

  • ssl
  • 监控
  • 会话保持
  • acl
  • 内置状态信息
  • ...

特性概述

连接保持、连接关闭

​ http的事务模型,http协议是事务驱动型,每个request有且仅有个response,

http-close模型:

​ 每个请求都要建立一次tcp连接,响应后随机关闭tcp连接,**一个tcp连接只能用于一次http请求和响应,这样会频繁的建立和释放tcp连接,消耗资源,**但仍有适用场景,后端是应用服务器的情况下,

http-keep-alive

​ 一个tcp连接用于多于http请求和响应的传输,server端通过响应头部的content-length字段告知客户端,还有多少数据没发完,直到数据发完后,才关闭连接,避免了频繁建立释放tcp连接的资源消耗,适用后端是静态web服务器的情况

haproxy支持的http连接模式

  • keep alive:适用后端是静态服务器
  • server close:处理完一对请求和响应后,即关闭和后端服务器的tcp连接,适用后端是动态服务器
  • tunnel:仅分析第一个请求和响应,后续内容不分析直接转发
  • passive close
  • forced close:传输完一对请求和响应后,关闭客户端和服务器的tcp连接

会话保持

​ 作为反向代理软件,必须具备会话保持的功能,在选择某后端节点需要被调度时,不仅仅要考虑既定调度算法,也要考虑,请求与请求之间的相关性,即会话保持,举例:购物网站,添加购物车,刷新页面后,购物车信息不会丢失,是因为应用服务器将购物车等信息存储在了内存中,叫做上下文session,每次请求过来时都会找到对应的上下文,继续后续处理逻辑

​ 静态web服务,是无状态的,每台服务器提供的服务都是完全一样,因此调度到不同的服务器上对结果并不会有什么影响;

​ 动态应用服务,是有状态的,其内存中会保存了客户端的会话信息,因此有关联的请求需要被调度后同一台动态应用服务器上,才能找到之前的会话信息,因此haproxy等代理软件在调度时,就必须考虑请求之间的相关性,将有关系的请求调度到同一台服务器上,

​ 会话共享:如果将多个应用服务器的会话,抽离出来防止一台会话服务器上,如redis,memcache,应用服务器本身不需要保存会话信息,需要会话信息时,直接到会话服务器上查找,此时应用服务器实现了状态的剥离,**成为了无状态应用,此时haproxy调度时,就不需要考虑请求之间的相关性,直接根据调度算法调度即可,**会话服务器本身需要高可用!

haproxy会话保持方式

​ 共有3种:

  • 源ip的hash:
  • 基于cookie
  • 基于stick table
  • 会话共享服务器(此时haproxy不需要实现会话保持了)

1、源ip的hash

​ 同一个ip发来的请求会根据hash取模或一致性hash调度到同一台后端服务器,hash取模时,后端节点增减会导致算法结果的大幅度变化,造成大量请求的重新分配节点,所以一般采用一致性hash可以减少变化的节点数,

2、基于cookie

2类cookie,1、应用服务器产生的,用于程序逻辑的cookie,2、反代软件产生的,用于调度的cookie

​ 在snat上网的情况下,一个源ip可能对应许多个私网ip的源ip,导致分布的不均衡,因为区分每个私网源ip的方法是采用cookie,哪怕是采用一个公网的源ip出口,但是每个客户端请求携带的cookie是不一样的,因此haproxy可以根据cookie进行调度,

​ 客户端和应用服务器中间隔了haproxy此类反代软件时,cookie分2类,一类是后端服务器添加的用于保存会话信息的cookie,一类是haproxy代理添加,用于保证同样客户端的请求被调度到相同的后端节点,cookie都会被添加到响应报文头部的set-cookie字段,set-cookie字段一般情况下可以有多个,如下为百度首页响应头的3个set-cookie字段!

image-20200915171025325

​ 假设cli1第一次访问,根据调度算法,被调度到app server1上,app server1处理时会添加一些cookie信息到响应头,响应报文经由haproxy时,haproxy也会给响应头部加入一条,app=app1 ,app是可以自定义的cookie的名称,app1就是每个后端server的标识符,当cli1再次发请求时,携带了app=app1的信息,此时haproxy就知道上次该客户端是被app1处理的,然后会再次把它调度到app1上进行处理,自然,app1上也能找到cli1相关的会话信息,若此时app1 down掉,haproxy会将其调度到 app2上,haproxy设置的cooki会修改成app=app2,但此时cli1之前的会话就会丢失,除非各个app 之间设置了会话复制或、会话共享服务器、

image-20200915172120430

3、基础stick table

​ haproxy的stick table,可以抽取客户端请求报文的信息,如源ip,请求头部的host,响应头部应用服务器添加的session作为key;后端服务器的标识id作为value,组成一条k-v数据,那么后续请求,分析出是相同key的请求都会查表,然后转发到相同的后端服务器上,实现了会话的保持;第一次响应头部,应用服务器设置的session,haproxy在转发给客户端前,可以把这个session抽离出来,作为key,应用服务器id作为value,客户再次请求时,带着应用服务器设置的session,haproxy根据此信息做key,查到对应的valus即之前的应用服务器id,再将请求转发给相同的后端服务器,实现了会话保持

​ stick table,占用内存较小,一条标准k-v数据占用大概50字节,且支持额外的统计信息,每加一项统计信息,占用内存自然就大些

​ stick table,在haproxy的双主,多主架构时,多节点之间的复制效率极高,通过建立单独一条tcp连接实现复制,从而保证了haproxy上,会话信息的 高可用;

​ stick table查看,可以通过socat工具,借助haproxy的管理socket可以查看

4、基于cookie共享服务器

​ 此时后端节点状态外置,都成了无状态服务器,haproxy可以直接根据调度算法调度,前面三种:基于ip、基于haproxy设置的cookie,基于stick table实现的都是调度时的会话保持;保证了调度时能被调度到存有会话信息的同一台后端节点上, cookie共享服务器实现的是会话信息的剥离于后端节点,在后端节点挂掉时,其他节点仍能读取会话信息继续提供服务,当然会话服务器要做高可用!此时haproxy调度时,无需考虑会话的保持调度了,也无需设置基于ip等调度算法了,因为每台节点都能读取会话信息

image-20200915180733526

后端节点健康监测

​ haproxy作为反代服务,可以对后端节点做持续性的健康监测,动态的摘除,恢复后端节点;支持的监测方法有:

  • tcp四层监测,默认方法,探测的是tcp连接联通性
  • http ,可以基于状态码,响应头,响应体内容判断健康状态
  • ladp
  • mysql
  • pgsql
  • redis
  • spop
  • smtp

加工请求和响应报文

​ nginx作为反代时,可以对客户端请求报文,和后端节点响应报文做一定修改,haproxy同样支持,如:添加真实客户端ip在给后端的请求报文中,删除后端服务器版本信息在给客户端的响应报文中,等...

​ 在2 和 4 步可以,对报文头部进行修改

image-20200915184746777

状态查看

haproxy支持查看自身和后端节点的状态信息,通过启用管理用socket接口,socat包中命令可以实现调用该socket查看状态信息;

​ 1、启用配置

global 
	log 127.0.0.1 local2
	chroot /var/lib/haproxy
	pidfile /var/run/haproxy.pid
	maxconn 20000
	user haproxy
	group haproxy
	daemon 
	
	stats socket /var/lib/haproxy/stats
	# 启用管理用socket

​ 2、安装socat包

yum install -y socat
# epel 源

[root@host2 ~]# echo "help" | socat stdio /var/lib/haproxy/stats 
Unknown command. Please enter one of the following commands only :
  help           : this message
  prompt         : toggle interactive mode with prompt
  quit           : disconnect
  disable agent  : disable agent checks (use 'set server' instead)
  disable health : disable health checks (use 'set server' instead)
  disable server : disable a server for maintenance (use 'set server' instead)
# 查看帮助

[root@host2 ~]# echo "show info" | socat stdio /var/lib/haproxy/stats 
Name: HAProxy
Version: 1.7.12
Release_date: 2019/10/25
Nbproc: 1
Process_num: 1
# 查看信息

[root@host2 ~]# echo "show backend" | socat stdio /var/lib/haproxy/stats 
# name
static
app
# 查看所有后端
# 此外,还可以动态上下线某后端节点、调整权重、设置acl等

acl

​ haproxy支持acl,访问控制列表,access controll list,基于acl可以对请求流量分组,如根据请求的uri的特征,进行正则匹配,分为动、静,从而转发给不同的后端节点组

连接重用

​ haproxy在转发客户端请求时,选择调度到某个后端节点,之后haproxy会和该后端节点建立连接,该连接在完成一次请求和响应的传输后,如没有后续请求和响应,而该连接又不释放的情况下,空闲的tcp连接无疑是浪费,因此haproxy引入了连接重用,使得别的客户端的请求可以使用该空闲tcp连接进行传输

​ http-reuse strategy_name指令可以设置连接重用的策略,默认策略为禁用连接重用

​ strategy_name有4个值;

  • never,默认,表示禁用连接重用,来源不同的请求不会共享同一个后端连接;
  • safe,为客户端的第一个请求建立一个tcp连接,然后后续的请求会重用和后端节点空闲的tcp连接,
  • aggressive,重用空闲tcp连接转发大多数客户端第一次请求
  • always,总是为第一个请求重用空闲连接,
  • 建议:safe,搭配http-keep-alive的事务模型
updatedupdated2020-10-212020-10-21
加载评论