RabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现。 AMQP :Advanced Message Queue,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。 RabbitMQ 最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。具体特点包括:
如今,软件通常会作为一种服务来交付,它们被称为网络应用程序,或软件即服务(SaaS)。12-Factor 为构建如下的 SaaS 应用提供了方法论:
这套理论适用于任意语言和后端服务(数据库、消息队列、缓存等)开发的应用程序。
本文的贡献者参与过数以百计的应用程序的开发和部署,并通过 Heroku 平台间接见证了数十万应用程序的开发,运作以及扩展的过程。
本文综合了我们关于 SaaS 应用几乎所有的经验和智慧,是开发此类应用的理想实践标准,并特别关注于应用程序如何保持良性成长,开发者之间如何进行有效的代码协作,以及如何 避免软件污染 。
我们的初衷是分享在现代软件开发过程中发现的一些系统性问题,并加深对这些问题的认识。我们提供了讨论这些问题时所需的共享词汇,同时使用相关术语给出一套针对这些问题的广义解决方案。本文格式的灵感来自于 Martin Fowler 的书籍: Patterns of Enterprise Application Architecture , Refactoring 。
任何 SaaS 应用的开发人员。部署和管理此类应用的运维工程师。
作为一名苦逼运维,写软件部署文档时必不可少的一件事情,可以说:文档的好坏决定了运维能力的高低。
那我们在写部署文档的时候,要做哪些事情,要写关于软件的哪些步骤呢,本人结合自己常用的一些流程,整理了下列的模板,仅供大家参考!
作为一个苦逼运维人,在学习一门新软件的时候,要经历过哪些阶段,或者说要做哪些事情,才能算真的了解这个软件呢?下面就个人经历而言整理了一些步骤。
系统包
管理方式部署源码包
编译方式部署docker
容器部署docker-compose
方式部署kubernetes
方式部署单机
部署集群
部署centos
debian
安装软件
的存放目录软件日志
的存放目录软件数据
的存放目录软件进程
管理方式(service
,systemd
,supervistor
)软件日志
的切割方式shell
方式进行自动化部署ansible
方式进行自动化部署监控指标
数据收集zabbix
传统方式监控,并制定监控报警模板prometheus
方式监控,并制定监控报警模板grafana
展示监控面板短信
邮件
部署规模
,分别进行备份软件的数据故障场景
,对备份数据进行恢复
平滑
升级停机
升级部署方式
,分别进行升级版本操作宿主机
,分别进行升级版本操作宿主机
,分别进行相关优化操作部署规模
,分别进行相关优化操作学习途径的话
可通过下列方式去寻找软件相关的知识,帮助各位快速学习。
google.com
搜索软件的一切信息,如 pdf
,ppt
,cookebook
,awesome
,cheatsheet
,install
,gitbook
,问题
, Bug
亚马逊
京东
/当当
/闲鱼二手
商城购买实体书微信读书
技术名称 + cookbook
/ ebook
google
/baidu
/微信公众号
/个人博客
等等。https://www.slideshare.net/ | https://myslide.cn/ 中分享的ppt |
github
github.com
中搜索软件的awesome
,其整理了软件相关的知识点及工具清单。github.com
中搜索软件的cheatsheet
,其整理了软件相关的常用命令。github.com
中搜索软件的issues
,其整理了用户使用的问题以及软件的bug。写在最后
当然你大可不必将上面的每一种情况都操作一遍
,但是你一定要将上列的步骤都要做一遍
。
这真是最后了
最后,好记性不如烂笔头,统统都要记笔记,无论你记在哪里。都要记笔记。
这个要切记,不要怕麻烦!
最后,好记性不如烂笔头,统统都要记笔记,无论你记在哪里。都要记笔记。
这个要切记,不要怕麻烦!
最后,好记性不如烂笔头,统统都要记笔记,无论你记在哪里。都要记笔记。
这个要切记,不要怕麻烦!
鲁棒性
鲁棒是Robust的音译,也就是健壮和强壮的意思。它也是在异常和危险情况下系统生存的能力。比如说,计算机软件在输入错误、磁盘故障、网络过载或有意攻击情况下,能否不死机、不崩溃,就是该软件的鲁棒性。
稳定系统
当一个实际的系统处于一个平衡的状态时(就相当于小球在木块上放置的状态一样)如果受到外来作用的影响时(相当于上例中对小球施加的力),系统经过一个过渡过程仍然能够回到原来的平衡状态,我们称这个系统就是稳定的,否则称系统不稳定。一个控制系统要想能够实现所要求的控制功能就必须是稳定系统。
在使用 supervisor 管理应用进程的时候,我希望有个程序或者脚本来检测这些应用是否正常运行(虽然supervisor可以根据错误重启进程,但有些时候,程序假死,程序占用资源过多的场景下,supervisor是没办法的),类似 k8s 中的存活检测,在检测到不正常的时候,会触发一些动作,类似于故障治愈的功能。
要求
OCI 定义了容器运行时标准,runC 是 Docker 按照开放容器格式标准(OCF, Open Container Format)制定的一种具体实现。
runC 是从 Docker 的 libcontainer 中迁移而来的,实现了容器启停、资源隔离等功能。Docker 默认提供了 docker-runc 实现,事实上,通过 containerd 的封装,可以在 Docker Daemon 启动的时候指定 runc 的实现。
从Docker 1.11之后,Docker Daemon被分成了多个模块以适应OCI标准。拆分之后,结构分成了以下几个部分。
从图中可以看出,docker 对容器的管理和操作基本都是通过 containerd 完成的。 那么,containerd 是什么呢?
Containerd 是一个工业级标准的容器运行时,它强调简单性、健壮性和可移植性。Containerd 可以在宿主机中管理完整的容器生命周期:容器镜像的传输和存储、容器的执行和管理、存储和网络等。
详细点说,Containerd 负责干下面这些事情:
runC
运行容器(与 runC
等容器运行时交互)注意:Containerd 被设计成嵌入到一个更大的系统中,而不是直接由开发人员或终端用户使用。
内存映射,其实就是将虚拟内存地址映射到物理内存地址。为了完成内存映射,内核为每个进程都维护了一张页表,记录虚拟地址与物理地址的映射关系。
当进程访问的虚拟地址在页表中查不到时,系统会产生一个缺页异常
为决页表项过多的问题,Linux 提供了两种机制,也就是多级页表和大页(HugePage)
分配
对小块内存(小于 128K),C 标准库使用 brk() 来分配,也就是通过移动堆顶的位置来分配内存。这些内存释放后并不会立刻归还系统,而是被缓存起来,这样就可以重复使用。
brk() 方式的缓存,可以减少缺页异常的发生,提高内存访问效率。不过,由于这些内存没有归还系统,在内存工作繁忙时,频繁的内存分配和释放会造成内存碎片。
而大块内存(大于 128K),则直接使用内存映射 mmap() 来分配,也就是在文件映射段找一块空闲内存分配出去。
mmap() 方式分配的内存,会在释放时直接归还系统,所以每次 mmap 都会发生缺页异常。在内存工作繁忙时,频繁的内存分配会导致大量的缺页异常,使内核的管理负担增大。这也是 malloc 只对大块内存使用 mmap 的原因。
在内核空间,Linux 则通过 slab 分配器来管理小内存。
回收内存
回收缓存,比如使用 LRU(Least Recently Used)算法,回收最近使用最少的内存页面;
回收不常访问的内存,把不常用的内存通过交换分区直接写到磁盘中;
杀死进程,内存紧张时系统还会通过 OOM(Out of Memory),直接杀掉占用大量内存的进程。
直接内存回收,尽可能地满足新内存请求,进而回收一部分内存
kswapd0内核线程定时回收内存
kswapd0 定期扫描内存的使用情况,并根据剩余内存落在这三个阈值的空间位置,进行内存的回收操作。
剩余内存小于页最小阈值,说明进程可用内存都耗尽了,只有内核才可以分配内存。 剩余内存落在页最小阈值和页低阈值中间,说明内存压力比较大,剩余内存不多了。这时 kswapd0 会执行内存回收,直到剩余内存大于高阈值为止。 剩余内存落在页低阈值和页高阈值中间,说明内存有一定压力,但还可以满足新内存请求。 剩余内存大于页高阈值,说明剩余内存比较多,没有内存压力。
通过内核选项 /proc/sys/vm/min_free_kbytes来设置页低阈值,而其他两个阈值,都是根据页最小阈值计算生成的pages_low = pages_min*5/4, pages_high = pages_min*3/2
NUMA (Non-UniformMemory Access) 架构下的内存回收。
/proc/sys/vm/zone_reclaim_mode 来调整numa node的内存回收策略
默认的 0 ,也就是刚刚提到的模式,表示既可以从其他 Node 寻找空闲内存,也可以从本地回收内存。 1、2、4 都表示只回收本地内存,2 表示可以回写脏数据回收内存,4 表示可以用Swap 方式回收内存。
Buffers 是内核缓冲区用到的内存,对应的是 /proc/meminfo 中的 Buffers 值。 Cache 是内核页缓存和 Slab 用到的内存,对应的是 /proc/meminfo 中的 Cached 与SReclaimable 之和。
Buffers 是对原始磁盘块的临时存储,也就是用来缓存磁盘的数据,通常不会特别大(20MB 左右)。这样,内核就可以把分散的写集中起来,统一优化磁盘的写入,比如可以把多次小的写合并成单次大的写等等。 Cached 是从磁盘读取文件的页缓存,也就是用来缓存从文件读取的数据。这样,下次访问这些文件数据时,就可以直接从内存中快速获取,而不需要再次访问缓慢的磁盘。
SReclaimable 是 Slab 的一部分。Slab 包括两部分,其中的可回收部分,用SReclaimable 记录;而不可回收部分,用 SUnreclaim 记录。
Buffer 是对磁盘数据的缓存,而 Cache 是文件数据的缓存,它们既会用在读请求中,也会用在写请求中。
所谓缓存命中率,是指直接通过缓存获取数据的请求次数,占所有数据请求次数的百分比。命中率越高,表示使用缓存带来的收益越高,应用程序的性能也就越好。
堆内存由应用程序自己来分配和管理。除非程序退出,这些堆内存并不会被系统自动释放,而是需要应用程序明确调用库函数 free() 来释放它们。如果应用程序没有正确释放堆内存,就会造成内存泄漏。
内存泄漏的危害非常大,这些忘记释放的内存,不仅应用程序自己不能访问,系统也不能把它们再次分配给其他应用。
属于可回收内存的缓存和缓冲区,是文件页
被应用程序修改过,并且暂时还没写入磁盘的数据就是脏页
应用程序动态分配的堆内存被称为匿名页
对文件页的回收,当然就是直接回收缓存,或者把脏页写回磁盘后再回收。 而对匿名页的回收,其实就是通过 Swap 机制,把它们写入磁盘后再释放内存。
Swap 说白了就是把一块磁盘空间或者一个本地文件(以下讲解以磁盘为例),当成内存来使用。它包括换出和换入两个过程。
/proc/sys/vm/swappiness 选项,用来调整使用 Swap 的积极程度。
swappiness 的范围是 0-100,数值越大,越积极使用 Swap,也就是更倾向于回收匿名页;数值越小,越消极使用 Swap,也就是更倾向于回收文件页。
在内存资源紧张时,Linux 会通过 Swap ,把不常访问的匿名页换出到磁盘中,下次访问的时候再从磁盘换入到内存中来。你可以设置 /proc/sys/vm/min_free_kbytes,来调整系统定期回收内存的阈值;也可以设置/proc/sys/vm/swappiness,来调整文件页和匿名页的回收倾向。
内存性能指标
├── 系统内存指标
│ ├── 已用内存
│ ├── 剩余内存
│ ├── 可用内存
│ ├── 缺页异常
│ │ ├── 主缺页异常
│ │ └── 次缺页异常
│ ├── 缓存/缓冲区
│ └── Slabs
├── 进程内存指标
│ ├── 虚拟内存(VSS)
│ ├── 常驻内存(RSS)
│ ├── 按比例分配共享内存后的物理内存(PSS)
│ ├── 独占内存(USS)
│ ├── 共享内存
│ ├── SWAP内存
│ └── 缺页异常
│ │ ├── 主缺页异常
│ │ └── 次缺页异常
└── SWAP
├── 已用空间
├── 剩余空间
├── 换入速度
└── 换出速度
系统的已用内存、剩余内存、共享内存、可用内存、缓存和缓冲区的用量
进程内存使用情况,比如进程的虚拟内存、常驻内存、共享内存以及 Swap 内存等。
缺页异常
Swap 的使用情况,比如 Swap 的已用空间、剩余空间、换入速度和换出速度等。
案例
在缓存和缓冲区的原理篇中,
我们通过 proc 文件系统,找到了内存指标的来源; 并通过 vmstat,动态观察了内存的变化情况。与 free 相比,vmstat 除了可以动态查看内存变化,还可以区分缓存和缓冲区、Swap 换入和换出的内存大小。
为了弄清楚缓存的命中情况,我们又用了 cachestat,查看整个系统缓存的读写命中情况,并用 cachetop 来观察每个进程缓存的读写命中情况。
在内存泄漏的案例中,我们用 vmstat,发现了内存使用在不断增长,又用memleak,确认发生了内存泄漏。通过 memleak 给出的内存分配栈,我们找到了内存泄漏的可疑位置。
在 Swap 的案例中,我们用 sar 发现了缓冲区和 Swap 升高的问题。通过cachetop,我们找到了缓冲区升高的根源;通过对比剩余内存跟 /proc/zoneinfo 的内存阈,我们发现 Swap 升高是内存回收导致的。案例最后,我们还通过 /proc 文件系统,找出了 Swap 所影响的进程。
内存指标 | 性能工具 |
---|---|
系统已用、可用、剩余内存 | free vmstat sar /proc/meminfo |
进程虚拟内存、常驻内存、共享内存 | ps top |
进程内存分布 | pmap |
进程Swap换出内存 | top /proc/pid/status |
进程缺页异常 | top |
系统换页情况 | sar free vmstat |
缓存/缓冲区用量 | sar cachestat |
缓存/缓冲区命中率 | cachetop free |
SWAP已用空间和剩余空间 | sar |
Swap换入换出 | vmstat memleak |
内存泄漏检测 | valgrind |
指定文件的缓存大小 | pcstat |
根据工具查指标
性能工具 | 内存指标 |
---|---|
free /proc/meminfo |
系统已用、可用、剩余内存以及缓存和缓冲区的使用量 |
top ps |
进程虚拟、常驻、共享内存以及缺页异常 |
vmstat | 系统剩余内存、缓存、缓冲区、换入、换出 |
sar | 系统内存换页情况、内存使用率、缓存和缓冲区用量以及Swap使用情况 |
cachestat | 系统缓存和缓冲区的命中率 |
cachetop | 进程缓存和缓冲区的命中率 |
slabtop | 系统Slab缓存使用情况 |
/proc/pid/status | 进程Swap内存等 |
/proc/pid/smaps | 进程地址空间和内存状态 |
pmap | 进程内存错误检查器,用来检测内存初始化、 |
valgrind | 泄漏、越界访问等各种内存错误 |
memleak | 内存泄漏检测 |
pcstat | 查看指定文件的缓存情况 |
快速分析内存的性能瓶颈
分析流程图
显示Linux系统中空闲的、已用的物理内存及swap内存,及被内核使用的buffer
常用命令
free
free -m
free -g
指标含义
total:总计物理内存的大小。
used:已使用多大。
free:可用有多少。
Shared:多个进程共享的内存总额。
Buffers/cached:磁盘缓存的大小。
available
提供了整个操作系统缓存的读写命中情况。 需要安装 bcc 软件包 。
常用命令
cachestat 1 3
TOTAL MISSES HITS DIRTIES BUFFERS_MB CACHED_MB
2 0 2 1 17 279
2 0 2 1 17 279
2 0 2 1 17 279
指标含义
TOTAL 表示总的 I/O 次数
MISSES 表示缓存未命中的次数
HITS 表示缓存命中的次数
DIRTIES 表示新增到缓存中的脏页数
BUFFERS_MB 表示 Buffers 的大小,以 MB 为单位
CACHED_MB 表示 Cache 的大小,以 MB 为单位
提供了每个进程的缓存命中情况。 需要安装 bcc 软件包 。
cachetop
11:58:50 Buffers MB: 258 / Cached MB: 347 / Sort: HITS / Order: ascending
PID UID CMD HITS MISSES DIRTIES READ_HIT% WRITE_HIT%
13029 root python 1 0 0 100.0% 0.0%
指标含义
默认按照缓存的命中次数(HITS)排序,
HITS 表示缓存命中的次数
MISSES 表示缓存未命中的次数
DIRTIES 表示新增到缓存中的脏页数
READ_HIT 表示读的缓存命中率
WRITE_HIT 表示写的缓存命中率
以实时的方式显示内核“slab”缓冲区的细节信息
常用命令
slabtop
slabtop -d 1 # 1秒钟刷新一次数据
slabtop -s c # 按照cache size排序
用于显示一个或多个进程的内存状态
常用命令
pmap $PID
名称解释
Address: 内存开始地址
Kbytes: 占用内存的字节数(KB)
RSS: 保留内存的字节数(KB)
Dirty: 脏页的字节数(包括共享和私有的)(KB)
Mode: 内存的权限:read、write、execute、shared、private (写时复制)
Mapping: 占用内存的文件、或[anon](分配的内存)、或[stack](堆栈)
Offset: 文件偏移
Device: 设备名 (major:minor)
valgrind是一个专业的程序优化和内存调试工具集。
常用的工具包括
memcheck
,cachegrind
,callgrind
,massif
,helgrind
和drd
。
安装
yum -y install make gcc autoconf automake
wget https://sourceware.org/pub/valgrind/valgrind-3.15.0.tar.bz2
tar -xjvf valgrind-3.15.0.tar.bz2
cd valgrind-3.15.0
./autogen.sh
./configure
make
make install
valgrind --version
常用命令
valgrind # 使用Memcheck(默认)工具显示program对内存使用情况的诊断
valgrind --leak-check=full --show-leak-kinds=all # 使用Memcheck详细输出program的所有可能的内存泄漏
valgrind --tool=cachegrind # 使用Cachegrind工具来分析和记录program的CPU缓存操作
valgrind --tool=massif --stacks=yes # 使用Massif工具来分析和记录program的堆内存和堆栈使用情况
memleak跟踪内存分配和回收请求,收集每次分配的调用栈。 属于bcc套件
/usr/share/bcc/tools/memleak -a -p ${pid}
可以查看某个文件是否被缓存 https://github.com/tobert/pcstat
pcstat /bin/ls
参考 极客时间专栏《Linux 性能优化实战》