
【重磅直播预告】【直播主题】:数据治理实践与应用【讲师简介】:泓峥,曾辗转多个行业与领域,擅长数据分析、数据仓库与数据架构等,2020年6月加入混合云,目前负责数字政务江浙沪区域的运维服务工作。【直播时间】:2021.03.11 19:00-20:00【直播简介】:直播分为两部分,分别为数据治理理论、数据治理的关键点与落地。【阿里云SRE技术学院】集结了阿里云技术服务团队的精英导师及技术专家,定期组织群直播,分享行业前沿干货、趣谈人生感悟与思索,感兴趣的小伙伴扫描下方二维码加入我们吧!快来与业界大咖零距离交流互动。
1. 背景谈及linux内存,很多时候,我们会关注free,top等基础命令。当系统遇到异常情况时,内存问题的根因追溯,现场诊断时,缺乏深层次的debug能力。本篇幅不做深层讨论,能把当前系统的问题描述清楚,是每个SRE应该具备的最基础能力。2. free2.1 free命令原理free是通过查看 /proc/meminfo 来获取内存的使用情况。但是 /proc/meminfo 这个文件又是怎么来的?我们先了解下 /proc 目录:/proc 是一个虚拟文件系统,该目录下的所有文件都是伪文件,该类文件只存在于内存中,并不占用空间——使用 du -sh 即可验证,该模具路下的磁盘占用都是0。/proc 下的所有文件都是内核调用proc_create() 接口来创建的虚拟条目。/proc 中的文件,大多反馈系统信息的实时情况(进程、内存、cpu、设备信息等)。结论: /proc/meminfo 是 /proc 文件系统下保存你内存相关信息的"伪文件"。2.2 命令输出简介每个发行版输出都有一定差异,我们以debian8 4.19.x发行版为例。root@4f996feeb851:~# free -m total used free shared buffers cached Mem: 1991 1909 81 4 155 836 -/+ buffers/cache: 917 1073 Swap: 1023 1 1022大部分的命令输出意思,大家可以在man文档中找到解析,这里不做赘述。used: 已使用的内存 used = total - free -buffers -cachedfree: 未使用的内存 memFree & swapFree in /proc/meminfoshared: tmpfs使用的内存 shmem in /proc/meminfobuffers:被内核缓冲去使用的内存cached: 被页缓存和slabs使用的内存buffers/cache: 表示buffers和cache的总和swap: 交换分区的使用量2.3 buffer和cache会使用内存吗?答案是肯定的,先来了解下buffer和cache。cache(缓存)官方定义是用来弥补高速设备和低速设备之间的访问速度不匹配而预留的一段空间,用来加快资源的访问。 简单讲就是读的更快。buffer(缓冲)是为了做资源写入整形,计算机遇到大量的“小规模IO”时,会将其整形为少量的“大规模IO”,降低写入次数。从而达到“写资源”合理利用的效果。然而,free命令所展示的buffer和cache 有点狭义的意思——free展示的buffer表示 块设备所占用的缓存 、free展示的cache表示普通文件占用的the page cache(缓存页) 。总之,buffer和cache使用的内存都是用来加速Linux读写性能,如果有新的进程需要内存,系统会将buffer和cache占用的内存回收,并重新分配给进程使用。2.4 其他内存概念RSS & VSZ & PSS & USSRSS(Resident Set Size):进程实际使用的物理内存大小,包括sharedMem。VSZ(Virtual Memory Size):进程所有能够访问到的内存大小,包括因为缺页中断,被swap出去的内存大小,以及sharedMem。PSS(Proportional Set Size):按照比例将内存的大小加到RSS中。USS(Unique Set Size):进程独占的物理内存大小。usedMem分为 active & inactiveactive:表示这部分的内存正在被某个特定的进程使用,不太可能被收回。inactive:表示这部分内存是被分配到某个不在running状态的进程,有可能会被回收。Linux会维护一个LRU List用来管理活动页和非活动页的回收。 简单讲, 越接近该List的末尾,该页面被回收的概率就越大,反之,越接近列首,则更不易被回收。 linux内核会维护两类LRUList——active list和inactive list,刚访问过的页面放入active list,长时间未访问的页面放入inactive list,内核线程kswapd会定期将active list中的页面移至 inactive list中。如果系统的inactive的内存过大,可以通过如下操作对其做回收。sync; echo 3 > /proc/sys/vm/drop_caches3. 虚拟内存现代x86系统,计算机能够使用的内存会大于其物理内存的上限,依靠的就是虚拟内存机制。Linux支持虚拟内存机制和实模式机制。 实模式下,计算机会直接申请物理内存, 虚拟内存机制下,系统会把磁盘当成内存的扩展,已增加可使用的内存大小。并通过映射map的机制,来保存和物理内存的真实对应关系。在磁盘和内存之间传送Page的活动叫做swapping或者页面调度(paging),被用作虚拟内存的磁盘分区称为swap。可以通过在线添加swap的方式临时缓解内存不足的问题,但一般不能直接作在线减少swap的操作,很有可能导致进程的crash。具体swap配置方式见5.1swap相关配置。4. OOM1.What is OOM?Out Of Memory Killer 是 Linux 的一种系统保护机制,在系统内存紧张时,kill掉某些进程防止系统卡死。系统通过打分机制,来实施对进程的杀死操作。默认机制是通过扫描所有进程的内存占用,cpu占用等因素,然后打分 (badness),分数越高,进程被kill的优先级就越高。 2.哪些行为会让系统对进程进行打分?进程使用fork(2)调用,创建众多子进程时,会加分(+)进程已经运行了很长时间,或者和使用了大量的CPU时间,会减分(-)进程的nice值如果比较低,会加分(+)进程如果是特权进程(privileged),会减分(-)进程如果对硬件设备进行直接访问,会减分(-)3.在哪儿可以看到进程的打分?/proc/<pid>/oom_score 4.手动调整分数/proc//oom_adj 该文件可以用于调整在oom发生时,哪些进程应该被kill,范围-16 -- +15 ,默认值为0, 特殊值-17:表示进程永远不会被kill。5.我怎么知道系统有没有触发过OOM?/var/log/messages 、 /var/log/syslog 系统日志或者 dmesg 系统日志诊断工具等都能够找到网图如下:5. 内存相关配置5.1 swap相关配置通过调节系统参数,来告诉计算机使用swap分区的权重1. 简介 swappiness范围0-100,默认60 0: 表示禁止使用swap 60: 默认 100: 疯狂使用swap 2. 操作方法 # sysctl vm.swappiness=VALUE # sysctl vm.swappiness=20 或者 # echo VALUE > /proc/sys/vm/swappiness # echo 30 > /proc/sys/vm/swappiness通过在线增加swap分区大小,临时控制内存泄露,内存不够用等异常。1. 需要root用户 2. 创建存储文件 # dd if=/dev/zero of=/home/swap2G bs=1024 count=2M 3. 安全设置 # chown root:root /home/swap2G # chmod 0600 /home/swap2G 4. 创建liunx交换分区 # mkswap /home/swap2G 5. enable 交换分区 # swapon /home/swap2G 6. 更新fstab文件【注意: 部分操作系统不需要】 # vim /etc/fstab /home/swap2G none swap sw 0 0 7. 检查是否生效 #free -m 8. 卸载swap分区 # swapoff /home/swap2G5.2 缓存相关sync; echo 3 > /proc/sys/vm/drop_caches 0:不释放 1:释放页缓存 2:释放 dentries 和 inodes 3:释放所有缓存5.3 OOM相关vm.panic_on_oom是否在触发 oom 机制时触发 kernel panic。0表示关闭(推荐),1表示打开。 kernel panic是指计算机遇到了致命的错误,并且他不知道该怎么处理时的一种动作——可以类比windows的蓝屏。 我们当然不希望每次计算机在oom时就直接蓝屏。推荐设置为0vm.overcommit_kbytes:用于限制进程能够申请的最大内存,0表示不设置,如果设置其他数值,比如400,则进程能够申请到的最大内存为 swap+400kBytesvm.overcommit_ratio:定义了进程可以使用的最大内存(百分比模式),默认为50。表示配置50之后,进程不允许申请超过 swap + 50% * 物理内存总量 以上的内存vm.oom_kill_allocating_task (Linux 2.6.24+支持)这在内存不足的情况下启用或禁用杀死OOM触发任务。0表示禁用(默认),1表示启用。可以理解为oom机制的开关,默认为禁用——表示要让oom触发器正常执行。其他有兴趣的话,可以自行man proc6. 结语如有纰漏欢迎指正。我们是阿里云智能全球技术服务-SRE团队,我们致力成为一个以技术为基础、面向服务、保障业务系统高可用的工程师团队;提供专业、体系化的SRE服务,帮助广大客户更好地使用云、基于云构建更加稳定可靠的业务系统,提升业务稳定性。我们期望能够分享更多帮助企业客户上云、用好云,让客户云上业务运行更加稳定可靠的技术,您可用钉钉扫描下方二维码,加入阿里云SRE技术学院钉钉圈子,和更多云上人交流关于云平台的那些事。
1. DataX定义首先简单介绍下datax是什么。DataX是阿里巴巴集团内被广泛使用的离线数据同步工具/平台,实现包括 MySQL、Oracle、SqlServer、Postgre、HDFS、Hive、ADS、HBase、TableStore(OTS)、MaxCompute(ODPS)、DRDS 等各种异构数据源之间高效的数据同步功能。2. DataX 商业版本阿里云DataWorks数据集成是DataX团队在阿里云上的商业化产品,致力于提供复杂网络环境下、丰富的异构数据源之间高速稳定的数据移动能力,以及繁杂业务背景下的数据同步解决方案。目前已经支持云上近3000家客户,单日同步数据超过3万亿条。DataWorks数据集成目前支持离线50+种数据源,可以进行整库迁移、批量上云、增量同步、分库分表等各类同步解决方案。2020年更新实时同步能力,支持10+种数据源的读写任意组合。提供MySQL,Oracle等多种数据源到阿里云MaxCompute,Hologres等大数据引擎的一键全增量同步解决方案。关于datax的git地址,可参考文后资料了解详情[1]。2.1 应用案例接下来介绍下我们在两个项目上的应用案例。2.1.1 案例一 通过datax协助分析数据同步链路客户某oracle数据库在迁移上云过程中,使用了某封装好的产品,但是传输效率一直很低,只有6M/s。客户一直怀疑是云内vpc网络瓶颈或rds数据库瓶颈导致,但是实际上,云内网络以及数据库整体处于非常低的负载状态。由于客户侧的传输工具我们不方便直接拿来测试,所以在ecs上临时部署了datax,来做分析和对照测试;测试结果如下图所示。图1:测试结果常用的优化参数介绍如下:1.通道(channel)--并发通过测试可知,channel的设置对传输效率的影响较为明显,上述实验中,所有设置为1的,即没有并发的情况下,同步速度均为8.9M/s;将该设置调高之后,速率明显倍增,但增大到一定程度后,瓶颈点就转到其他配置了;2.切片(splitpk)Git官方介绍如下:描述:MysqlReader进行数据抽取时,如果指定splitPk,表示用户希望使用splitPk代表的字段进行数据分片,Datax因此会启动并发任务进行数据同步,这样可以大大提高数据同步的效能。推荐splitPk用户使用表主键,因为表主键通常情况下比较均匀,因此切分出来的分片也不容易出现数据热点。目前splitPk仅支持整形数据切分,不支持浮点、字符串、日期等其他类型。如果用户指定其他非支持类型,MysqlReader将报错。如果splitPk不填写,包括不提供splitPk或者splitPk值为空,DataX视作使用单通道同步该表数据。必选:否默认值:空实际上,由测试结果可知,切片是要配合channel来使用的,如果只开了splitpk,但是channel的配置为1,同样不会有并发的效果;3.BatchsizeGit官方介绍如下:描述:一次性批量提交的记录数大小,该值可以极大减少DataX与Mysql的网络交互次数,并提升整体吞吐量。但是该值设置过大可能会造成DataX运行进程OOM情况。必选:否默认值:1024现场的实际测试效果不明显,主要原因是数据量较小,1c1g配置时,适当提高batch可以提升同步速度。其他还有很多参数,有待小伙伴们去逐一发掘,或者下次我们用到再给大家分享;由测试结果可知,项目使用的工具只能同步6m的速率,肯定是远远不足的,性能瓶颈既不在网络上,也不在数据库上,我们只做了部分测试,就发现4c16g的数据库轻轻松松就能达到27M的同步速率。2.1.2 案例二 datax在数据同步实战中的应用该案例是客户两朵云之间的数据迁移,客户新建了一朵云,需要把前一朵云上的数据迁移过去;方案如下:图2:方案2.2 部署方式Datax本身无自动集群化部署,需要逐台手工部署;15台v2的物理机,空余内存均在150G左右。(因为V2集群即将下线,上述产品无业务,所以利用了闲置的物理机,在物理条件不具备时,可以采用ecs或其他虚拟机。)机器要求:同步任务启动会占用较多内存,测试平均1个任务占用10G内存(大表);单台150G内存可以支持15个并发任务;2.3 同步方式2.3.1 数据特点分类项目数总数据量1T以上project7个97T1T以下project77个15T历史记录表:历史数据,项目数不多,但占用了80%以上的空间;维表+临时表:项目数多,表较小,占用空间占比小;数据特点:客户几十个部门分析报表,小表分区比较多,大表相对少一些;2.3.2 同步顺序先同步大表,然后再同步小表;业务没有同步顺序要求,小表易变,大表稳定,因此优先同步大表;大表同步需要的手动配置少,也适合前期做好调试;(正式启动同步前的测试不要选太大的表,建议10G-50G,可以测出效率和压力。)优点:机器多,并发高,可以快速压到瓶颈,提升整体同步效率;缺点:Datax为原生的迁移工具,不具备自动化能力,需要人工大量的配置同步任务;注:建议预留几台机器专门用于多分区小表的同步,剩余其他机器同步大表。2.4 总结综上所述,Datax的优势非常明显:首先,部署非常简单,无论是在物理机上或者虚拟机上,只要网络通畅,便可进行数据同步,给实施人员带来了极大的便利,不受标准数据同步产品部署的条框限制;再者,它是开源产品,几乎没有成本;但是,它的缺点也是显而易见的:开源工具更多的是提供基础能力,并不具备任务管理,进度跟踪、校验等等一系列的功能,只能使用者自己通过脚本或者表格记录,目前暂无白屏;因此注定了它只能作为临时性质的数据同步工具去使用;所以,业务上有一些规范化管理或者标准化运维的需求时,或者有频繁的、持续的使用数据同步调度的需求时,安全生产是非常重要的,还是推荐大家使用阿里云官方的产品。3. 写在最后本期给大家介绍了Datax的相关概念,分享了两个案例供大家参考,但是在实际的数据同步过程中仍有非常多的困难和问题,需要对整个数据传输的链路做分析和优化,操作较为繁杂。后续会给大家介绍案例二中的性能瓶颈分析和优化。所以,下一期见咯。参考文档[1] Datax的git地址:https://github.com/alibaba/DataX/我们是阿里云智能全球技术服务-SRE团队,我们致力成为一个以技术为基础、面向服务、保障业务系统高可用的工程师团队;提供专业、体系化的SRE服务,帮助广大客户更好地使用云、基于云构建更加稳定可靠的业务系统,提升业务稳定性。我们期望能够分享更多帮助企业客户上云、用好云,让客户云上业务运行更加稳定可靠的技术,您可用钉钉扫描下方二维码,加入阿里云SRE技术学院钉钉圈子,和更多云上人交流关于云平台的那些事。
1. 序某专有云项目具备压测场景,在Windows的压测机上用 LoadRunner 进行业务的压力测试,压测运行一段时间后出现大量端口无法分配的报错。其实通过问题描述,以及 Windows的报错信息基本确定是压测机的问题。但可能原因较多,一直未能达成一致。所以,趁机分析了客户端的压测机成为压测瓶颈的可能,除了CPU、网络、I/O 等机器性能参数外,仍需考虑网络协议引入的资源短缺问题。注:以下内容的目的是理清TCP协议中比较模糊的内容,对协议比较熟悉的可以忽略。2. TIME_WAIT基础:RFC 793 TCP协议众所周知, TCP存在三次握手,四次挥手过程。其具体设计的目的,简而言之,是为了在不稳定的物理网络环境中确保可靠的数据传输;因此,TCP在具体实现中加入了很多异常状况的处理,整体协议就变得比较复杂。要理解TCP协议,推荐阅读 RFC 793,可参考文后资料[1]了解详情。同时,也要理解“TCP state transition”状态机,如下图所示,可参考文后资料[2]了解详情。图1. TCP状态转换图本文仅针对 TW 在TCP协议中的作用进行讨论,不涉及整体协议的分析。四次挥手后的TIME_WAIT 状态,后续将以TW缩写替代。2.1 TW 作用首先,主要作用是保证TCP连接关闭的可靠性。考虑下在四次挥手过程中,如果主动关闭方发送的LAST_ACK丢失,那么被动关闭方会重传FIN。此时,如果主动关闭方对应的TCP Endpoint没有进入TW状态而是直接在内核中清理了,根据协议,主动关闭方会认为自己没有打开过这个端口,而以RST响应被动关闭方重传的FIN。最终该行为导致被动关闭方认为连接异常关闭,在业务上可能会收到异常报错等情况。其次,TW状态同时也能避免相同的TCP端口收到在网络上前一个连接的重复数据包。理论上,数据包在网络上过期时间对应即MSL(Maximal Segment Lifetime),随着操作系统的不断发展,也有例外情况,这部分搜索PAWS应该可以看到不少类似的文章说明。再次,端口进入 TW 状态 同时也避免了被操作系统快速重复使用的可能。2.2 TW形成的原因当一台主机操作系统主动关闭TCP Endpoint(socket)时,该TCP Endpoint进入TW状态。以Windows为例,Windows内核会对 TCP Endpoint 数据结构进行相应清理,然后放入额外的 TW queue 中,设置2MSL 的定时器,等待定时器超时后调用对应的释放代码。Linux上的实现也是类似。目前较多的说法是"TCP连接"进入TW ,但我们可能需要理解 "连接" 其实是抽象的概念。实际"连接"在逻辑上存在,因为客户端和服务器端及中间可能涉及的4层设备同时为一次传输创建了关联的TCP资源(Endpoint,或者 Session)。准确理解TW状态,即TCP EndpointTW进入TW状态。2.3 小结TW 是为了保证 TCP 连接正常终止(避免端口被快速复用),也是为了保证网络中迷失的数据包正常过期(防止前一个连接的数据包被错误的接收)。TW暗杀术,可参考文后资料[3]了解详情。3. 概念澄清欢迎讨论几个可能比较模糊的地方,明确如下:1.作为连接双方,客户端和服务器端的TCP Endpoint都可能进入 TW 状态(极端情况下,可能双方同时进入 TW 状态)。该情况在逻辑上是成立的,可参考文后资料[4]了解详情。2.TW 是标准的一部分,不代表TCP端口或者连接状态异常。(这个概念很重要,避免陷入某些不必要的陷阱。)3.CLOSE_WAIT 尽管也是标准的一部分,但它的出现预示着本端的 TCP Endpoint 处于半关闭状态,原因常常是应用程序没有调用 socket 相关的 close 或者 shutdown。可能的原因是应用程序仍有未发送完成的数据,该情况下CLOSE_WAIT 最终还是会消失的。 具体描述这部分,长期有 CLOSE_WAIT 状态的端口缓慢累积,这种情况是需要引起注意的,累积到一定程度,端口资源就不够了。针对前面的 TCP Endpoint 这个词语,可能很多人不太了解,这边也简单说明下:在Windows 2008 R2之前,socket是用户态(user mode) 的概念,大多数Windows socket应用程序基本都基于Winsock开发,由中间层AFD.sys 驱动翻译成内核 tcpip.sys 协议栈驱动 所能接受的TCP Endpoint数据结构。在2008 R2之后,微软为了方便内核的网络编程,在Windows Kernel中提供WSK,即Winsock在内核的实现。文中提到的TCP Endpoint是在Windows内核中由TCPIP.sys驱动文件实现的TCP数据结构,也对应Linux上的socket。该文简单以 Endpoint 代指内核的"socket"。4. TW 优化手段对于Linux,优化手段已经进行了很多讨论了,以Centos为例。1.在timestamps启用的情况下,配置 tcp_tw_reuse 和tcp_tw_recycle。针对客户端,连接请求发起方。net.ipv4.tcp_timestamps = 1net.ipv4.tcp_tw_reuse = 1针对服务器端,连接请求接收方net.ipv4.tcp_timestamps = 1net.ipv4.tcp_tw_recycle = 1注:tcp_tw_recycle的启用会带来一些 side effect,具体在NAT地址转换场景下,容易发生连接异常问题。可参考文后资料[4]了解详情。2.配置 max_tw_buckets,连接请求发起方接收方通用,但需要注意这个选项本身有违 TW 设计的初衷。net.ipv4.tcp_max_tw_buckets = 50003.配置 ip_local_port_range,连接请求发起方。net.ipv4.ip_local_port_range = 5000 65535针对Windows ,资料较少,这边借之前的工作经验,总结如下:1.Windows Vista / Windows Server 2008 之前的操作系统,注册表端口范围:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\ParametersMaxUserPort = 0n65534TW 超时时间:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\ParametersTcpTimedWaitDelay = 0n302.Windows 7 / Windows Server 2008 R2 及其之后的版本端口范围:netsh int ipv4 set dynamicport tcp start=1025 num=64511TW 超时时间:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\ParametersTcpTimedWaitDelay = 0n30Windows Server 2012 and earlier: 30-300 (decimal)Windows 8 and earlier: 30-300 (decimal)Windows Server 2012 R2 and later: 2-300 (decimal)Windows 8.1 and later: 2-300 (decimal)注:任何涉及注册表的修改,只有重启机器才会生效。与 Linux不同,Windows 没有快速回收机制,不存在快速回收 TW 的可能,只能等待2MSL过期(即TcpTimedWaitDelay)。Windows唯一能快速回收TW状态的Endpoint 的情况:新连接请求的SEQ序列号>TW状态的Endpoint记录的SEQ序列号。 此时,内核会认为该 SYN 请求合法。 这里,这个TW 状态的 TCP Endpoint 一定是在服务端(通过socket accept 打开的 服务端口)。(为了这个能力,Windows 的 RFC 1323 选项必须打开,内容可以自行搜索。)5. 压测客户端无法分配端口的原因分析端口无法分配有两种可能:完全随机的动态端口请求,报错端口分配异常,基本是操作系统没有可用端口。指定端口的绑定申请报错端口分配异常,可能存在端口使用冲突问题。针对第一种情况,首先需要通过 netstat -ano 进行快速检查,分析是否存在端口占满的情况,以及占满端口的TCP Endpoint状态。针对不同的状态,考虑不同的方案。比如,极端情况下,没有任何异常的服务器上,端口分配失败问题,可参考文后资料[5]了解详情。以Windows操作系统TW状态Endpoint占满可用端口场景为例(在Linux上发生的可能性较低),分析问题前需要大概了解 Windows 上端口分配原理。Windows和Linux在动态分配端口的机制上有很大的不同。Linux以粗浅的理解应该是针对五元组的分配,即可能存在相同的动态端口访问不同服务器的服务端口。Windows的动态端口分配实现基于Bitmap查找,无论访问哪里,动态端口的池子最大为 1025 – 65536,即64511个。考虑到最短30秒的 TW 超时时间,如果按照 64511/29 = 2225 ports/s 的速度去创建端口,那么很可能在30秒后持续发生端口无法分配的问题。这还是在连接处理比较快速的情况下,如果连接建立后不关闭,或者关闭时间比较久,创建端口的速度仍需持续下降来规避端口问题。理解了 TW 的形成原因,相应的解决方案也就比较清楚了。降低应用程序创建端口的速度。考虑连接持续时间和TW超时时间,计算相对合理的连接建立速度。不过,物理机操作系统、CPU/内存、网络IO等均可能影响连接状态,精确计算很难;同时,就应用程序而言,降低端口创建速度需要额外的逻辑,可能性不大。在这个压测场景下,通过增加机器的方式来变相减少端口的需求。压测一般考虑某个固定阈值下整体系统的响应情况。在压力固定的情况下,可以通过分散压力的方式来减少端口资源的占用。改变连接的行为,使用持久连接(注:非HTTP的长连接),例如针对500个并发,仅建立 500 个连接。好处显而易见,但坏处也很明显,持久连接不大符合用户真实行为,压测结果可能失真。同时,该方法需要应用程序上的支持。不让机器的TCP Endpoint进入TW状态,可参考以下2种方案。a) 不让该机器主动关闭连接,而让对方主动关闭。这样,该主机进入被动关闭进程,在应用关闭TCP Endpoint之后,可直接释放端口资源。一些协议本身就有控制是否保持连接或者请求对方关闭连接的行为或者参数,在考虑这类问题的时候,可以适当进行利用。比如 HTTP 的长短连接,可参考文后资料[4]了解详情。b) 通过TCP Reset强制释放端口。TCP Reset可以由任何一方发出,无论是发送方还是接收方,在看到TCP Reset之后会立刻将对应TCP Endpoint拆除。这里,可设置 socket 的 SO_LINGER选项,比如配置Nginx,可参考文后官方文档[6]了解详情。图2:Nginx Lingering配置参考说明针对压测工具本身,官方网站上也有类似 ABRUPT 选项,可参考文后官方文档[7]了解详情。图3:LoadRunner ABRUPT配置选项说明参考文档[1] RFC 793:https://tools.ietf.org/html/rfc793[2] IBM TCP state transition:https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.halu101/constatus.htm[3] TIME-WAIT Assassination Hazards in TCP:https://tools.ietf.org/html/rfc1337[4] Tengine健康检查引发大量TIME_WAIT堆积:https://developer.aliyun.com/article/781244[5] CloudMonitor 引发的网络问题排查一则:https://developer.aliyun.com/article/682535[6] 配置Nginx:http://nginx.org/en/docs/http/ngx_http_core_module.html#lingering_close[7] ABRUPT选项:https://admhelp.microfocus.com/lr/en/2020_SP2-SP3/help/function_reference/Content/FuncRef/web/lrFR_web_set_sockets_option.htm?Highlight=web_set_socket_option#Shutdown我们是阿里云智能全球技术服务-SRE团队,我们致力成为一个以技术为基础、面向服务、保障业务系统高可用的工程师团队;提供专业、体系化的SRE服务,帮助广大客户更好地使用云、基于云构建更加稳定可靠的业务系统,提升业务稳定性。我们期望能够分享更多帮助企业客户上云、用好云,让客户云上业务运行更加稳定可靠的技术,您可用钉钉扫描下方二维码,加入阿里云SRE技术学院钉钉圈子,和更多云上人交流关于云平台的那些事。
题目:你正在做的性能测试不是你想象中的样子1996年LR 4.0版本发布,将性能测试专业理论工具化、产品化,这也直接影响后20多年至今性能测试领域的理论基础。但是LR是一个商业化产品,价格昂贵,1998年底开源社区贡献Jmeter 1.0发布上线,性能测试逐渐蓬勃发展起来了。Loadrunner、Jmeter引领了性能测试领域的一个时代,功能强大,脚本化,扩展性强,将性能测试标准化、专业化,后续几乎所有性能测试工具或者商业化产品都马首是瞻。本文就性能测试做了一个纯YY的“实践”(真的只是纯理论分析!),有一些不一样的思路跟大家一起探讨下,望轻踩。1. 前言:并发、RPS和RT接触性能测试的同学要理解的概念有非常多,在正文之前先跟大家就几个核心指标统一下口径:并发用户、并发、VU:一般用来表示虚拟用户(Virutal User,简称VU),对应到Jmeter的线程组线程,对应到Loadrunner的并发Concurrency,在本文都是一个意思。每秒发送请求数、RPS:指客户端每秒发出的请求数,有些地方也叫做QPS,本文不单独讨论“事务”所以可以近似对应到Loadrunner的TPS(Transaction Per Second, 每秒事务数),本文统一叫做RPS。响应时间、RT:对,没错,这个就是你理解的那个意思,从发起请求到完全接收到应答的时间消耗。根据“Little定律”,在平衡状态下,我们可以等价认为并发、RPS和RT之间的关系可以概括为并发数 = RPS * 响应时间偷懒的话,可以把它当成性能测试领域的“乘法口诀”,直接背下来吧,他会帮助你快速理解很多问题;如果想深入了解具体的原理可以去拜读下Eric Man Wong 在2004年发表了名为《Method for Estimating the Number of Concurrent Users》的文章,这两者是等价的。2. 100工人的问题如果你还不了解“RT对于并发模式的性能测试的影响”或者还存在一些疑惑,强烈建议读完本章;如果不想理解细节,可以选择直接跳到本章末尾看结论;如果已经充分了解了,可以直接跳过本章。先从一个大家相对熟知的例子开始,假设有这么一条生产箱子的流水线,安排了100个工人,条件如下:100个工人的身体素质一模一样, 因此可以近似的认为工作效率只与工作的复杂度有关;这个流水线有3份工作(如下图所示的节点A、节点B和节点C),所有工人都可以胜任;节点A工人包装箱子平均耗时 RT1=0.5s(秒),节点B工人包装箱子平均耗时 RT2=3s(秒),节点C工人包装箱子平均耗时 RT3=1.5s(秒)同一个箱子必须按照 节点A、节点B、节点C 的顺序被包装。问:节点A、节点B、节点C分别安排多少工人 X、Y、Z 可以让这个流水线达到最大的产能,并且求得流水线的最大产能 T/s?如下图所示。在平衡状态下,我们从宏观的视角来分析下,整条流水线包装完一个箱子的 总耗时=(0.5+3+1.5)s,那么我们可以很轻易地得到流水线的产能:流水线的产能 T = 100 / (0.5 + 3 + 1.5) = 20 /s可能很多人有疑问,“什么是平衡状态?”,这个可以这么理解,为了保证所有工人都可以达到最大的工作效率,主管会非常睿智的调配各个节点之间的工人分配直到“所有工人都有事可做,也不会存在工人忙不过来”,那么从微观的角度去看,如果节点之间的产能不一致,有些节点就会出现箱子等待被处理,有些节点的工人等待箱子的情况。所以,我们可以得到这样的结论 在平衡状态下,所有节点产能肯定是一致的:T(A) = T(B) = T(C) = T = 20 /s从而,根据little定律,我们可以推算出来,各个节点的人员(vu)分配了:X = T(A) RT1 = 20 0.5 = 10 Y = T(B) RT2 = 20 3 = 60 Z = T(C) RT3 = 20 1.5 = 30下面这张Jmeter的图,相信大家可以轻易地跟前面的自理找到对照关系,我这里不再赘述了:产能 = RPS 工人 = 并发 完成平均时间RT = 响应时间、RT(rt)综上所述,我们可以得出两个结论:在平衡状态下,所有节点的RPS必然一样在平衡状态下,任意节点的RT都会影响整体RPS,进而会影响并发在节点之间的分配关系。为了描述方便,我们将节点A、节点B和节点C组成的“100人的流水线”叫做“串联链路”。 节点A的RPS = 节点B的RPS = ... = 串联链路RPS 串联链路RPS = 并发数 / (RT1 + RT2 + ... ) 节点N的并发数 = RTn 节点N的RPS = RTn 串联链路RPS3. 你确定考虑全面了吗?控制并发是目前最为普遍被使用到的压测模式,打个比方,有一个网站大概会在 下周一10:00 预估有 10w人同时访问,那么为了保障网站的问题,很自然的想到使用10w个并发来压测下整个网站的接口,对应到JMeter即为设置线程组的线程数,对应到LoadRunner设置VU(Visual User)数,很容易理解。另外,我从 阿里云PTS 官方拿到近6个月的数据显示,近10000+企业用户中,选择并发模式与RPS模式分别占比 89%与11%,并发模式占据绝对的规模优势。但是,如果你已经充分了解了“RT对于固定并发模式的性能测试的影响”,这里我不禁要问一句“Emm... 你有想过类似Jmeter、LR等并发模式压测工具拿到的结果是真实的吗?准确吗?”。下面我要讲一个“恐怖故事”,先来看一张相对抽象的环境结构图。在平衡状态下,已知总并发VU,以及 接口1、接口2、接口3 的响应时间分别为RT1、RT2、RT3,通过前面的理论基础,我们可以轻易地写出下面的算式:T = RPS1 = RPS2 = RPS3 = VU / (RT1 + RT2 + RT3)接口1的并发 X = T * RT1 接口2的并发 Y = T * RT2 接口3的并发 Z = T * RT3分析下接口的RT的构成,大致概括为下面5部分:压测工具耗时:这个很好理解,压测工具在发送请求之前会做参数的拼装/替换、下载应答报文、解析应答报文(断言)等都是需要耗费时间的,一般情况下压测工具的时间消耗会非常低,可以忽略。但是对于报文较大或者断言较复杂的情况下,压测工具耗时过大也会出现瓶颈;网络时间:一般来说在VPC/IDC内部的网络消耗非常低,所以我们可以近似地认为网络时间消耗都来源于运营商网络。同样,对于接口的请求和应答报文比较大的情况下,不论是运营商网络还是内网网络的带宽都更容易出现瓶颈;安全、鉴权、负载均衡模块耗时:这一块的时间消耗一般来说相对较低,受限于连接数、带宽等,可能会出现由于配置问题,比如连接数上限超过预期,则会造成等待建连超时;应用业务处理耗时:一般情况下,应用业务处理耗时占据RT的百分比最高,也是一般我们可以通过优化提高吞吐量的重点区域。可能包含 应用之间RPC服务调用、数据库SQL执行、读写缓存、读写消息等。第三方依赖耗时:这里就复杂了,各种情况都有,你可以完全信赖或者完全不信赖它的稳定性。一般它的RT评估有相关SLA的要求,一般压测实施的时候根据SLA约定的RT要求,mock掉第三方接口依赖,正式压测的时候再一起联压。更进一步,可以得出这样的结论,在并发模式下,影响压测结果以及应用服务器的吞吐量的因素有:压测工具的性能网络状态接入层配置和性能应用服务性能第三方依赖的SLA...因此,出现了一种混沌状态,可能由于压测工具所在宿主机负载变化、网络环境变化、应用服务性能优化或者劣化等因素的干扰,拿着相同的脚本进行了10次,每次得到的接口RPS都不一样,服务器端的压力也不一样,但是从表象来看,一切正常,但这样的性能测试并不能真实反映任何问题,也并不能指导运维做出正确容量规划的决策。因为影响RT的因素实在是太多太多了,任何客观因素的影响都直接影响测试结果的准确性。4. 并发模式=性能瓶颈“定性”分析在这里,我更愿意定义并发模式性能测试为一种性能瓶颈分析的定性工具,在尽量相同的条件下经过反复测试,通过分析各个接口的RT构成找到“相对的”性能瓶颈。但是大家有没有想过,将所有接口优化到极限的性能之后,可以拍胸脯说“我们的系统已经可以抗住XXX并发用户量的访问了”吗?答案是否定的,原因有三:不真实,主要体现在 ① 环境不真实;② 压测(脚本)模型不真实;主体错误,并发只是一个诱因和触发器,影响性能的主体是服务端的RPS;并发测试的效果真实性依赖于RT,而RT的构成异常复杂。对了,前面的分析漏了(我故意的)一个影响并发性能测试结果的非常重要的因素:思考时间(用户在操作的时候,步骤之间用户会停顿一段时间)。思考时间的引入会将并发的建模的复杂度带到几乎不能实现的地步,因为它不像其他相对客观的因素,它是非常主观的。假如用户停留的时间很长,可能是因为感兴趣多看一会儿,或者页面上有100个表单需要填写,或者看不懂文案是啥意思正在google,或者...去冲咖啡了。有人可能会追问“思考时间究竟要设置多少合适呢?”,我可以非常明确的说“不知道!”,如果你有时间,可以通过大数据BI分析统计学意义上的每个接口之间用户停顿的时间,然后将它设置上,假设每个接口的思考时间总和为 S=(S1+S2+S3),那么我们可以更新下公式:T = RPS1 = RPS2 = RPS3 = VU / (RT1 + RT2 + RT3 + S) 接口1的并发 X = T * RT1 接口2的并发 Y = T * RT2 接口3的并发 Z = T * RT3可以看到,增加了思考时间之后,整体的吞吐量、所有接口的并发都下降了,因为有部分用户在“思考”。增加“思考时间”有助于提高并发模式下性能测试的准确性,除此之外,还有一些提高并发模式的准确性的手段:压测工具地域定制、运营商定制增加条件跳转,模拟用户重试行为增加集合点...这些手段你可以非常轻易的在市面上的开源或者云测平台上找到(有些功能可能需要支付一些费用),在这里不再一一赘述,归根到底,可以总结为“优化接口RT使其接近真实值以提高并发模式的准确性”。但并发模式始终都受制于“不稳定的”、“难模拟的”、“难预测的”接口RT,通过并发模式拿到指导运维进行容量规划的结果,是要付出的代价会非常大的,甚至也不能达到想要的结果。在真实情况下,接口1、接口2、接口3的RPS是不一样的,抛开接口异常断言失败不继续调用后面的接口的情况,接口RPS关系是呈倒金字塔分布,比方说,浏览商品(接口)了之后不一定会去下单购买(接口),因为大家一般会反复浏览不同的商品选择最中意的再下单,所以浏览商品(接口)的RPS必然会比下单购买(接口)的RPS要高,用户有放弃继续“走下一步”的权利,但是这种情况你如果尝试对并发的分布来建模,是一个非常庞大且复杂工程问题,因为影响的因素实在太多了。如下图所示,并发压测模式下,所有接口的RPS都是一样的,与“实际情况”(图右部分)大相径庭。受传统性能测试思路的影响,目前有 接近90%的企业用户(数据来源于阿里云PTS[1] ) 将并发模式性能测试的结果作为稳定性、容量验收的依据,所以说这是一件非常恐怖的事情。5. 容量规划:从定性分析到定量分析在这里我非常乐意跟大家分享一份来源于 QA Intelligence[2]《State of Testing™ Report 2019》关于2016~2019年软件开发模式的调查数据:软件开发模式占比(2019、2018、2017、2016)数据显示,DevOps第一次超过Waterfall(瀑布模式)成为第二位被越来越多的企业接受的开发模式,而瀑布模式等传统开发模式有逐渐退出历史舞台的趋势。敏捷开发和DevOps大行其道,开发、测试和运维等部门、角色之间需要有一种高效的沟通和协作手段。想到了一句非常“肤浅”但有点道理的话,“性能问题优化之后最终都可以转化为容量问题”,简单地可以理解为测试同学发现了性能瓶颈,然后开发同学经过了优化,运维同学根据优化之后的系统的能力进行扩容或者缩容。瞧!这不就是开发、测试和运维完美协作的一个典型实践嘛?!这个过程,我们叫做“容量规划”的实施过程,重点不是容量而是规划,如果成本不是任何问题,我们可以堆砌无限大的资源,用户体验会极其好,但是会造成极大的资源浪费。所以这里说的“容量规划”是在保证用户体验不受影响(稳定性)的前提下,使有限的资源的利用率最大化(成本)的方法论。打个比方,运维准备了100台机器,有5个应用,那么“怎么分配这100台机器给5个应用可以使系统既可以正常对外服务又可以使系统达到最大的吞吐量能力”就是容量规划要解决的问题。容量规划的核心有一张已经用的“泛黄”的图,大家应该一看就明白,有两个核心指标:预估的业务量级:对于单应用而言就是这个应用的RPS吞吐量峰值,这个数据一般可以来源于流量模型和历史数据沉淀;单台机器的能力值:在某一个流量模型下,单台机器系统水位达到安全水位时的RPS峰值。上面提到一个概念叫做“流量模型”,这个流量模型你可以近似的认为就是前面图中“实际情况”的RPS倒金字塔,他有两个要素,接口范围每个接口的RPS容量规划的目的性非常强,也就是在特定“流量模型”下,给出资源分配的最优解。在压测实施的时候,压测的主体是接口的RPS,按照流量模型进行试压。(如果你还在想为什么主体是RPS而不是并发的话,请在仔细阅读前面那章)RPS模式压测在容量规划的典型应用,是并发模式无法实现的。正式因为此,我们才能将性能测试从“定性分析”转化为“定量分析”。阿里在2013年构建了一整套基于线上全链路压测的容量规划体系,逐渐替代之前单应用、单接口这种低效的容量评估手段,过程也是非常曲折的。容量规划是一个非常大的课题,本文的重点不是“容量规划”,如果你对“智能化全链路容量规划”感兴趣,请留言。6. 结尾:无意引战并发模式与RPS模式压测各有各自的使用场景,并发模式更加适用于对于系统定性的分析,比如帮助定位性能瓶颈,单接口的性能基线沉淀(对比历史性能优化or劣化);而RPS模式在对系统做定量的分析有杰出表现,比如容量规划,全链路性能基线沉淀,当然也可以帮助定位性能瓶颈。并发模式的难点在于RT的准确性拟真,RPS模式的难点在于模型的准确性评估和预测,从实现难度上来说,前者相对于后者来说难度更大一些、掌控度更低一些。当然,我无意引战,并发模式、RPS模式、你想要的和你还没有想到未来想要的都可以在 阿里云PTS 上找到。Done!参考文档[1] 阿里云PTS:https://www.aliyun.com/product/pts[2] QA Intelligence:https://qablog.practitest.com/相关内容如何做好性能压测(一)丨压测环境设计和搭建我们是阿里云智能全球技术服务-SRE团队,我们致力成为一个以技术为基础、面向服务、保障业务系统高可用的工程师团队;提供专业、体系化的SRE服务,帮助广大客户更好地使用云、基于云构建更加稳定可靠的业务系统,提升业务稳定性。我们期望能够分享更多帮助企业客户上云、用好云,让客户云上业务运行更加稳定可靠的技术,您可用钉钉扫描下方二维码,加入阿里云SRE技术学院钉钉圈子,和更多云上人交流关于云平台的那些事。
2021年03月
2021年02月
2021年01月