--- title: "6. 内存管理" linkTitle: "6. 内存" weight: 300 description: "内存分配、限制、内存池、缓冲区与进程容量规划" icon: fa-solid fa-memory module: [HAPROXY] categories: [任务] aliases: - /haproxy/management/memory/ - /docs/haproxy/management/memory/ - /haproxy/memory/ upstream_link: "https://docs.haproxy.org/3.4/management.html" upstream_name: "HAProxy 3.4 Management Guide" upstream_ref: "v3.4.4, chapter 6" --- HAProxy 采用简单、快速的池式内存管理。由于 HAProxy 只使用少量不同的对象类型,从已经包含适当大小对象的内存池中获取新对象,远比针对每种大小分别调用 malloc() 高效。内存池按栈或 LIFO 方式组织,新分配的对象会优先取自刚刚释放、仍在 CPU 缓存中的对象。大小相近的内存池会合并,以减少内存碎片。 默认配置以性能为先:每个释放的对象都会放回原来的内存池;已分配对象不会归还给系统,因为预计很快便会再次使用。 可以在 CLI 中使用 "show pools" 命令检查各内存池的使用情况: ```shell > show pools Dumping pools usage. Use SIGQUIT to flush them. - Pool cache_st (16 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9ccc40=03 [SHARED] - Pool pipe (32 bytes): 5 allocated (160 bytes), 5 used, 0 failures, 2 users, @0x9ccac0=00 [SHARED] - Pool comp_state (48 bytes): 3 allocated (144 bytes), 3 used, 0 failures, 5 users, @0x9cccc0=04 [SHARED] - Pool filter (64 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 3 users, @0x9ccbc0=02 [SHARED] - Pool vars (80 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 2 users, @0x9ccb40=01 [SHARED] - Pool uniqueid (128 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 2 users, @0x9cd240=15 [SHARED] - Pool task (144 bytes): 55 allocated (7920 bytes), 55 used, 0 failures, 1 users, @0x9cd040=11 [SHARED] - Pool session (160 bytes): 1 allocated (160 bytes), 1 used, 0 failures, 1 users, @0x9cd140=13 [SHARED] - Pool h2s (208 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 2 users, @0x9ccec0=08 [SHARED] - Pool h2c (288 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9cce40=07 [SHARED] - Pool spoe_ctx (304 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 2 users, @0x9ccf40=09 [SHARED] - Pool connection (400 bytes): 2 allocated (800 bytes), 2 used, 0 failures, 1 users, @0x9cd1c0=14 [SHARED] - Pool hdr_idx (416 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9cd340=17 [SHARED] - Pool dns_resolut (480 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9ccdc0=06 [SHARED] - Pool dns_answer_ (576 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9ccd40=05 [SHARED] - Pool stream (960 bytes): 1 allocated (960 bytes), 1 used, 0 failures, 1 users, @0x9cd0c0=12 [SHARED] - Pool requri (1024 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9cd2c0=16 [SHARED] - Pool buffer (8030 bytes): 3 allocated (24090 bytes), 2 used, 0 failures, 1 users, @0x9cd3c0=18 [SHARED] - Pool trash (8062 bytes): 1 allocated (8062 bytes), 1 used, 0 failures, 1 users, @0x9cd440=19 Total: 19 pools, 42296 bytes allocated, 34266 used. ``` 内存池名称仅供识别,取自最先使用该内存池的对象类型。括号中的大小是池内对象的大小;对象大小总是向上取整为最接近的 16 字节倍数。输出会同时报告当前已分配的对象数及其对应字节数,便于判断哪个内存池占用最多。"used" 字段还会报告当前正在使用的对象数;"allocated" 与 "used" 之差,就是已经释放、可立即复用的对象数。每行末尾的地址是内存池地址,后面的数字是内存池索引;没有分配索引时报告为 -1。 可以使用 "-m" 命令行选项限制每个进程分配的内存量,后接以 MB 为单位的数值。该限制覆盖进程的全部可寻址空间,包括部分库和栈使用的内存,因此在构建资源受限系统时可以作为可靠上限。其作用与支持 "ulimit -v" 的系统相同,其他系统则相当于 "ulimit -d"。 如果因为达到内存上限或系统可用内存不足而分配失败,HAProxy 会先释放所有内存池中的全部可用对象,再次尝试分配。向 HAProxy 进程发送 SIGQUIT 信号,也可以主动触发这一未使用内存释放机制。 执行重载时,进入优雅停止状态的进程还会在释放连接后自动执行若干清理操作,尽可能释放内存供新进程使用。