haproxy反向代理

编译安装

源码包下载

[root@localhost ~]# cd /usr/local/src/
[root@localhost ~]# wget http://www.haproxy.org/download/2.4/src/haproxy-2.4.9.tar.gz


# 解压
[root@localhost src]# tar xf haproxy-2.4.9.tar.gz

安装编译的基础环境

yum install gcc gcc-c++ glibc glibc-devel pcre pcre-devel openssl openssl-devel systemd-devel net-tools vim iotop zip unzip zlib-devel lrzsz tree screen lsof tcpdump

# lua环境源码下载
wget http://www.lua.org/ftp/lua-5.4.3.tar.gz
tar xf lua-5.4.3.tar.gz
cd lua-5.4.3

make all test

# 验证
[root@localhost lua-5.4.3]# lua -v
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio


[root@localhost lua-5.4.3]# ./src/lua -v
Lua 5.4.3  Copyright (C) 1994-2021 Lua.org, PUC-Rio

编译安装haproxy

make ARCH=x86_64 TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_CPU_AFFINITY=1 USE_LUA=1 LUA_INC=/usr/local/src/lua-5.4.3/src/ LUA_LIB=/usr/local/src/lua-5.4.3/src/ PREFIX=/apps/haproxy

make install PREFIX=/apps/haproxy

验证HAProxy版本

[root@localhost haproxy-2.4.9]# /apps/haproxy/sbin/haproxy -v
HAProxy version 2.4.9-f8dcd9f 2021/11/24 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2 2026.
Known bugs: http://www.haproxy.org/bugs/bugs-2.4.9.html
Running on: Linux 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64

准备启动脚本

 cat >> /usr/lib/systemd/system/haproxy.service << 'EOF'
[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target

[Service]
ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q 
ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /var/lib/haproxy/haproxy.pid
ExecReload=/bin/kill -USR2 $MAINPID

[Install]
WantedBy=multi-user.target
EOF

配置文件

cat /etc/haproxy/haproxy.cfg
global  # 全局配置
maxconn 100000  # 每个haproxy进程最大的并发连接数
chroot /apps/haproxy  # 锁定运行目录
# stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin  # socket文件
stats socket /var/lib/haproxy/haproxy1.sock mode 600 level admin process 1 # 多进程模式下,需要每个进程定义一个socket文件
stats socket /var/lib/haproxy/haproxy2.sock mode 600 level admin process 2
stats socket /var/lib/haproxy/haproxy3.sock mode 600 level admin process 3
stats socket /var/lib/haproxy/haproxy4.sock mode 600 level admin process 4

uid 99 # 运行haproxy的用户uid
gid 99 # 运行haproxy的组id
daemon  # 以守护进程运行
nbproc 4  # 开启haproxy的进程个数,一般于cpu保持一直
cpu-map 1 0  # 第一个进程绑定到cpu0上
cpu-map 2 1
cpu-map 3 2
cpu-map 4 3
pidfile /var/lib/haproxy/haproxy.pid  # haproxy的pid文件路径,这个路径需要手动创建
log 127.0.0.1 local3 info  # 定义syslog服务器

defaults  # 默认配置项,针对以下的frontend、backend和lsiten⽣效
option http-keep-alive  # 开启与客户端的会话保持
option forwardfor # 透传客户端真实IP至后端web服务器
maxconn 100000

mode http #设置默认工作类型
timeout connect 300000ms # 客户端请求从haproxy到后端server的最长连接等待时间(TCP之前)
timeout client 300000ms # 设置haproxy与客户端的最长非活动时间
timeout server 300000ms # 客户端请求从haproxy到后端服务端的请求处理超时时长(TCP之后),这个时间设置要稍微长一点


frontend+backend配置示例:

frontend WEB_PORT_80
	bind 192.168.119.248:80 # 监听的地址和端口
	mode http # 工作类型
	use_backend web_prot_http_nodes # 指定backend的名字

backend web_prot_http_nodes
	mode http # 工作类型
	option forwardfor # 这里如果不定义,会使用defaults配置段的配置
	server 192.168.119.101 192.168.119.101:8080 check inter 3000 fall 3 rise 5
		# check inter 3000 fall 2 rise 5
		# check 对指定real进行健康状态检查
		# inter 健康状态检查间隔时间,默认2000 ms
		# fall 后端服务器失效检查次数,默认为3
		# rise 后端服务器从下线恢复检查次数,默认为2
	server 192.168.119.102 192.168.119.102:8080 check inter 3000 fall 3 rise 5

listen替代frontend+backend

listen web_port
	bind 192.168.119.101:80  # 监听的地址和端口
	mode http  # 工作类型
	log global
	server web1 192.168.119.103:80 check inter 3000 fall 2 rise 5
	server web2 192.168.119.104:80 check inter 3000 fall 2 rise 5

准备两台nginx提供web服务

yum install nginx -y

web1
echo web1 >  /usr/share/nginx/html/index.html

web2
echo web2 >  /usr/share/nginx/html/index.html

测试:

[root@localhost nginx]# while  true;do  curl http://192.168.119.101;sleep 0.5 ;done
web1
web2
web1
web2
web1
web2

调度算法

静态算法

静态算法:按照事先定义好的规则轮询公平调度,不关⼼后端服务器的当前负载、链接数和响应速度等,且⽆法实时修改权重,只能靠重启HAProxy⽣效。

static-rr:基于权重的轮询调度,不支持权重的运行时调整及后端服务器慢启动,其后端主机数量没有限制

first:根据服务器在列表中的位置,自上⽽下进行调度,但是其只会当第⼀台服务器的连接数达到上限,新请求才会分配给下⼀台服务,因此会忽略服务器的权重设置。

动态算法

roundrobin:基于权重的轮询动态调度算法,支持权重的运行时调整,不完全等于lvs中的rr轮训模式,HAProxy中的roundrobin⽀持慢启动(新加的服务器会逐渐增加转发数),其每个后端backend中最多支持4095个real server,roundrobin为默认调度算法,且支持对real server权重动态调整。

leastconn加权的最少连接的动态,支持权重的运行时调整和慢启动,即当前后端服务器连接最少的优先调度(新客户端连接),⽐较适合长连接的场景使用,⽐如MySQL等场景。

其他算法

其他部分算法即可作为静态算法,⼜可以通过选项成为动态算法(hash-type consistent)

source:源地址hash,基于用户源地址hash并将请求转发到后端服务器,默认为静态即取模⽅式,但是可以通过hash-type⽀持的选项更改,后续同⼀个源地址请求将被转发至同⼀个后端web服务器,⽐较适用于session保持/缓存业务等场景。

uri:基于对用户请求的uri做hash并将请求转发到后端指定服务器,也可以通过map-based和consistent定义使用取模法还是⼀致性hash。

url_param:url_param对用户请求的url中的 params 部分中的参数name作hash计算,并由服务器总权重相除以后派发至某挑出的服务器;通常用于追踪用户,以确保来自同⼀个用户的请求始终发往同⼀个real server

hdr:针对用户每个http头部(header)请求中的指定信息做hash,此处由 name指定的http⾸部将会被取出并做hash计算,然后由服务器总权重相除以后派发至某挑出的服务器,假如⽆有效的值,则会使用默认的轮询调度。

rdp-cookie:rdp-cookie可以实现对windows远程桌⾯的负载,如果有多个后端windows Server服务器,rdp-cookie可以实现同⼀个window server的请求始终被转发给同⼀个后端服务器,如果之前从未访问过,那么第⼀次使用连接roundrobin算法计算出⼀个后端服务器并进行转发。

random:在1.9版本开始增加⼀个叫做random的负载平衡算法,其基于⼀个随机数作为⼀致性hash的key,随机负载平衡对于⼤型服务器场或经常添加或删除服务器非常有用。

static-rr--------->tcp/http 静态
first------------->tcp/http 静态

roundrobin-------->tcp/http 动态
leastconn--------->tcp/http 动态
random------------>tcp/http 动态

source------------>tcp/http
Uri--------------->http
url_param--------->http 取决于hash_type是否consistent
hdr--------------->http
rdp-cookie-------->tcp
# 如果mode是tcp,算法用的是只能用http的算法,例如url_param,会自动把算法改为roundrobin

配置监控页面:

listen stats
	mode http
	bind 0.0.0.0:9999	# 监听的IP和端口
	stats enable
	log global
	stats uri /haproxy-status  # http://<IP>:9999/haproxy-status
	stats auth haadmin:q1w2e3r4ys # 配置登录的用户名和密码,如果不加此项,打开页面不需要认证
	# stats admin if TRUE		# 启用状态页的管理功能,一般不开启

状态页说明

pid = 3698 (process #2, nbproc = 2, nbthread = 1) #pid为当前pid号,process为当前进程号,nbproc和nbthread为⼀共多少进程和每个进程多少个线程
uptime = 0d 0h00m08s #启动了多长时间
system limits: memmax = unlimited; ulimit-n = 131124 #系统资源限制:内存/最⼤打开文件数/
maxsock = 131124; maxconn = 65536; maxpipes = 0 #最⼤socket连接数/单进程最⼤连接数/最⼤管道数maxpipes
current conns = 1; current pipes = 0/0; conn rate = 1/sec #当前连接数/当前管道数/当前连接速率
Running tasks: 1/9; idle = 100 % #运行的任务/当前空闲率
active UP:#在线服务器
backup UP:#标记为backup的服务器

active UP, going down:#监测未通过正在进⼊down过程
backup UP, going down:#备份服务器正在进⼊down过程
active DOWN, going up:#down的服务器正在进⼊up过程
backup DOWN, going up:#备份服务器正在进⼊up过程
active or backup DOWN:#在线的服务器或者是backup的服务器已经转换成了down状态
not checked:#标记为不监测的服务器
active or backup DOWN for maintenance (MAINT) #active或者backup服务器⼈为下线的
active or backup SOFT STOPPED for maintenance #active或者backup被⼈为软下线(⼈为将weight改成0)

基于haproxy,实现网页动静分离

访问控制列表(ACL,Access Control Lists)是⼀种基于包过滤的访问控制技术,它可以根据设定的条件对经过服务器传输的数据包进行过滤(条件匹配),即对接收到的报文进行匹配和过滤,基于请求报文头部中的源地址、源端口、目标地址、目标端口、请求⽅法、URL、文件后缀等信息内容进行匹配并执行进⼀步操作,⽐如允许其通过或丢弃。

acl		<aclname>	<criterion>		[flags]		[operator]		[<value>]
acl		名称			匹配规范		匹配模式	具体操作符		操作对象类型

匹配规范

hdr([<name> [,<occ>]]):完全匹配字符串,header的指定信息
hdr_beg([<name> [,<occ>]]):前缀匹配,header中指定匹配内容的begin
hdr_end([<name> [,<occ>]]):后缀匹配,header中指定匹配内容end
hdr_dom([<name> [,<occ>]]):域匹配,header中的domain name

hdr_dir([<name> [,<occ>]]):路径匹配,header的uri路径
hdr_len([<name> [,<occ>]]):长度匹配,header的长度匹配
hdr_reg([<name> [,<occ>]]):正则表达式匹配,自定义表达式(regex)模糊匹配
hdr_sub([<name> [,<occ>]]):⼦串匹配,header中的uri模糊匹配

dst 目标IP
dst_port 目标PORT

src 源IP
src_port 源PORT

⽰例:
hdr(<string>) 用于测试请求头部首部指定内容
hdr_dom(host) 请求的host名称,如 www.12345.com
hdr_beg(host) 请求的host开头,如 www. img. video. download. ftp.
hdr_end(host) 请求的host结尾,如 .com .net .cn
path_beg 请求的URL开头,如/static、/images、/img、/css
path_end 请求的URL中资源的结尾,如 .gif .png .css .js .jpg .jpeg

有些功能是类似的,⽐如以下⼏个都是匹配用户请求报文中host的开头是不是www:
	acl short_form hdr_beg(host) www.
	acl alternate1 hdr_beg(host) -m beg www.
	acl alternate2 hdr_dom(host) -m beg www.
	acl alternate3 hdr(host) -m beg www.

匹配模式

-i 不区分⼤⼩写
-m 使用指定的pattern匹配⽅法
-n 不做DNS解析
-u 禁⽌acl重名,否则多个同名ACL匹配或关系
global
maxconn 100000
chroot /apps/haproxy
stats socket /var/lib/haproxy/haproxy1.sock mode 600 level admin process 1 # 多进程模式下,需要每个进程定义一个socket文件
stats socket /var/lib/haproxy/haproxy2.sock mode 600 level admin process 2
stats socket /var/lib/haproxy/haproxy3.sock mode 600 level admin process 3
stats socket /var/lib/haproxy/haproxy4.sock mode 600 level admin process 4
uid 99
gid 99
daemon
nbproc 4
cpu-map 1 0
cpu-map 2 1
cpu-map 3 2
cpu-map 4 3
pidfile /var/lib/haproxy/haproxy.pid
log 127.0.0.1 local3 info

defaults
option http-keep-alive
option forwardfor
maxconn 100000

mode http
timeout connect 300000ms
timeout client 300000ms
timeout server 300000ms


listen web_port
	bind 192.168.119.101:80
	mode http
	log global
	####################################
	acl php_server path_end -i .php 
		# php_server  ACL的名称
		# path_end	请求的URL中资源的结尾
		# -i 不区分大小写
	use_backend php_server_host if php_server
		# 如果匹配上名称为php_server的acl,就转发到php_server_host后端主机组
	####################################
	acl image_server path_end -i .jpg .png .jpeg .gif
	use_backend image_server_host if image_server	
	####################################
	
backend php_server_host
	mode http
	server web1 192.168.119.103 check inter 3000 fall 2 rise 5
	
backend backend image_server_host
	mode http
	server web2 192.168.119.104 check inter 3000 fall 2 rise 5

使用haproxy,实现https

证书制作

# mkdir /apps/haproxy/certs
# cd /apps/haproxy/certs
# openssl genrsa -out haproxy.key 2048
# openssl req -new -x509 -key haproxy.key -out haproxy.crt -subj "/CN=www.12345.net"
# cat haproxy.key haproxy.crt > haproxy.pem
# openssl x509 -in haproxy.pem -noout -text #查看证书

配置:

#web server http
frontend web_server-http
	bind 192.168.119.101:80
	redirect scheme https if !{ ssl_fc }  # 全站https主要选项
	mode http
	use_backend web_host

# web server https
frontend web_server-https
	bind 192.168.119.101:443 ssl crt /apps/haproxy/certs/haproxy.pem
	mode http
	use_backend web_host

backend web_host
	mode http
	http-request set-header X-Forwarded-Port %[dst_port]
	http-request add-header X-Forwarded-Proto https if { ssl_fc }
	server web1 192.168.119.103:80 check inter 2000 fall 3 rise 5
	server web2 192.168.119.104:80 check inter 2000 fall 3 rise 5
上一篇:linux与文件操作相关命令


下一篇:customizeFunctions.py