关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

按核数算云手机能开多少台,为什么总是不准:三本账要分开算

发布时间:2026-11-04

一台十几个核的服务器买回来的时候,账是这么算的:一个云手机实例给两个核,十几核除下来七八台的容量,剩下的留给系统和调度,看起来绰绰有余。真跑起来是另一回事——开到第三台还算顺,第四台一上去,画面就开始拖,点击下去隔一小会儿才有反应,掉帧、桌面卡在某帧、偶尔整个实例黑一下。第一反应是内存不够,加了一轮内存,改善有限;再看整机占用,CPU 平均也不高,内存也没打满,可体感就是卡。这种落差不是个例,它说明密度压根不是按核数封顶的:核数只是四本账里的一本,而且往往不是最先撞墙的那一本。上文的数字只是当时按“每实例两个核”排出来的估算口径,用来说明这种算法为什么会落空,不构成任何可参考的容量值。

要把这件事算清楚,得把一个虚拟手机实例在机器上同时占用什么拆开,分成四条独立的账本分别记:计算账(CPU 时间与调度)、编码账(每一路画面送出前的编码,按并发路数计)、显存账(帧缓冲与纹理,按每实例固定占用累加)、存储账(镜像层、写时复制层与用户数据层叠加出来的写放大)。四本账各自算出一个上限,密度取其中最小的那个,而不是取它们的平均值,也不是照核数直接反推。遗漏任何一本,算出来的数都会系统性偏高,而且高出的部分没有提示——机器不会报错,只会变卡。

按核数估密度为什么会落空:平均值算出来的数经不起并发

“每实例两个核”这个口径本身隐藏了一个前提:把一个核当成一份可以按人均分的、持续稳定的算力。这个前提在多实例场景里站不住。单个实例内部的应用逻辑、界面绘制、图形指令提交、网络收发并不是平滑铺开的,它们是成串的突发——一帧画面要在一小段时间里完成绘制到合成到送出的全过程,中间任何一环排队,后面全部顺延。把好几个这样的突发串排到同一批物理核上,平均值可能仍然很好看,但同一时刻的叠加值已经超过了窗口能给的额度。

平均占用率正是这里最容易骗人的指标。整机 CPU 平均只占一部分,是因为每个实例的忙闲是错开的,闲的那一瞬把忙的那一瞬填平了;而用户感知到的卡顿恰恰发生在它们同时忙的那一瞬。密度算的就是这一瞬能不能装下,不是一天的平均能不能装下。

还有一层折扣常常被忽略:物理核与逻辑核不是一回事,超线程带来的并行度远不等于翻倍,两个逻辑核抢同一组执行资源时,收益取决于负载类型。也就是说,即便只算计算账,“物理核数除以二”这一步也已经低估了折扣。再叠加实例里还跑着一批后台常驻任务——消息轮询、心跳、日志落盘、统计上报——它们不在业务脚本里,却一直消耗份额。

更根本的问题是,还有相当一部分负载根本不落在 CPU 上。画面的编码如果有独立硬件单元承担,就不算进 CPU 账;帧缓冲与纹理占的是显存;实例的写入落的是存储队列。这三块在“每实例两个核”的算式里完全缺席。所以按核数估密度,等于默认了这三本账不存在,或者默认它们永远不会先崩——而这个默认恰好是大多数情况下最先被现实推翻的那个。

一个虚拟手机实例在跑什么:计算、画面、存储三件事同时发生

拆一个实例在稳定运行时占用了什么,可以粗略归为三件同时发生的事。第一件是应用自身的逻辑执行与界面渲染指令的生成,主要吃 CPU 时间,部分图形工作在 GPU 侧完成;第二件是把自己这台“画面”变成可以远程观看的一路码流,这一步是编码,吃的是编码器资源,属于按会话数计的并发资源;第三件是存储读写,既包含从共享镜像里读系统文件,也包含这个实例私有的写入。三者在时间轴上基本同时发生,而且互不等待——不会因为 CPU 忙就少编一帧,也不会因为编码排队就少写一份日志。

正因为是三件独立的事,它们各自的上限来源完全不同:一件受调度窗口限制,一件受并发会话数限制,一件受队列深度与介质能力限制。再用一层附加账:显存既不属于 CPU 也不属于磁盘,它是第三种稀缺品,而且在虚拟化的图形栈里通常表现为“每实例先扣一笔固定额度”的形态,先到先得,后来者分不到。

下表把这四份账本并列,方便对照。它只描述“该看什么”,不给出任何数值定论——每一项的具体大小都必须由读者在自己的镜像、分辨率、帧率与业务脚本下实测填进去。

资源面 主要影响因素 为什么会先成为瓶颈 观察指标 该跑一次什么实测
计算(CPU 与调度) 核数与逻辑核比、单核性能、调度配额与亲和策略、后台常驻任务 多实例的渲染突发叠加到同一时间窗,平均值达标但并发峰值撞墙 每帧耗时分布、调度等待时长、运行队列长度 目标场景下单实例满载占用的 CPU 时间换算方法
画面编码(并发路数) 编码器类型与并发会话上限、分辨率、帧率、码率控制与画质策略 容量按并发会话数封顶,路数超过额度后转为排队而非变慢 编码排队深度、帧间隔抖动、超编或降帧触发频次 在目标分辨率与帧率下实际能稳定并发的路数
显存(帧缓冲与纹理) 每实例固定占用的缓冲份数、分辨率与每像素格式、虚拟图形栈的分配策略 按实例线性累加且不压缩,越界表现为分配失败或实例被杀,不是降级 显存占用随实例数的斜率、显存回收与交换行为 单个实例在自己的分辨率下的固定显存占用
内存(每实例固定开销) 虚拟化与设备模拟开销、运行时常驻、可共享页比例、页缓存与匿名页比例 固定开销乘以实例数后再被缓存争抢,交换一旦开启延迟账劣化 匿名页占用、页缓存命中率、换入换出速率 相似镜像之间的内存去重收益是否值得开
存储(写放大与 IO 模式) 系统镜像只读层、写时复制层、用户数据层的叠加方式、随机写 IOPS、队列深度 持续小随机写与批量同步写叠加,容量不紧但队列先满 队列深度、写延迟分位、写放大倍率 单实例在完整业务周期内的累计写入量与 IO 分布

这张表真正要表达的只有一条:四个资源面的失效形态不一样。CPU 不够时表现为变慢,尚且能用;编码超过额度时表现为排队与掉帧;显存不够时表现为实例直接起不来或被回收;存储队列满时表现为整个机器上的所有实例一起卡。所以“先成为瓶颈”的那一本账,决定了故障长什么样,也决定了你第一步该去查什么。

每一路画面都要编码:并发路数才是封顶的那一项

这是最容易被漏掉的一本账,也是最常成为密度上限的一本。远程观看一台虚拟手机,本质上是把这台设备的每一帧画面压成码流传出去,实例与码流是一一对应的关系:十台实例就是十路独立的码流,每一路都要维持自己的帧率,不会因为别的路忙就允许自己少编几帧。这一点决定了它是并发资源,不是平均资源。

并发资源与平均资源的区别在于能不能透支。平均资源可以这样想:总量够一天跑完就行,忙的时候多用、闲的时候少用。并发资源不行——同一时刻在线的每一路都必须在自己的时间预算里拿到额度,额度给不出,这一路就得排队。排队的结果是帧间隔被拉长,客户端看到的就是卡顿、拖影、操作延迟;如果编解码链路为了保通路而降画质或者丢帧,看到的就是糊与跳。此时去看整机的平均资源占用,很可能各项都不高,因为排队的代价不体现在占用率上,体现在等待时间上。

单路压力由分辨率、帧率、码率控制策略与画面复杂度共同决定。这里没有放之四海皆准的数:同样的机器,把分辨率和帧率往下压一个档,能服务的并发路数可能是另一番景象;而业务能不能接受这个画质,又完全取决于业务形态——跑脚本的任务可能根本不需要看画面,做真机兼容性测试的就必须要看清细节。所以这一步不是问“能开多少”,而是问“在我要的分辨率与帧率下能开多少路”。

还有一个连带效应:一部分实例降画质、一部分保持高画质,混合并不等于取中间值。编码器按会话粒度占用资源,测算时须按最重的那批实例口径估算,而不是按平均画质。

硬件编码与软件编码的差别不在速度,而在能不能同时开这么多路

谈编码一定要区分两条路。软件编码是在通用 CPU 上用算法算出来的,它占用的是 CPU 时间——也就是说,它会回头和“每个实例分几个核”那本账打架:实例越多,编码抢走的计算越多,原本留给应用逻辑的份额越少,最后表现为应用本身变慢。这种情况下 CPU 账与编码账是耦合的,测算时不能分别取最小值再乘,必须迭代。

硬件编码是另一回事,它由专门的固定功能电路承担,不占用通用 CPU 时间。好处很明显:计算账清静了。但它的容量也是有限的,而且限制形式与 CPU 不同——它不是“总共能算多少”,而是“同时能挂几路会话”。不同代际的产品、不同的驱动与固件策略、不同的虚拟化透传或虚拟化方式,对这个并发上限的处理都可能不同,有的严格、有的宽松但超出后画质骤降。所以问资源方时,正确的问法不是“支不支持硬件编码”,而是“在我的分辨率与帧率下,能稳定并发几路”,并且要求在自己的镜像上验证。

实践中还要注意两点。第一,取流、叠加、缩放这类前后处理不一定全走同一条通路,如果有一部分图形工作仍要落到通用计算或软件路径上,硬件编码省下来的份额会被吃掉一部分。第二,不要把解码和大模型计算或者别的同时跑在同一批单元上的任务混算;同一台机器上如果还并行运行其他需要编码器或相关单元的负载,这里的账要重新分。

帧缓冲与纹理:显存是按“每实例固定占用”被吃掉的

显存这一本账的形态跟前面几本都不一样,它是“先扣款”而非“按用量计费”。一个虚拟设备在初始化的时候,就会申请好自己的一组缓冲:前台 buffer、合成层、编码输入前的缓冲,以及纹理缓存。这些额度与实例是否空闲无关——实例黑屏待机,占用依然在。于是显存消耗随实例数基本呈线性累加,斜率的单位是“每实例多少”,而不是“每秒多少”。

斜率由分辨率主导:画面的宽度乘高度再乘每像素的字节数,得到一幅的大小,再乘好几份缓冲。这意味着分辨率往上跳一档,每实例显存占用是乘法式的上升,而不是加法式的。换句话说,同样一台机器,把每个实例的分辨率从一档降到下一档,允许的实例数可能成倍变化——这也是为什么降分辨率往往比加硬件更快看到密度改善。

显存账还有一个讨厌的特点:它的失效不是渐进的。CPU 不够时还能跑得慢一点,编码排队时还能勉强看,显存一旦不够,行为可能是直接的——分配失败、新实例起不来、或者某个已有实例被回收。这类失效表现为随机性和不可复现,因为谁先被杀取决于当时的分配顺序。因此在测算阶段,显存这一本账必须留足余量,不能贴着上限排容量。

另外要留意记账方式本身能不能看清。若底层是共享式的虚拟图形栈,每实例占用可能被摊进共享池而没有清晰读数,只能靠逐步加压、观察实例个数与失效点的关系来反推斜率——这一点不同虚拟化与驱动版本表现不一,必须自行实测。

内存账:每实例的固定开销、匿名页与缓存争抢

内存是最直观的一本账,也是最容易被误算的一本。误算的来源是把它当成“只要总量除一下就行”,但实际上每实例的内存由两部分构成:一部分是不随负载变化的固定开销,另一部分是随负载波动的可变部分。固定开销包括虚拟机与其设备模拟自身的管理结构、运行时、框架常驻的那部分;可变部分是应用自己的堆栈与缓存。密度估算真正要算的是固定开销乘实例数之后,还剩多少给可变部分。

共享内存的收益值得期待但不可预设。多个实例跑同一套系统镜像时,代码段与只读资源是可以在实例之间合并的,合并机制本身也有扫描与维护成本,收益取决于镜像的相似度、页面改写频率以及是否开启了相应机制。相同版本、相同应用的实例群,收益通常比混跑多种镜像要好。但这个比例无法从纸面推算,只能在自己的镜像组合上压一遍,看内存占用随实例数的斜率有没有变缓。

匿名页与页缓存的争抢是第二个陷阱。前者不可回收,只能靠交换;后者可以回收,但回收掉之后再读回来就是读放大,而且这份读的压力会落到存储账上。于是会看到一种典型现象:内存看起来还很充裕,实例却开始卡,因为系统正在频繁回收页缓存,把本该命中的读变成命中不了。

于是要不要用交换来换取密度,答案通常偏向否。交换换来的是“实例能起来”,不是“实例能跑”;一旦开始换入换出,延迟账会以远超比例的方式劣化,而这类业务的验收标准恰恰是延迟与流畅度。宁可让密度低一档,也不要把密度建立在不稳定的内存基础上。

存储账:系统镜像、每实例写时复制与用户数据三层叠加的写放大

存储的账要分三层来看。最底下是共享的系统镜像只读层,所有实例从这里读,读的这部分压力主要靠页缓存吸收,实例越多、镜像越一致,缓存命中的收益越明显。中间是每实例的写时复制层,实例对系统文件的任何改写都落到这里,它让 N 个实例共享一份底图的同时保留各自的差异。最上面是用户数据与应用产生的数据,这部分写入随机、琐碎、持续。

三层叠加出来的问题集中在“写放大”上:一个看似很小的逻辑写落到物理介质可能是一笔大得多的动作。写时复制本身就是放大源;日志、统计、数据库事务、缓存重建、资源热更新这类行为又提供了源源不断的小随机写。再叠加一个常被忽略的时间因素——每个实例都在做自己的后台维护与数据回收,这些任务往往集中在设备空闲或充电状态之类的条件下触发,而这种触发条件在虚拟化环境里可能被压缩到同一段时间,形成写风暴。

所以要盯的不是容量而是模式:随机写的能力、队列能排多深、延迟分布如何。容量几乎没有成为云手机密度的瓶颈过,队列深度和写延迟才是。介质类型、raid 或冗余策略、是否有独立的数据盘,都会改变这本账的上限,而且这些参数组合起来非常难从纸面推断。一个实用的记账办法是把三层分别放到不同的卷上,先分别测得各自的 IO 形态,再叠加,避免三层互相干扰导致读数无法归因。

附带一层连带影响:存储慢会反过来拖慢内存,页缓存回读与写时复制的元数据操作都要走存储。这正是“别处都有余量、整体就是不顺”的常见幕后原因。

操作延迟是密度上去之后最先变坏的指标

密度往上加的过程中,指标变坏是有顺序的。最先恶化的通常不是成功率也不是吞吐,而是延迟,尤其是延迟的长尾。原因很直白:每一项资源在被填满之前,都会先出现排队,排队不减少产出,只增加等待。而占用率这类平均值恰恰看不到等待。

具体到操作响应,一次点击要走过完整的链路:输入注入到虚拟设备、应用处理、界面绘制、送出前编码、网络传输、客户端解码呈现。每一段都有自己的队列。密度低的时候队列基本为空,延迟接近链路固有开销;密度上去之后任意一段开始排队,端到端延迟立刻抬升。麻烦的是排队的段落不固定——有时是 CPU 突发,有时是编码队列,有时是存储的写回——所以看到卡顿就去加某一个资源,往往加错方向,这也是开篇那个“加了内存没改善”的典型成因。

因此验收要看分位而不是平均。平均值会把一条长尾藏得很干净,而用户抱怨的从来不是平均响应时间,是偶尔那一下。建议在自己的业务脚本里把关键操作打上时间戳,记录端到端耗时并看高分位,用这条线去反向确定密度,而不是用占用率去推断密度。

抖动与串扰:为什么平均占用不高,体感还是卡

即便各项平均值都还在合理区间,体感依然可能很差,这要归到抖动与串扰。抖动指的是同一个动作的耗时忽长忽短;串扰指的是实例之间通过各种共享资源互相影响。二者叠加的结果就是:机器“看着不忙”,用户“用着很卡”。

共享资源的争抢点很多:末级缓存被邻居的实例刷掉、内存带宽被大批读取占满、编码单元的队列被旁边的路数插队、写入带宽被某个实例的热更新独占。这些都是同一台机器内部的事务,不会出现在“这台机器还剩多少”的简单读数里。密度越高,争抢的概率越高,抖动的幅度越大,于是出现一种奇怪的现象:加一台实例的边际代价并不是常数,第二十台的代价可能远大于第十台。

行为同步化是另一个放大器。同一批镜像意味着相同的系统版本、相同的定时策略、相同的推送到达逻辑,于是很多后台行为会在同一时刻集体发生——同时做数据整理、同时拉起、同时回收。这种惊群式同步会把本来分散的压力压在同一个瞬间。解决思路不是加资源,而是错开:把定时任务随机化、把升级与维护分批、给不同的实例组设定不同的触发窗口。

还有一类抖动跟拓扑有关。多处理器机器上内存访问不是均质的,若实例的内存分配位置与其计算节点不在同一侧,部分实例会长期多背一次跨节点开销,表现为“有的实例明显比别的慢”。这类差异在平均值里完全消失,只有按实例逐个观察才看得出来。

密度测算的四步口径:先定单实例基线,再定并发峰值,再取最小值,最后留余量

把上面的分析收成一个可执行的口径,是四步。第一步,定单实例基线:只开一个实例,跑真实的业务脚本,在真实的分辨率与帧率下,同时记录四样东西——它占多少 CPU 时间、它占用多少编码资源(或在软编路径下换算成 CPU)、它占用多少显存、它在一个完整业务周期内产生多少写入与什么样的 IO 形态。注意这里要跑满载的典型脚本,而不是空闲待机。

第二步,确定并发峰值而不是平均值。峰值有两种来源,一是业务自身的忙闲周期,二是运维事件的叠加(批量开关机、镜像更新、备份、日志上传)。要把这两种都设计进压测脚本里,让它们真的同时发生,而不是分开做。编码账尤其要按同时在线路数取峰值,不能按日均套均值。

第三步,用四本账分别算上限,取最小值。这里有个容易犯的错误:把四本账的资源互相折算、互为补充。它们不能互补——CPU 有余量不能变出显存,显存有余量换不来一路并发编码。最小值就是这台机器在这种配置、这种分辨率、这种画质策略、这种脚本下的密度上限。

第四步是留余量,而且是必须留。余量的理由很具体:系统与应用版本更新后单实例基线会整体上移;突发行为无法提前全部枚举;维保与异常恢复需要临时迁移一个实例到别的机器上;长期运行的机器会有性能衰减与后台碎片。因此按测算出的最小值直接排满是最容易出事的排法。

需要明确划一界限:本文给的是测算口径与方法,不提供任何具体机型参数、实例密度定值、帧率或跑分数据;所有量化结论都必须由读者在自己的镜像、分辨率、帧率与业务脚本下实测得出。本文也不比较任何云手机产品或虚拟化方案——不同方案在这四本账上的表现差异极大,横向比较只有在同一套镜像与同一套脚本下才有意义,而那已经超出了一篇方法文章的能力范围。

选型看哪几个变量:核数、单核性能、硬件编码能力、显存与内存带宽

把口径落实到采购参数上,值得逐项确认的变量有六类。第一是核数与是否有超线程,以及更重要的第二项——单核性能。同为核心数量,不同代际产品在同样单帧工作上花的时间差别很大,而这直接决定第一步测出来的基线高低;核心数多而单核弱的机器在多实例突发场景下未必占优。

第三项是硬件编码能力,前面说过,正确的问法是目标分辨率与帧率下的稳定并发路数,以及超出之后的行为是排队、降画质还是失败。第四项是显存与图形栈:总量、是否可切分、每实例是否被清晰记账。第五项是内存带宽与容量——带宽常被漏掉,多实例同时读取、同时写回时,带宽先于容量成为约束。

第六项是存储:介质类型、随机写能力、能否把三层分在不同卷上、热点数据有无独立写入路径。第七项是常被当作附带却足以卡住整件事的网络与出口:每实例上下行、批量开关机突发、是否需独立地址,它们不决定“能开几台”,但决定“能不能正常工作”。

还有一个方向性的判断值得提前做:密度是拉满单机,还是横向多铺几台同等密度的机器。单机高密度通常单位成本更优,但代价是故障影响面集中、升级与迁移的窗口更难安排、抖动更难控制;多台低密度的方案运维更从容,代价是镜像分发、调度与地址管理更复杂。这两个方向选择哪一档,应该由业务的容错要求决定,而不是由“别人家能开多少”决定。

批量运维:开关机风暴、镜像分发与调度错峰

密度算完之后,还有一批事情在“按规划数量开起来”的那一刻等着。最典型的是开关机风暴:一批实例同时上电,各自要做文件系统检查、应用冷启动、数据加载、首帧绘制与首帧编码,把平时分散的开销全压到同一分钟;超时失败后的重试还会二次叠加。应对办法并不神秘——分批拉起、错峰、给每批设定观察窗。以下为通用的部署思路示例,不指向任何具体客户,也不构成性能承诺。

镜像分发是第二个坑。给一批实例同时推一次系统或应用更新,会同时造成读放大(所有实例读同一份包,缓存能否兜住)与写放大(每个实例各自落盘、各自解压、各自改写数据)。比较稳的做法是把分发做成阶梯:先在一小批实例上验证,确认新增的资源占用没有抬高单实例基线,再逐步推开;同时在推之前预留额外资源余量,因为新版镜像往往意味着基线整体上移。

调度错峰要落到具体行为上:定时任务随机化打散、备份与日志上传放到业务低峰、巡检与统计错开,避免几十个实例在同一秒做同一件事。这类改动几乎不花钱,对抖动的改善常比加硬件明显。

观测粒度同样关键:整机平均占用在密度问题上信息量很低,有用的是按实例、看分位的三条曲线——关键操作耗时、画面帧间隔、写积压。

三类业务形态的适用边界

第一类是以数量取胜的挂机与自动化任务。这类业务对时延相对宽容,但有一个隐藏要求:不能掉步。脚本依赖画面识别或界面状态判断时,一次掉帧可能让脚本做出错误分支,最终表现为任务失败而不是卡顿。因此这类形态真正的约束不是“看起来顺不顺”,而是“识别成功率”,它可以牺牲分辨率与帧率去换并发路数——把画质降档往往是这类业务提升密度的最快手段。

第二类是多账号隔离类业务。它的核心诉求是账号环境之间不可互相识别、不可互相污染,画面只是附属产物。这类形态的瓶颈常常不在画面而在“隔离”本身:地址资源、设备指纹参数、环境扰动的一致性。画面甚至可以按需抓图而不是持续出流,一旦不要求持续出流,编码这本账的压力会大幅下降,密度口径随之完全不同。这也说明为什么跨业务类比密度没有意义——出流模式变了,账本结构就变了。

第三类是兼容性测试与真机调试。特点是占空比低但峰值极端:大部分时候空闲,一旦批量跑测试就是 CPU、存储、编码同时打满,而且操作系统版本、屏幕参数、渲染路径的组合极多。给它配密度不能用稳态均值,必须按极端并发的最坏情况预留,并且要接受“多数时间资源闲着”这个代价。把这类负载与长期挂机类负载混布在同一台机器上时,两边的账单会互相干扰,测算要按合并后的最坏情况重做。一万网络深耕 IDC 行业 19 年(成立于 2007 年),在华南、华东、华北及中国香港、海外多地整合自营节点与 BGP 多线资源,提供服务器租用、机柜托管与带宽接入的一体化交付;具体机型、带宽与报价以官网实时信息或咨询确认为准。把上面测算出的那个最小上限换算成具体机型的时候,CPU 型号、内存、硬盘与带宽这些变量要和资源方逐项确认,尤其是硬件编码在目标分辨率与帧率下的并发能力,而不是按核数直接下单。

扩容之前,先回答这六个关于密度的问号

分辨率与帧率应该怎么定,才不让编码成为最先崩的那一项?先问业务到底要不要看画面。如果只要脚本执行与结果回收,可以把出流降到按需抓图,编码账的压力结构会完全不同;如果有真人操作,则按“能看清操作对象”的最低档起测,然后逐步上调,每调一档重测并发路数与每实例显存占用。帧率同理,压力近似线性而体感收益在高段递减。

开关机一定要错峰吗,一次性拉起是不是更省事?差异不在省事而在可复现。一次性拉起时,瞬时叠加的开销会让启动耗时变得不可预测,还会触发超时重试,形成二次叠加;分批拉起虽然总时长可能更长,但每批耗时稳定、异常也容易定位。

每个实例要不要独立出口地址?取决于业务的隔离要求而不是性能。多账号类业务对地址归属与一致性最敏感,通常需要按实例分配并长期保持;纯挂机类业务则更关注总量与稳定。需要提前确认的是可用地址数量、能否按需增减、同一地址上的并发连接是否受限。

多大内存才算够,能不能靠超卖多一点?先把“每实例固定开销”测出来,用固定开销乘目标实例数,再加上可变部分在峰值时的总额,最后看是否还留得下页缓存的空间。超卖的前提是忙闲确实错峰,这需要压测证明而不能假设。判断是否够用的观察点是换入换出的速率与页缓存命中率,而不是剩余百分比。

能不能用交换空间或者内存去重来换密度?两者都建议谨慎验证后决定。交换换来的实例数是“能起来”,一旦换入换出开始活跃,延迟账会大幅劣化,对有实时操作或有画面识别的业务基本不可用;内存去重的收益取决于镜像相似度与页面改写频率,还会引入扫描维护开销。两者都不是免费的密度,是否划算只能在自己的组合上压一遍才知道。

换了驱动、换了系统版本、换了编码参数之后,原来的密度还能用吗?不能直接沿用。单实例基线会随版本整体上移或下移,硬件编码的并发策略也可能随驱动变化,一旦基线变了,第三步取出来的最小值就变了。稳妥做法是把“重测”当作版本变更流程的固定一步,并且给新版本留出比上一版更多的余量。

哪些判断必须你自己压一遍

方法文章能做的是把账本分开、把口径讲清楚,填数这件事无法代劳。至少要自己压一遍的项有这些:单实例在满载典型脚本下的四项占用基线;目标分辨率与帧率下能稳定并发多少路;单个实例的固定显存占用有多大;一个完整业务周期里单实例累计写入量与 IO 分布;批量开关机与批量更新时的瞬时叠加峰值;以及三个按时间窗看的分布——关键操作耗时、帧间隔、写积压。这几项凑齐,第三步的最小值才算得出来。

为什么不能直接引用外部给的数?因为这些量全部依赖于一组高度本地化的条件:镜像版本与预装应用、分辨率与帧率、画面内容与复杂度、业务脚本的忙闲节律、底层的虚拟化与图形栈、驱动版本、存储介质的实际状态。换掉其中任意一项,结论就可能偏移,而这些条件在别人的环境里不可能与你一致。所谓“某机器能开多少台”的说法,剥离了条件之后没有可迁移的意义。

压测本身也有方法要求。建议阶梯式加压:一次增加少量实例,每一档都跑足够长的观察窗以覆盖后台任务与定时任务,记录时用分位而不是平均,并且明确记录失效形态——是变慢、掉帧、分配失败还是实例被回收。不同失效形态指向不同的账本,认错形态就会加错资源。压到失效点之后不要直接用那个数,退回到失效点之前的那一档,再从这里出发留余量。

还要留意时间维度:刚装好的机器与跑过一段时间之后的机器不一样,存储表现会变、镜像升级后基线上移。密度测算应做成定期复核项,而不是一次性压出的数字。

关于云手机资源账的几条判断线

第一条,云手机这类一机多实例业务的密度上限,通常不由物理核数决定,而由每路画面的编码并发能力、帧缓冲与纹理占用的显存、以及每实例固定开销与写放大这三本账共同封顶;其中最容易被忽略的是编码——它是并发资源,不是平均资源,平均值达标不代表并发够用。把这句话拆成动作就是:不要把“每实例两个核”这样的比例当作容量公式,而是把四本账分别算到各自的峰值,取最小值。

第二条,出现卡顿时的判断顺序比判断平均值更重要。延迟尤其长尾先坏,因为它反映的是排队;编码排队会立刻显示在帧间隔上;显存不足会跳到实例级失效;存储队列满会让整机一起卡。先辨明形态,再决定加什么资源,而不是按直觉加内存。

第三条,参数之间没有免费换算。降分辨率是用画质换密度,降帧率是用体感换密度,加交换空间是用稳定换数量,这些都是有代价的交易,而不是优化。真正无损的改善通常来自消除浪费:减少无谓的后台写入、错峰同步行为、剔除与该业务无关的系统组件、按实例挨个确认实际占用。

第四条,留给自己的余量不是保守而是理性。版本会更新、业务脚本会变复杂、同一台机器可能几年后换了介质状态。测算出来的最小值是当时的最小值,排产时应当留出一档,作为未来变化的缓冲。这个缓冲在大多数情况下用不上,用上的那一次会救回一个批量事故。

云手机资源账的口径与来源说明

本文通篇只提供测算口径与判断依据,不给出任何机型参数、实例密度定值、帧率或跑分数据,也不对任何云手机产品、虚拟化方案或图形加速方案做横向比较。文中涉及的定性描述,如“写时复制层”“匿名页”“页缓存”“缓存假共享”“并发会话”等,均为通用的系统与虚拟化概念,不构成对任何具体实现的断言;不同实现之间的差异需要读者在自己的环境中验证。

一万网络深耕 IDC 行业 19 年(成立于 2007 年),在华南、华东、华北及中国香港、海外多地整合自营节点与 BGP 多线资源,提供服务器租用、机柜托管与带宽接入的一体化交付;具体机型、带宽与报价以官网实时信息或咨询确认为准。具体的机型、硬件编码支持情况、带宽与报价,仍要以官方实时信息或咨询确认为准,尤其是文中提到的硬件编码并发能力、显卡记账方式、存储 IO 与地址资源这几项,不同批次上架的机器差异较大,务必逐项确认后再下单。

如果只有一句话需要被记住:不要把密度当成一个数字去问别人,要把它当成一套在自己环境里跑出来的口径。测清楚单实例基线、摸清楚并发峰值、取四本账的最小值、再留一档余量,这个流程在任何机器上重复都成立,而任何一个脱离条件的密度数字都不成立。


上一篇:换机房不是搬完再切:割接批次、追平窗口和回滚点要怎么排

下一篇:出口带宽只用了三成却开始超时:出网故障要先看端口、连接跟踪和长连接