最近,我开始监控咱们一直在开发的 Node.js 应用程序。一段时间后,我发现它的内存使用率增加缓慢,3 天就增加了 20%。在如下 Node.js 代码中测量了内存使用状况。docker
const os = require("os"); const total = os.totalmem(); const free = os.freemem(); const usage = ((free - total) / total) * 100;
因此,它们基本上来自操做系统,在这种状况下是Docker 上的Alpine Linux。幸运的是,我还记录了应用程序进程的内存使用状况,但它们并无增长。那么为何操做系统内存使用量会增长呢?缓存
我使用了top命令Shift+m(按内存使用状况排序)并比较了长时间运行的服务器上的进程和新部署的服务器上的进程。双方的流程几乎相同。惟一的区别是,buffers而且cached Mem在长期运行的状况下很高。服务器
通过一些研究或谷歌搜索后,我得出结论,这不是问题。当应用程序进程要求更多内存时,大部分buffers和cached Mem被放弃。网络
其实free -m命令提供了一行used,并free采起缓冲区和缓存的考虑。app
$ free -m total used free shared buffers cached Mem: 3950 285 3665 183 12 188 -/+ buffers/cache: 84 3866 Swap: 1896 0 1896
那么,它们到底是什么?根据的手册/proc/meminfo,这是一个伪文件和 的数据源free,top还有朋友:ui
Buffers %lu Relatively temporary storage for raw disk blocks that shouldn't get tremendously large (20MB or so). Cached %lu In-memory cache for files read from the disk (the page cache). Doesn't include SwapCached.
我仍然不肯定到底Buffers包含什么,但它包含文件的元数据等,并且它的大小相对微不足道。Cached包含缓存的文件内容,称为页面缓存。操做系统保留页面缓存,而 RAM 有足够的可用空间。这就是为何即便进程没有泄漏内存,内存使用量也在增长。操作系统
若是您有兴趣,/proc/meminfo 输出中的 Buffers 和 Cached 列有什么区别?在 Quora 上有关于Buffers和的更多详细信息Cached。code
那么,咱们应该使用free + buffers + cached? /proc/meminfo有一个更好的指标,称为MemAvailable。排序
MemAvailable %lu (since Linux 3.14) An estimate of how much memory is available for starting new applications, without swapping. $ cat /proc/meminfo MemTotal: 4045572 kB MemFree: 3753648 kB MemAvailable: 3684028 kB Buffers: 13048 kB Cached: 193336 kB ...
它的背景在 Linux Kernel中的提交中获得了很好的解释,但本质上它排除了不可释放的页面缓存并包括可回收的平板内存。Linux v4.12-rc2 中的当前实现看起来仍然几乎相同。进程
free -m有available列的一些实现。例如,在 Boot2Docker 上:
$ free -m total used free shared buff/cache available Mem: 3950 59 3665 183 226 3597 Swap: 1896 0 1896
它也能够经过--mem-avail标志在 AWS CloudWatch 指标上使用。
个人另外一个问题是“Docker 中的这些指标是否相同?”。在深刻探讨这个问题以前,让咱们检查一下 docker 是如何工做的。
根据Docker 概述:底层技术,Docker 容器中的进程直接在其主机操做系统中运行,没有任何虚拟化,但因为这些 Linux 内核特性,它们与主机操做系统和其余容器有效隔离:
命名空间:隔离 PID、主机名、用户 ID、网络访问、IPC 等。
默认状况下,Docker 容器没有资源限制。因此,若是你在一台主机上运行一个容器,而且不限制容器的资源使用,这就是个人状况,容器的“空闲内存”与主机操做系统的“空闲内存”是同样的。
若是您想从容器外部监控 Docker 容器的内存使用状况,这很容易。您可使用docker stats.
$ docker stats CONTAINER CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS fc015f31d9d1 0.00% 220KiB / 3.858GiB 0.01% 1.3kB / 0B 0B / 0B 2
可是,若是您想获取容器中的内存使用状况或获取更详细的指标,就变得复杂了。Linux 容器内的内存详细描述了困难。
/proc/meminfo和sysinfo,由Node.js使用os.totalmem()和使用os.freemem(),不是孤立的,若是您在 Docker 容器中使用top和等普通实用程序,您将得到主机操做系统的指标free。
要获取特定于 Docker 容器的指标,您能够在/sys/fs/cgroup/memory/. 不过,它们并未根据Linux 容器内的内存进行标准化。
$ cat /sys/fs/cgroup/memory/memory.usage_in_bytes 303104 $ cat /sys/fs/cgroup/memory/memory.limit_in_bytes 9223372036854771712
memory.limit_in_bytes若是没有限制,则返回一个很是大的数字。在这种状况下,您可使用/proc/meminfo或使用它的命令找到主机操做系统的总内存。
这是一段比我最初想象的更长的旅程。个人要点是: