haproxy在1.8就官方就开始支持很多的新的功能,如:reload的功能,至今从2001年12月到现在已经过去了17年,改进是非常的多,并且在未来haproxy将会以每年2次的发布更新,版本先后兼容旧的配置。
PS:内容谷歌翻译
在haproxy1.9中更新了很多的内容,其中包括:
缓冲区改进
HAProxy 已经支持HTTP / 2到客户端。此版本的主要目标是支持端到端HTTP / 2,包括后端服务器。我们还希望支持任何未来版本的HTTP,例如HTTP / 3(QUIC)。
我们的研发团队付出了巨大的努力来确定实现这一目标所需的变更。发现的一个非常重要的问题涉及HAProxy处理缓冲区的方式。
该缓冲器是存储切成两个部分的面积:尚未被分析和输出数据的输入数据。缓冲区可以在任何地方开始和结束。在以前的HAProxy版本中,有22种可能的缓冲区(代码的两个版本:输入和输出),如下图所示:
这显示了1.9版之前各类缓冲区及其分配方式的细分。决定重写缓冲区处理并简化缓冲区分配。下面的图表显示了最新的缓冲区更改:
从此前的复杂的22种重写缓冲区处理并简化缓冲区分配到现在的7个。并且缓冲区从存储区域分离。这意味着对于相同的数据不再具有单个表,并且多个actor可以在不同的状态下使用相同的存储。这通常在数据传输期间在较低层多路复用器中使用,以通过读取器和写入器对相同数据块进行别名来避免存储器复制(“零复制”)。这导致HTTP / 2的性能提升。
链接管理
从面向回调的模型转变为具有完成回调的异步事件模型。这种新设计将非常有益,并减少连接层中可能出现的错误数量。
这些设计可以较低的send()延迟(几乎从不轮询),更少的层间往返(更好的I-cache效率),在上层直接使用,以及消除代码重复和在较低层内提供粒度错误报告。它也将提供给重试失败的连接,使用一个不同的协议。
线程改进
1.9中的线程进行了重大改进。这些变化使HAProxy能够提供卓越的性能。为实现这一目标,任务调度程序进行了重新设计。它现在将其工作分为三个层次:
- 所有线程之间共享的优先级感知级别
- 无锁,优先级感; 每个线程一个
- 每个线程的已启动任务列表,可用于I / O.
这导致大多数调度工作在没有任何锁定的情况下执行,这可以更好地扩展。此外,在调度程序中对其等待队列进行了优化。它们现在大部分都是无锁的。内存分配器变得无锁,并使用最近使用的对象的每线程缓存,这些对象在CPU缓存中仍然就绪,从而导致更快的结构初始化。文件描述符事件缓存也基本上无锁,允许更快的并发I / O操作。最后,文件描述符(FD)锁已更新,因此使用频率较低。总的来说,在使用启用了线程的HAProxy 1.9时,应该会看到大约60%的性能提升。
缓存改进
在HAProxy 1.8中引入了小对象缓存。在内部,我们将其称为favicon缓存,因为它仅限于缓存小于的对象tune.bufsize
,默认为16KB。此外,在第一个版本中,它只能缓存返回HTTP 200 OK响应代码的对象。
在HAProxy 1.9中,现在可以缓存最大2GB的对象,设置为max-object-size
。该total-max-size
设置确定缓存的总大小,最多可增加到4095MB。
API改进
我们已经更新了Runtime API。第一个更改修改了主/工模型,以支持更轻松地与工作人员进行交互,并更好地观察整个过程。首先,master现在有自己的套接字,可以用来直接与它通信。然后,此套接字可以管理与每个工作者的通信,甚至是那些正在退出的工作者。
要开始使用此新功能,应使用-W
和-S
选项启动HAProxy 。
[root@Linuxea.com ~]# haproxy -W -S /var/run/haproxy-master-socket -f /etc/haproxy/haproxy.cfg
然后通过主套接字连接到Runtime API,如下所示:
[root@Linuxea.com ~]# docker exec -it haproxy bash
bash-4.4# socat /var/run/haproxy.sock readline
prompt
master> help
Unknown command. Please enter one of the following commands only :
help : this message
prompt : toggle interactive mode with prompt
quit : disconnect
@<relative pid> : send a command to the <relative pid> process
@!<pid> : send a command to the <pid> process
@master : send a command to the master process
show cli sockets : dump list of cli sockets
show cli level : display the level of the current CLI session
show proc : show processes status
operator : lower the level of the current CLI session to operator
user : lower the level of the current CLI session to user
reload : reload haproxy
新show proc
命令显示每个进程的正常运行时间。
master> show proc
#<PID> <type> <relative PID> <reloads> <uptime>
11 master 0 1 0d 15h44m38s
# workers
16 worker 1 0 0d 04h22m44s
新reload
命令重新加载HAProxy并加载新的配置文件。它与向主进程发送SIGUSR2信号完全相同,只是在重载新配置文件后可以由外部程序触发。
在主套接字中,命令可以通过在命令前加上@符号和工作者编号来发送到每个单独的工作进程。以下是你将如何show info
向第一个工作进程发出的示例:
master> @1
16> show info
Name: HAProxy
Version: 1.9.8
Release_date: 2019/05/13
Nbthread: 1
Nbproc: 1
Process_num: 1
Pid: 16
Uptime: 0d 4h23m22s
Uptime_sec: 15802
Memmax_MB: 0
.....
我们还添加了有效负载支持,允许你使用Runtime API插入多行值。例如,这对于更新map 文件很有用。目前,不支持通过Runtime API更新TLS证书,但请继续关注HAProxy 2.0!
要使用有效负载更新map 文件,你将获得要更新的map 的ID,然后用于add map
追加新行,用 n分隔行:
echo "show map" | socat /var/run/haproxy.sock stdio
# id (file) description
-1 (/etc/haproxy/maps/hosts.map) pattern loaded from file '/etc/haproxy/maps/hosts.map' used by map at file '/etc/hapee-1.8/hapee-lb.cfg' line 94
$ echo -e "add map #-1 <<ntest1 be_onentest2 be_twon" | socat /var/run/haproxy.sock stdio
$ echo "show map #-1" | socat /var/run/haproxy.sock stdio
0x217aa80 test1 be_one
0x2190010 test2 be_two
你还可以附加文件的内容,如下所示:
$ echo -e “ add map#-1 << n $( cat data.map ) n ” | socat /var/run/haproxy.sock stdio
HAProxy已经可以执行OCSP装订,其中证书的撤销状态和到期日期附加到TLS证书。这使浏览器不必联系证书供应商本身进行验证。新的有效负载支持使你可以更轻松地更新OCSP文件,而无需重新加载HAProxy。
首先,使用openssl ocsp命令为证书生成.ocsp文件。获得.ocsp文件后,你可以发出以下命令,该命令将使用具有有效负载支持的Runtime API在正在运行的进程中进行更新:
$ echo -e “ set ssl ocsp-response << n $( base64 /etc/haproxy/certs/haproxy.com.pem.ocsp ) n ” | socat /var/run/haproxy.sock stdio
下面的脚本显示了自动执行此过程的完整示例:
#!/bin/bash
# Certificates path and names
DIR="/etc/haproxy/certs"
CERT="haproxy.com.pem"
RUNTIME_API=/var/run/haproxy.sock
# Get the issuer URI, download it's certificate and convert into PEM format
ISSUER_URI=$(openssl x509 -in ${DIR}/${CERT} -text -noout | grep 'CA Issuers' | cut -d: -f2,3)
ISSUER_NAME=$(echo ${ISSUER_URI##*/} | while read -r fname; do echo ${fname%.*}; done)
wget -q -O- $ISSUER_URI | openssl x509 -inform DER -outform PEM -out ${DIR}/${ISSUER_NAME}.pem
# Get the OCSP URL from the certificate
ocsp_url=$(openssl x509 -noout -ocsp_uri -in ${DIR}/${CERT})
# Extract the hostname from the OCSP URL
ocsp_host=$(echo $ocsp_url | cut -d/ -f3)
# Create/update the ocsp response file and update HAProxy
openssl ocsp -noverify -no_nonce -issuer ${DIR}/${ISSUER_NAME}.pem -cert ${DIR}/${CERT} -url $ocsp_url -header Host $ocsp_host -respout ${DIR}/${CERT}.ocsp
echo -e "set ssl ocsp-response <<n$(base64 ${DIR}/${CERT}.ocsp)n" |socat $RUNTIME_API stdio
exit 0
show activity
Runtime API中还添加了一个新命令。它为每个线程显示系统检测到的总CPU时间,可能是在同一处理器上运行的其他进程中,或者由同一个虚拟机管理程序共享的另一个VM。它还指示所有任务所经历的平均处理延迟,这可能表示正在进行一些繁重的操作,例如非常高的非对称加密使用,或涉及数千个正则表达式的极大ACL。
[root@Linuxea.com ~]# socat /var/run/haproxy.sock readline
prompt
master> @1
16> show activity
thread_id: 0
date_now: 1559625686.924307
loops: 145909
wake_cache: 64549
wake_tasks: 16244
wake_signal: 0
poll_exp: 80793
poll_drop: 68
poll_dead: 0
poll_skip: 0
fd_skip: 0
fd_lock: 0
fd_del: 0
conn_dead: 0
stream: 213
empty_rq: 81148
long_rq: 0
cpust_ms_tot: 3
cpust_ms_1s: 0
cpust_ms_15s: 0
avg_loop_us: 26
同样,在global
部分中启用分析或使用Runtime API启用分析时,可以在日志中报告CPU时间和延迟值。这有助于指出哪些TCP / HTTP请求需要花费很多时间才能处理,哪些会受到其他TCP / HTTP请求的影响。要在该global
部分中启用分析,你需要添加
global
profiling.tasks on
(可选)使用Runtime API进行设置:
$ echo "set profiling tasks on" |socat /var/run/haproxy.sock -
要验证它已启用:
$ echo "show profiling" |socat /var/run/haproxy.sock -
Per-task CPU profiling : on # set profiling tasks {on|off}
haproxy日志格式
HAProxy日志中捕获的以下提取:
获取方法 | 描述 |
---|---|
date_us | 日期的微秒部分。 |
cpu_calls | 自分配以来处理流或当前请求的任务的调用次数。它会在同一连接上为每个新请求重置。 |
cpu_ns_avg | 每次调用处理流或当前请求的任务所花费的平均纳秒数。 |
cpu_ns_tot | 每次调用处理流或当前请求的任务所花费的总纳秒数。 |
lat_ns_avg | 在处理流的任务被唤醒的那一刻和它被有效调用的那一刻之间花费的平均纳秒数。 |
lat_ns_tot | 唤醒流的任务被唤醒的时刻与有效调用流的时刻之间的总纳秒数。 |
要在日志中使用这些,你可以扩展默认的HTTP日志格式,如下所示:
log-format "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r cpu_calls:%[cpu_calls] cpu_ns_tot:%[cpu_ns_tot] cpu_ns_avg:%[cpu_ns_avg] lat_ns_tot:%[lat_ns_tot] lat_ns_avg:%[lat_ns_avg]"
或者,扩展默认TCP log-format
:
log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq cpu_calls:%[cpu_calls] cpu_ns_tot:%[cpu_ns_tot] cpu_ns_avg:%[cpu_ns_avg] lat_ns_tot:%[lat_ns_tot] lat_ns_avg:%[lat_ns_avg]"
服务器队列优先级控制
HAProxy 1.9允许你为某些排队连接优先于其他连接。例如,这可以帮助你在图像之前传递JavaScript或CSS文件。或者,你可以使用它来改善高级客户的加载时间。使用它的另一种方法是给机器人一个较低的优先级。
通过添加http-request set-priority-class
指定指定分配给请求的重要性级别的指令,为JS或CSS文件在映像上设置更高的服务器队列优先级。为了避免由连续的高优先级请求流引起的饥饿,还有一个set-priority-offset
指令设置某个请求与其他请求相比应该经历的额外等待时间的上限。将此与ACL规则结合使用时,你可以灵活地决定何时以及如何确定连接的优先级。
acl is_jscss path_end .js .css
acl is_image path_end .png .jpg .jpeg
http-request set-priority-class int(1) if is_jscss
http-request set-priority-class int(10) if is_image
http-request set-priority-class int(100) if !is_jscss !is_image
较低的数字被赋予较高的优先级。因此,在这种情况下,JavaScript和CSS文件被赋予最高优先级,其次是图像,然后是其他所有内容
随机负载均衡算法
我们添加了一个新的随机负载平衡算法。使用时,将选择随机数作为一致散列函数的关键字。在此模式下,服务器权重受到尊重。动态权重更改会立即生效,新服务器添加也会立即生效。随机负载平衡对于大型服务器机群或经常添加和删除服务器非常强大。当使用许多负载均衡器时,它会降低所有负载均衡器指向同一服务器的风险,例如可能发生在最少的情况下。
该hash-balance-factor
指令可用于通过保持分配给服务器的负载接近平均值来进一步提高负载平衡的公平性,这在服务器显示高度可变响应时间的情况下尤其有用。
要启用随机负载平衡算法,请在a中设置balance
为randombackend
。
balance random
我们一直在寻求改进我们的负载平衡算法,并希望尽快推出更多选项!
原生日志
HAProxy已具备登录系统日志服务器的能力。但是,在使用Docker的微服务架构中,将syslog安装到容器中违背了范例。用户经常要求使用其他方法来发送日志。我们已经收到了相当多的请求,并花了一些时间来规划实施它的最佳方式 - 没有阻塞 - 我们很高兴地宣布我们已经找到了解决方案!
使用HAProxy 1.9时,你现在可以利用三种新方法发送日志:将它们发送到文件描述符,stdout或stderr。可以使用标准log
语句添加这些新方法。
要启用日志记录到stdout,请使用以下stdout
参数:
log stdout local0
同样可以做到stderr
。另一种方法是登录文件描述符,如下所示:
log fd @ 1 local0
该fd@1
参数是别名,stdout
并且fd@2
是别名stderr
。此更改还带有两种新的日志格式:( raw
更适合Docker)和short
(更适合systemd)。
log stdout format raw local0
请注意
Haproxy不支持记录到文件。如文档(https://cbonte.github.io/haproxy-dconv/1.8/configuration.html#3.1-log)中所述,“log”语句将地址作为第一个参数。如果这是一个文件,它是一个unix套接字,HAProxy将以syslog格式解释出这个套接字。Haproxy的设计是这样的,因为它的责任是代理请求,而不是写文件,它将日志文件的写入委托给syslog
新的方式
HAProxy中的提取提供来自内部状态或第4,5,6和7层的信息源。你可以在此版本中看到的新提取包括:
获取方法 | 描述 |
---|---|
date_us | 日期的微秒部分。 |
cpu_calls | 自分配以来处理流或当前请求的任务的调用次数。它会在同一连接上为每个新请求重置。 |
cpu_ns_avg | 每次调用处理流或当前请求的任务所花费的平均纳秒数。 |
cpu_ns_tot | 每次调用处理流或当前请求的任务所花费的总纳秒数。 |
lat_ns_avg | 在处理流的任务被唤醒的那一刻和它被有效调用的那一刻之间花费的平均纳秒数。 |
lat_ns_tot | 唤醒流的任务被唤醒的时刻与有效调用流的时刻之间的总纳秒数。 |
srv_conn_free / be_conn_free | 确定服务器/后端上的可用连接数。 |
ssl_bc_is_resumed | 通过SSL / TLS传输层进行反向连接并使用缓存会话或TLS票证恢复新创建的SSL会话时,返回true。 |
fe_defbe | 获取前端默认后端名称。 |
ssl_fc_session_key / ssl_bc_session_key | 返回前/后连接的SSL主密钥。 |
ssl_bc_alpn / ssl_bc_npn | 为传出连接提供ALPN和NPN。 |
prio_class | 返回http模式的当前会话的优先级类或tcp模式的连接。 |
prio_offset | 返回http模式的当前会话的优先级偏移量或tcp模式的连接的优先级偏移量 |
新的转换器
转换器允许你在HAProxy中转换数据,并且通常在获取后进行跟踪。以下转换器已添加到HAProxy 1.9:
变流器 | 描述 |
---|---|
STRCMP | 将的内容与string类型的输入值进行比较。 |
CONCAT | 在当前样本之后连接最多三个字段,然后将其转换为字符串。 |
长度 | 返回字符串的长度。 |
CRC32C | 使用CRC32C散列函数将二进制输入样本散列为无符号的32位数量。 |
ipv6添加到“ipmask”转换器 | 将掩码应用于IPv4 / IPv6地址,并使用结果进行查找和存储。 |
字段/字转换器扩展 | 扩展,因此可以提取从开头/结尾开始计数的字段/单词和/或提取多个字段/单词(包括分隔符)。 |
其他杂项
此版本的HAProxy还添加了其他各种改进。他们包括:
- 新的棒表柜台,
gpc1
和gpc1_rate
,可用。 - 该
resolvers
部分现在支持resolv.conf。 busy-polling
- 允许在使用频率调整或支持深度空闲状态的机器上将请求处理延迟减少30-100微秒。-
对HAProxy中的Lua引擎进行了以下更新:
- 该服务器类上涨更改服务器的能力
maxconn
值。 - 该TXN类上涨到服务器队列中调整连接的优先级的能力。
- 有一个新的StickTable类允许访问
stick-table
按键的内容并允许转储内容。
- 该服务器类上涨更改服务器的能力
阅读更多
HAProxy 1.8的新功能HAProxy 1.9 Has Arrived使用HAProxy Runtime API进行动态配置Haproxy 配置手册haproxy入门指南使用HAProxy Runtime API进行动态配置负载平衡,亲和力,持久性,粘性会话