由Docker垃圾回收机制引发的一场血案

AlstonWilliams 关注

2017.04.01 19:00* 字数 1398 阅读 253评论 0喜欢 0

今天早晨,在我还没睡醒的时候,我们团队中的一名成员就告诉我,我写的微服务中,上传头像的那个没法用.而我在发布之前,已经测试过可以使用了.那这到底是怎么回事呢?

首先,我重新执行了一遍测试过程,发现生产服务器上的微服务上的这个上传头像的接口确实不可用.

然后,我在本地启动了一下微服务,同样测试了一下微服务.发现还是不可用.同时,通过本地打印错误日志,发现错误是在执行保存图片这个写操作的时候:Error: socket hang up.

开始以为是网络故障,但是访问网页以及通过SSH登陆到那台服务器都没有问题.

既然不是网络故障的原因.那到底是什么导致的呢?

通过查看Couchdb容器的日志,我发现了有如下错误日志:

你能从中看出是什么原因吗?错误就隐藏在这中间.

同样,我也是第一次使用CouchDB这个数据库,这个错误栈让我也很懵逼.这是啥意思?

这个看不懂,只好根据Error: socket hang up这个错误来猜了.猜测是打开数据库的连接太多.

顺着这个主线,通过查看CouchDB官方文档,我们发现默认的最大连接数就是1024,有图有真相:

通过curl -X GET http://server_ip:5984/_stats | json_reformat这条命令,我发现,当前数据库的总共HTTP请求才有49个:

也不是达到了最大连接数,导致不能创建新的连接的原因.那是因为什么呢?

还记得上面的错误信息吗?其中有一条是enospc.那这个到底是什么意思呢?No space.没有空间.

这就很容易解释为什么写操作会报错,而读操作却正常运行的原因了.

那为什么会没有空间呢?有两个原因,一是磁盘没有空间了,二是没有Inode可用了.

CouchDB本身是在一个容器中运行,它使用的是主机的资源.所以,很有可能是主机没有空间了.

一个容器中的所有的东西,都是存放在/var/lib/docker文件夹下的相应的文件系统中的.我这里因为是ubuntu系统,所以是存放在/var/lib/docker/aufs/mnt这个目录中.

而这个目录又是挂载到主机的/目录下.

所以,只要/var/lib/docker/aufs/mnt这个目录中存满了东西,主机上的/也就没有空间了.你在主机上进行任何写操作都不会成功.

运行df -h命令,发现果然是/目录中没有空间了.已用100%.

那我们如何来清理/var/lib/docker/aufs/mnt或者/这两个目录,让它们腾出来空间呢?

首先,我想到的是清理掉系统中的不必要的包,使用下面的命令:sudo apt-get autocleansudo apt-get autoremove

然而,并没有什么作用.还是100%.

然后,通过docker ps -a命令,我发现存在着几个已经退出或者被创建但是没有运行的容器.它们占用了一些宝贵的空间.

然后,通过docker rm -f &(docker ps -qf status=exited)和docker rm -f &(docker ps -qf status=created)命令移除那些没用的容器.结果,发现还是不管用.

其实,通过这种方式虽然移除了容器,但是和它们相关的卷并没有移除,我又通过docker volume ls -qf dangling=true | xargs -r docker volume rm命令,移除了那些没用的卷.

上面的删除容器和其相关的卷的命令,我们可以简化为:docker rm -v -f &(docker ps -qf status=exited)

这时候,再通过df -h命令,我们就能看到已用到了82%了:

因为我这里没有没用的镜像,所以就没有进行移除镜像的操作.

我们为什么命题为”由Docker垃圾回收机制引发的一场血案”呢?因为我一直都以为如果容器被移除掉,其对应的卷也会自动被回收.然而事实证明并没有.

从上图中你也可以看到,我们的这台服务器总容量才20G.实际上,我们不应当使用硬盘容量这么小的服务器来运行Docker容器.

清除了一定的空间,再测试上传头像接口,就可以正常使用了.

出了这次事故,我专门去官网看了看Docker的垃圾回收机制,发现目前官网只提供了针对Docker Registry的垃圾回收机制.而且还是需要手动运行bin/registry garbage-collect [–dry-run] /path/to/config.yml这条命令.

实际上,我们也完全可以自己写一个简单的脚本来进行垃圾回收.Github上也提供了相应的工具,有docker-cleanup-volumes以及其他的卷管理工具.这些我也没试过,请自行查看.

Docker垃圾回收机制的更多相关文章

  1. docker 垃圾回收机制

    docker垃圾回收机制 作者: 张首富 时间: 2019-04-10 个人博客: www.zhangshoufu.com QQ群: 895291458 说明 对于Docker来说,存在镜像/容器/存 ...

  2. .net垃圾回收机制编程调试试验

    1. 什么是CLR GC? 它是一个基于引用跟踪和代的垃圾回收器. 从本质上,它为系统中所有活跃对象都实现了一种引用跟踪模式,如果一个对象没有任何引用指向它,那么这个对象就被认为是垃圾对象,并且可以被 ...

  3. JavaScript具有自动垃圾回收机制

    JavaScript具有自动垃圾回收机制 原理: 找出那些不再继续使用的变量,然后释放其占用的内存.   正常的生命周期:     局部变量指在函数执行的过程中存在.而在这个过程中,会为局部变量在栈或 ...

  4. java垃圾回收机制

    1 .垃圾回收机制(GC)垃圾回收就是回收内存中不再使用对象:(1)垃圾回收的步骤:1)查找内存中不再使用的对象:2)释放这些对象所占用的内存:(2)查找内存中不再使用的对象方法:1)引用计数法如果一 ...

  5. 垃圾回收机制GC知识再总结兼谈如何用好GC

    一.为什么需要GC 应用程序对资源操作,通常简单分为以下几个步骤: 1.为对应的资源分配内存 2.初始化内存 3.使用资源 4.清理资源 5.释放内存 应用程序对资源(内存使用)管理的方式,常见的一般 ...

  6. 【转载】Java垃圾回收机制

    原文地址:http://www.importnew.com/19085.html Java垃圾回收机制 说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联 ...

  7. 【转】深入理解 Java 垃圾回收机制

    深入理解 Java 垃圾回收机制   一.垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再 ...

  8. JAVA的垃圾回收机制

    1. 垃圾回收的意义 在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象:而在Java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾.JVM的 ...

  9. Python的垃圾回收机制

    Python的GC模块主要运用了“引用计数”(reference counting)来跟踪和回收垃圾.在引用计数的基础上,还可以通过“标记-清除”(mark and sweep)解决容器对象可能产生的 ...

随机推荐

  1. matlab linux的安装(第二次)

    1 挂载 2 下载jdk,matlab里面那个不行,缺点东西 3 安装 ./install *** 4 激活,非在线 5 license.lic路径在百度云中有 6 运行路径在你安装过程中的选的路径, ...

  2. BZOJ3963: [WF2011]MachineWorks 【CDQ+斜率优化DP】*

    BZOJ3963: [WF2011]MachineWorks Description 你是任意性复杂机器公司(Arbitrarily Complex Machines, ACM)的经理,公司使用更加先 ...

  3. BZOJ5298 CQOI2018 交错序列 【DP+矩阵快速幂优化】*

    BZOJ5298 CQOI2018 交错序列 [DP+矩阵快速幂优化] Description 我们称一个仅由0.1构成的序列为"交错序列",当且仅当序列中没有相邻的1(可以有相邻 ...

  4. 前端(六):JavaScript面向对象之宿主对象

    宿主对象即浏览器提供的对象,主要包括DOM对象和BOM对象. 一.DOM源起 1.SGML.XML和XHTML SGML(标准通用标记语言)是定义使用标签来表示数据的标记语言的语法. - 标签由一个小 ...

  5. iOS 模态框覆盖导航栏

    1.使用window 覆盖 2.试图添加到 如果有一个场景:首页三个tab,要求只覆盖Navigation ,而不影响Tab使用,那么使用window 覆盖就不满足了.      这里我们可以使用如下 ...

  6. Python: 为对象动态添加函数,且函数定义来自一个str

    转自:http://blog.sina.com.cn/s/blog_55a11f330100ab1x.html 在Python中,通常情况下,你只能为对象添加一个已经写好的方法 需求:传入一个str类 ...

  7. STL容器的resize方法

    刚才写DFS程序,为了加个创建DFS树然后再次遍历的功能,把初始化的代码给封装到init()函数里,然后直接调用之后对同样是邻接表表示的DFS树进行DFS. 然后令人诧异的是竟然没有打印结果,调试发现 ...

  8. mysql innodb引擎事务的隔离级别

    一.事务的基本要素(ACID) 1.原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节.事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有 ...

  9. php处理字符串格式的计算表达式

    有时候我们对每一种产品都有一个提成公式,而这个计算提成的公式是以字符串格式存在表中的 当我们用这个计算公式时,他并不像我们写的:$a=2+3*5;这样简单的能计算出结果,而它是个字符串 所以,我们就必 ...

  10. 学习 FPGA之前的基础知识

    在学习一门技术之前往往应该从它的编程语言入手,比如学习单片机时,往往从汇编或者C语言入门.所以不少开始接触FPGA的开发人员,往往是从VHDL或者Verilog开始入手学习的.但小编认为,若能先结合& ...