我观察到我们的 HAProxy 实例中存在一些交换,这些实例为 Web 套接字提供服务。目前故障率很低(每秒 0.01 次重大故障)。我们使用 nbproc 模式,其中一个进程用于 http 处理,另外 3 个进程专用于 SSL 处理。
从 Perf 中,我能够从 http 处理实例中获取以下故障样本:
Samples: 36 of event 'page-faults:u', Event count (approx.): 206
28.64% haproxy-t3 haproxy [.] si_conn_wake_cb
20.87% haproxy-t3 haproxy [.] si_conn_recv_cb
13.11% haproxy-t3 haproxy [.] raw_sock_to_buf
10.68% haproxy-t3 haproxy [.] stream_int_chk_snd_conn
7.28% haproxy-t3 haproxy [.] conn_fd_handler
4.37% haproxy-t3 haproxy [.] http_end_txn
3.88% haproxy-t3 haproxy [.] stream_int_update_conn
3.88% haproxy-t3 haproxy [.] process_session
2.91% haproxy-t3 haproxy [.] eb_delete
2.43% haproxy-t3 haproxy [.] stream_sock_read0
1.94% haproxy-t3 libc-2.12.so [.] __memset_sse2
由于这维持了相当数量的并发连接,因此内存使用量相当高(所有实例约为 16 GB(由于我们正在运行,因此总共有 4 个实例nbproc
)。
我是否应该尝试通过将 swapiness 设置为零来防止此故障?我认为这可能是健康的内存管理,但也许 haproxy 永远不应该真正进行交换?
参考数据:
这台机器的内存开销:
[root@ny-lb06 ~]# free -m
total used free shared buffers cached
Mem: 64375 58876 5499 0 86 34472
-/+ buffers/cache: 24317 40058
Swap: 6015 267 5748
版本信息:
HA-Proxy version 1.5.2 2014/07/12
Copyright 2000-2014 Willy Tarreau <[email protected]>
Build options :
TARGET = linux26
CPU = generic
CC = gcc
CFLAGS = -m64 -march=x86-64 -O2 -g -fno-strict-aliasing
OPTIONS = USE_GETADDRINFO=1 USE_REGPARM=1 USE_OPENSSL=1 USE_STATIC_PCRE=1
Default settings :
maxconn = 2000, bufsize = 16384, maxrewrite = 8192, maxpollevents = 200
Encrypted password support via crypt(3): yes
Built without zlib support (USE_ZLIB not set)
Compression algorithms supported : identity
Built with OpenSSL version : OpenSSL 1.0.1e-fips 11 Feb 2013
Running on OpenSSL version : OpenSSL 1.0.1e-fips 11 Feb 2013
OpenSSL library supports TLS extensions : yes
OpenSSL library supports SNI : yes
OpenSSL library supports prefer-server-ciphers : yes
Built with PCRE version : 7.8 2008-09-05
PCRE library supports JIT : no (USE_PCRE_JIT not set)
Built with transparent proxy support using: IP_TRANSPARENT IP_FREEBIND
Available polling systems :
epoll : pref=300, test result OK
poll : pref=200, test result OK
select : pref=150, test result OK
Total: 3 (3 usable), will use epoll.
配置片段:
global
maxconn 300000
tune.bufsize 16384
nbproc 4
所有 HAProxy 实例的内存(注意,haproxy-t3 是我们的套接字服务器实例,也是正在交换的实例):
[root@ny-lb06 ~]# ps -A -o cmd,vsz,rss,pid
/opt/haproxy/haproxy-t3 -D 8424224 8299192 30343
/opt/haproxy/haproxy-t3 -D 2259988 2185768 30344
/opt/haproxy/haproxy-t3 -D 3079456 3013344 30345
/opt/haproxy/haproxy-t3 -D 2445524 2380072 30346
/opt/haproxy/haproxy-t4 -D 93332 27780 31606
/opt/haproxy/haproxy-t4 -D 61108 2988 31607
/opt/haproxy/haproxy-t4 -D 61232 3132 31608
/opt/haproxy/haproxy-t4 -D 61288 7464 31609
/opt/haproxy/haproxy-t2 -D 66572 14216 32497
/opt/haproxy/haproxy-t2 -D 63308 12052 32498
/opt/haproxy/haproxy-t2 -D 66400 15696 32499
/opt/haproxy/haproxy-t2 -D 64168 12592 32500
/opt/haproxy/haproxy-t20 -D 57400 5268 33284
/opt/haproxy/haproxy-t20 -D 59620 3864 33285
/opt/haproxy/haproxy-t20 -D 59640 6176 33286
/opt/haproxy/haproxy-t20 -D 59620 3928 33287
/opt/haproxy/haproxy-t1 -D 805556 750948 34693
/opt/haproxy/haproxy-t1 -D 189860 137264 34694
/opt/haproxy/haproxy-t1 -D 196988 144472 34696
/opt/haproxy/haproxy-t1 -D 187136 134524 34697
/opt/haproxy/haproxy-t5 -D 59464 7368 41065
/opt/haproxy/haproxy-t5 -D 59756 1772 41066
/opt/haproxy/haproxy-t5 -D 59984 2136 41067
/opt/haproxy/haproxy-t5 -D 59756 4240 41068
答案1
绝对要防止这种情况发生!幸好你在事情变得太严重之前就注意到了。
请在全局部分中检查您的 maxconn,检查您是否在全局部分中使用“tune.bufsize”(否则您可以假设为 16kB),并检查进程数。
对于 haproxy 本身,使用的最大内存量约为 ((2 * bufsize + 2kB) * maxconn * nbproc),再加上内核端套接字的最小内存量约为 (4 * 4kB * maxconn * nbproc)。
WebSocket 的问题在于,连接可能持续很长时间,并且会堆叠在一起,从而导致比使用连接非常短的 HTTP 时更大的压力。您的设置可能允许过高的内存使用率,并且只有 WebSocket 能够达到这些限制。
顺便说一句,我看到这台机器上有 34 GB 的缓存,所以它可能是真正的缓存(在这种情况下你不必担心)或 /dev/shm 中的临时数据。另外,你能检查一下 haproxy 进程的 VSZ 和 RSS 吗?
答案2
经过一番挖掘,我发现了以下结果:
该盒子绝对不存在任何形式的内存争用。几乎所有缓存数据都由映射到 haproxy 日志文件的页面组成。由于这些文件不断被写入,并且往往非常庞大,它们会占用大量缓存页面。
当这些用于日志的磁盘页面被映射时,它们最终会从 haproxy 中交换出非常旧的匿名页面。所有非常旧的页面恰好属于我们的 websockets haproxy,它们可能是来自非常旧连接的缓冲空间。
我已经关闭了 swappiness,这样它就不会那么积极地交换页面。这应该会导致那些 haproxy 日志页面被丢弃,而不是 haproxy 匿名页面被交换出去。