🔗 Squid 如何使用内存
Squid 出于性能考虑会使用大量内存。与直接从内存读取数据相比,从磁盘读取数据要花费更长的时间。
每个缓存对象的少量元数据都保存在内存中。这是StoreEntry数据结构。在 32 位架构上是 56 字节,在 64 位架构上是 88 字节。此外,每个StoreEntry都有一个 16 字节的缓存键(MD5 校验和)。这意味着您的缓存中的每个对象在内存中都有 72 或 104 字节的元数据。因此,一个包含 1,000,000 个对象的缓存仅元数据就需要 72MB 的内存。实际上,它需要的远不止这些。
Squid 的内存使用包括
| 原因 | 解释 | 参数 |
|---|---|---|
| 用于读写的磁盘缓冲区 | ||
| 网络 I/O 缓冲区 | read_ahead_gap | D |
| IP 缓存内容 | ipcache_size | DNS |
| FQDN 缓存内容 | fqdncache_size | DNS |
| Netdb ICMP 测量数据库 | N | |
| 每个请求的状态信息,包括完整的请求和响应头 | D | |
| 杂项统计信息收集 | D | |
| 磁盘上缓存的索引(元数据,保存在内存中) | cache_dir | I |
| 内存中的缓存(“热门对象”) | cache_mem | M+I |
字母解释
| D | 动态;访问的网站越多,使用的内存就越多 |
| I | 对于 32 位 Squid,每 1GB 磁盘占用 10MB 内存 对于 64 位 Squid,每 1GB 磁盘占用 14MB 内存 |
| N | 不经常使用 |
| M | 经验法则:cache_mem 通常占总内存消耗的三分之一。 除了配置的值之外,还有用于这些对象索引的内存(参见“I”) |
| DNS | 不建议更改。仅在缓存非常大或 DNS 服务器速度慢时增加 |
- read_ahead_gap 仅限制从服务器读取但尚未传递给客户端的数据窗口。至少有两个缓冲区(客户端到服务器和服务器到客户端方向)以及一个额外的缓冲区用于当前事务所通过的每个 ICAP 服务。
还有间接使用的内存:操作系统有 TCP 连接和文件系统 I/O 的缓冲区。
🔗 我如何知道我的 Squid 进程使用了多少内存?
一种方法是简单地查看系统上的ps输出。对于类 BSD 系统,您可能需要使用-u选项并查看VSZ和RSS字段。
wessels ~ 236% ps -axuhm
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
squid 9631 4.6 26.4 141204 137852 ?? S 10:13PM 78:22.80 squid -NCYs
对于类 SYSV 系统,您可能需要使用-l选项。在解释ps输出时,请务必查看您的ps手册页。报告的数字是以 KB 还是页(通常是 4 KB)为单位,可能并不清楚。
检查内存使用情况的更好方法是使用一个名为top的程序。
last pid: 20128; load averages: 0.06, 0.12, 0.11 14:10:58
46 processes: 1 running, 45 sleeping
CPU states: % user, % nice, % system, % interrupt, % idle
Mem: 187M Active, 1884K Inact, 45M Wired, 268M Cache, 8351K Buf, 1296K Free
Swap: 1024M Total, 256K Used, 1024M Free
PID USERNAME PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND
9631 squid 2 0 138M 135M select 78:45 3.93% 3.93% squid
最后,您可以要求 Squid 进程报告其自身的内存使用情况。这在 Cache Manager 的info页面中可用。您的输出可能因操作系统和 Squid 版本而异,但看起来与此类似:
Resource usage for squid:
Maximum Resident Size: 137892 KB
Memory usage for squid via mstats():
Total space in arena: 140144 KB
Total free: 8153 KB 6%
如果您的 RSS(驻留集大小)值远低于您的进程大小,那么您的缓存性能很可能受到分页的影响。另请参阅 CacheManager
🔗 为什么 Squid 使用如此多的缓存内存?
运行 Squid 的机器似乎使用了大量的内存,“缓存的内存”。
KiB Mem: 4037016 total, 3729152 used, 307864 free, 120508 buffers
KiB Swap: 8511484 total, 0 used, 8511484 free. 2213580 cached Mem
这是 Linux 中的正常行为 - 一旦从磁盘读取的内容就会被缓存到 RAM 中,只要有可用内存。如果 RAM 需要以其他方式使用,内存中的缓存将减少。另请参阅 https://www.linuxatemyram.com/
运行 Squid 的机器会显示大量这种磁盘 I/O 缓存,因为 Squid 缓存包含大量文件并随机访问它们。
🔗 我的 Squid 进程无界增长。
您可能将cache_mem参数设置得太高了。请参阅下面的我能做什么来减少 Squid 的内存使用?。
当进程的大小持续增长,没有趋于平稳或减缓时,通常表明存在内存泄漏。内存泄漏是指一块内存被使用,但在使用完毕后未被释放。
内存泄漏对于像 Squid 这样在其单个进程内完成所有处理的程序来说是一个真正的问题。从历史上看,Squid 曾存在真正的内存泄漏问题。但随着软件的成熟,我们相信几乎所有 Squid 的内存泄漏都已被消除,并且新的泄漏最容易识别。
内存泄漏也可能存在于系统的库中,例如libc.a甚至libmalloc.a。如果您遇到进程大小不断增长的现象,我们建议您首先尝试替代 malloc。
🔗 我将 cache_mem 设置为 XX,但进程却增长了超过这个值!
cache_mem参数**不**指定进程的最大大小。它仅指定用于缓存“热门”(非常受欢迎)响应的内存量。Squid 的实际内存使用量非常依赖于您的cache_dir大小(磁盘空间)和您的传入请求负载。减小cache_mem通常也会减小进程大小,但不一定,还有其他方法可以减少 Squid 的内存使用(见下文)。
另请参阅 Squid 服务器需要多少内存?。
🔗 “总计内存占用”值小于我的 Squid 进程的大小。
我们无法解释 Squid 使用的**所有**内存。这需要过多的代码来跟踪每一字节。我们尽力解释主要的内存用途。
此外,请注意malloc和free函数有自己的开销。需要额外的内存来跟踪哪些块正在使用,哪些是空闲的。此外,大多数操作系统不允许进程缩小。当进程通过调用free释放内存时,总进程大小不会缩小。因此,进程大小实际上代表了您的 Squid 进程已达到的最大大小。
🔗 xmalloc: 无法分配 4096 字节!
像“FATAL: xcalloc: Unable to allocate 4096 blocks of 1 bytes!”这样的消息会在 Squid 无法分配更多内存时出现,并且在大多数操作系统(包括 BSD)上只有两种可能的原因:
- 机器已用尽交换空间
- 进程的最大数据段大小已达到
第一种情况可以使用平台上可用的正常交换空间监控工具(SunOS 上的pstat,BSD 上可能也使用pstat)来检测。
要判断是否是第二种情况,请首先排除第一种情况,然后监视 Squid 进程的大小。如果它在特定大小停止并且还有大量交换空间,那么最大数据段大小无疑已达到。
数据段大小可以由两个因素限制:
- 内核强制的最大值,用户无法超过
- 通过 ulimit 设置的大小,用户可以控制。
Squid 启动时,它会将数据和文件 ulimit 设置为硬限制。如果您在启动 Squid 之前手动调整 ulimit,请确保您设置的是硬限制,而不仅仅是软限制(ulimit 的默认操作是仅更改软限制)。root 可以将软限制提高到硬限制之上。
此命令打印硬限制
ulimit -aH
此命令将数据大小设置为无限制
ulimit -HSd unlimited
BSD/OS
作者:Arjan de Vet
BSD/OS 上数据大小的默认内核限制为 64MB(至少在 3.0 版本上,我正在使用)。
重新编译一个具有更大数据大小设置的内核
maxusers 128
# Support for large inpcb hash tables, e.g. busy WEB servers.
options INET_SERVER
# support for large routing tables, e.g. gated with full Internet routing:
options "KMEMSIZE=\(16*1024*1024\)"
options "DFLDSIZ=\(128*1024*1024\)"
options "DFLSSIZ=\(8*1024*1024\)"
options "SOMAXCONN=128"
options "MAXDSIZ=\(256*1024*1024\)"
有关更多信息,请参阅/usr/share/doc/bsdi/config.n。
在 /etc/login.conf 中我有这个
default:\
:path=/bin /usr/bin /usr/contrib/bin:\
:datasize-cur=256M:\
:openfiles-cur=1024:\
:openfiles-max=1024:\
:maxproc-cur=1024:\
:stacksize-cur=64M:\
:radius-challenge-styles=activ,crypto,skey,snk,token:\
:tc=auth-bsdi-defaults:\
:tc=auth-ftp-bsdi-defaults:
#
# Settings used by /etc/rc and root
# This must be set properly for daemons started as root by inetd as well.
# Be sure reset these values back to system defaults in the default class!
#
daemon:\
:path=/bin /usr/bin /sbin /usr/sbin:\
:widepasswords:\
:tc=default:
# :datasize-cur=128M:\
# :openfiles-cur=256:\
# :maxproc-cur=256:\
这应该为 256MB 的 Squid 进程提供足够的空间。
FreeBSD (2.2.X)
作者:Duane Wessels
过程几乎与上面的 BSD/OS 相同。增加/sys/conf/param.c中的打开文件描述符限制。
int maxfiles = 4096;
int maxfilesperproc = 1024;
在内核配置文件中,例如/sys/conf/i386/CONFIG,增加最大和默认数据段大小。
options "MAXDSIZ=(512*1024*1024)"
options "DFLDSIZ=(128*1024*1024)"
我们还发现有必要增加 mbuf 集的数量。
options "NMBCLUSTERS=10240"
并且,如果您有超过 256MB 的物理内存,您可能需要禁用 BOUNCE_BUFFERS(无论它是什么),因此注释掉这一行。
#options BOUNCE_BUFFERS #include support for DMA bounce buffers
另外,在/etc/login.conf中更新限制。
# Settings used by /etc/rc
#
daemon:\
:coredumpsize=infinity:\
:datasize=infinity:\
:maxproc=256:\
:maxproc-cur@:\
:memoryuse-cur=64M:\
:memorylocked-cur=64M:\
:openfiles=4096:\
:openfiles-cur@:\
:stacksize=64M:\
:tc=default:
编辑文件后,不要忘记运行“cap_mkdb /etc/login.conf”。
🔗 我能做什么来减少 Squid 的内存使用?
如果您的缓存性能因内存限制而受到影响,您可以考虑购买更多内存。但如果这不是一个选项,您可以尝试一些方法:
- 尝试不同的 malloc 库(见下文)。
- 在配置文件中减小cache_mem参数。这控制了有多少“热门”对象保存在内存中。减小此参数对性能影响不大,但如果缓存繁忙,您可能会在cache.log中收到一些警告。
- 在配置文件中关闭memory_pools。这会导致 Squid 通过调用free()来释放未使用的内存,而不是将其保留以备将来使用。总的来说,这是一个坏主意,因为它会导致堆碎片。请改用memory_pools_limit。
- 在配置文件中减小cache_swap_low或cache_dir参数。这将减少 Squid 保留的对象数量。您的整体命中率可能会略有下降,但您的缓存性能将显著提高。
🔗 使用替代 malloc 库
许多用户发现将 Squid 与外部 malloc 库链接可以提高性能和内存利用率。我们推荐 GNU malloc 或 dlmalloc。
🔗 GNU malloc
要使 Squid 使用 GNU malloc,请执行以下简单步骤:
- 下载 GNU malloc 源代码,可从GNU 镜像之一获得。
-
编译它。
% gzip -dc malloc.tar.gz | tar xf - % cd malloc % vi Makefile # edit as needed % make -
将 libmalloc.a 复制到您系统的库目录,并确保将其命名为libgnumalloc.a。
% su # cp malloc.a /usr/lib/libgnumalloc.a -
(可选)将 GNU malloc.h 复制到您系统的包含目录,并确保将其命名为gnumalloc.h。此步骤不是必需的,但如果您执行此操作,Squid 将能够使用mstat()函数在 cachemgr info 页面上报告内存使用统计信息。
# cp malloc.h /usr/include/gnumalloc.h -
重新配置并重新编译 Squid。
% make distclean % ./configure ... % make % make install
在 Squid 的 configure 脚本运行时,请注意其输出。您应该会发现它找到了 libgnumalloc.a,可选地也找到了 gnumalloc.h。
🔗 Squid 服务器需要多少内存?
根据经验法则,Squid 使用大约 10MB RAM/GB 的总 cache_dirs(64 位服务器如 Alpha 上更多),加上您的 cache_mem 设置以及约 10-20MB 的额外内存。建议在您的 Squid 服务器上至少有两倍于此量的物理 RAM。有关 Squid 内存使用情况的更详细讨论,请参阅上面的部分。
除了 Squid 使用的内存外,推荐的额外 RAM 用于操作系统以提高磁盘 I/O 性能,以及用于服务器上运行的其他应用程序或服务。即使是仅运行 Squid 作为唯一 TCP 服务的服务器,也需要最低限度的内存来进行进程管理、日志记录和其他 OS 级例程。
如果您拥有内存不足的服务器和大型磁盘,那么您不一定能使用所有磁盘空间,因为随着缓存的填充,可用的内存将不足,迫使 Squid 交换内存并影响性能。非常大的 cache_dir 总量和不足的物理 RAM + Swap 可能会导致 Squid 完全停止运行。对于更大的缓存,解决方案是获取更多物理 RAM;通过cache_mem分配更多给 Squid 无济于事。
🔗 为什么我的 Squid 进程不能增长到某个大小以上?
作者:Adrian Chadd
许多人运行 Squid 使用超过一千兆字节的内存。以下是一些需要注意的事项:
- 操作系统可能对每个进程可用的内存量设置限制。检查资源限制(PAM 系统下的 /etc/security/limits.conf 或类似文件,‘ulimit’等)。
- 操作系统可能对进程大小有限制。32 位平台有时被“分割”为 2GB 进程/2GB 内核;这可以通过重新编译内核或引导时选项更改为 3GB 进程/1GB 内核。请查阅您的操作系统文档了解具体细节。
- 某些 malloc 实现可能不支持大于 2GB 的内存,例如 dlmalloc。除非您的平台非常糟糕(然后请意识到您将无法使用大于 2GB 的 RAM),否则请勿使用 dlmalloc。
- 确保 Squid 已编译为 64 位二进制文件(使用现代类 Unix 操作系统,您可以使用“file”命令来完成此操作);某些平台可能具有 64 位内核但 32 位用户空间,或者编译器可能默认使用 32 位用户空间。
回到 FAQ 索引
导航: 网站搜索、网站页面、分类、🔼 向上