推ter是如何做到每秒处理3000张图片的?
AmberMaynar
9年前
<p> 如今,推ter 每秒可以创建并保存 3000 张(20GB)的图片。2015 年,推ter 甚至从对媒体存储策略的优化中节省出了 600 万美元。 </p> <p> 但并非一开始就是这样的,2012 年 推ter 还主要是基于文本的,就像《哈利波特》中的霍格沃茨魔法学校没有了那些悬挂在墙上的炫酷活动照片一样。如今已经是 2016 年,推ter 已进入了富媒体未来时代。在新媒体平台发展的过程中,推ter 可以支持照片预览、多张照片、gif 图、Vine 短片以及在线视频。 </p> <p> 推ter 的软件开发工程师 Henna Kermani 在 Mobile @Scale London 的谈话中提及,这个媒体平台每秒能够处理 3000 张图片。虽然这次谈话的主要话题是讨论图片管道,但她表示其中的大多细节也适用于其他的媒体类型。 </p> <p> 这次谈话所总结的心得中,一些最有趣的内容摘录如下: </p> <ul> <li>按照可能奏效的最简单方式来执行,结果真的会让你大吃一惊: 发送一条带图片的推特是一个要么全有要么全无的操作,最简单的方式就是锁定。由于无法很好地扩展,尤其是网络状况不佳的情况下,推ter 很难再增加新功能。</li> <li>分离处理: 将发推与发送媒体分离,通过解耦的方式来处理,推ter 便可分别优化各个途径,同时还能大幅增进操作灵活性。</li> <li>移动 handle(句柄),而不要移动 blob(二进制大对象): 不要在系统中执行大块的数据移动,这样会消耗掉带宽,并导致接触到数据的各个服务有性能上的问题。请存储数据,并使用 handle 来引用。</li> <li>改用分段的、可恢复的上传操作能够大幅降低媒体上传的失败率。</li> <li>实验与研究: 推ter 在研究中发现:将各类图片变体(缩略图、小图、大图等)的 TTL(存活时间)设为 20 天可以让存储与计算达到最有效、最优秀的平衡。图片在 20 天之后的访问概率很低,删除后每天能节省下来的存储空间几乎有 4TB——达到计算服务器需要数值的近乎一半,这样做之后每年能节省数百万美元。</li> <li>按需操作: 我们可以删除旧图片的变体,是因为它们能在瞬间完成重建,而无需预计算。根据需求来执行服务能够增加灵活性,并在任务执行的方式上更为智能,控制时也更集中化。</li> <li>渐进式 JPEG(Progressive JPEG)是标准图片格式的真正优胜者:不但前端和后端对其支持都很优秀,在速度较慢的网络中,这类图片的效果也很好。</li> <li>在 推ter 发展为富媒体未来的过程中,有许许多多好事发生,让我们来一一解读。</li> </ul> <p><strong> 过去——2012 年的 推ter</strong> </p> <p><strong> 写入方式</strong> </p> <p> 用户在应用中编辑一条推文,或许再附上一张图片。 </p> <p> 客户端将这条带图推文发送给单一整体式端点。上传时,推文中的图片和其他元数据是捆绑在一起,发送给过程中所涉及的单体服务的。 </p> <p> 在旧式设计中,端点就是诸多问题产生的根源。 </p> <p> <strong>问题一: 浪费大量带宽</strong> </p> <p> 创建一条推文与上传媒体,两者在一个操作中紧密耦合。 </p> <p> 上传的动作是一个整体,要么全部成功,要么全部失败。无论失败的原因是什么——网络临时中断、暂时出错等等,都需要将整个过程从头来过,包括要重新上传媒体。如果在上传到 95% 的时候出现故障而导致失败,就必须重新再次上传。 </p> <p> <strong>问题二: 对较大的新型媒体来说,缺乏良好的扩展</strong> </p> <p> 这种办法缺乏针对大型媒体,比如视频的扩展性。媒体越大,失败的可能性也越大,特别是在 IT 业的新兴市场,比如巴西、印度、印尼等地,由于网速慢、网络可靠性差,这个问题更加严重,确实很需要增加上传的成功率。</p> <p><strong> 问题三: 内部带宽的使用效率低下</strong> </p> <p> 终端与 TFE(推ter 前端)相连,而 TFE 则负责用户身份验证,并将用户分配到不同图片服务器(Image Service)。 </p> <p> 图片服务器与图片变体生成器(Variant Generator )会话,并生成不同大小的图片实例(比如小图、中图、大图、缩略图)。图片变体存储在 BlobStore 中,这是一个针对类似图片和视频等大型有效载荷而优化的 key-value 存储系统,存储在其中的图片是永久性的。 </p> <p> 创建及保存推文的过程中,还涉及了许多其他服务。由于终端是单一整体式的,媒体与推文的元数据结合在一起,也会流经所有的服务。这个大型有效载荷被发送给直接负责图片的服务,这些服务并不属于媒体管道,但仍被强制执行大型有效载荷的优化。这种办法在内部带宽中效率非常低。 </p> <p> <strong>问题四: 臃肿的存储空间</strong> </p> <p> 推文中的图片在数月或数年后已经不再会被调用了,但仍存于 BloStore 中占用空间。有时甚至在推文被删除后,图片仍存在于 BlobStore 中,缺乏垃圾回收机制。 </p> <p> <strong>读取方式</strong> </p> <p> 引入了名为 MinaBird 的 CDN 源服务器(Origin Server )。 </p> <ul> <li>MinaBird 可以与 ImageBird、VideoBird 对话,因此如果没有的话,可以立即生成相应大小的图片及视频格式。</li> <li>MinaBird 在执行客户端请求时,更为动态也更为流畅。比如因为版权问题而需要将某个内容屏蔽,使用 MinaBird 可以很容易地对特定某条媒体执行屏蔽及恢复的操作。</li> <li>能够实时生成需求大小的图片与视频格式转码,推ter 在存储上的智能性也更高了。</li> </ul> <p> 按需生成要求的媒体变体意味着无需在 BlobStore 中存储所有的变体。这是一个巨大的胜利。 </p> <p> 原始媒体直到删除前都存储在 BlobStore 中,而变体只保存 20 天。媒体平台团队做了很多关于最佳保存时限的研究,所有请求的图片中,大约 50% 只保存 15 天,按收益率递减结果,删除较早的图片。很旧的媒体很可能没有人会发起相应的请求,在 15 天后会有很长的长尾期。 </p> <p> 如果不设定 TTL(存活时间)和过期时间,每天增加的媒体存储量有 6TB。懒办法就是按需生成所有媒体变体,导致媒体存储增长为 1.5TB。20 天 TTL 所使用的存储空间比懒办法多不了多少,因此不会占用太大的存储空间,但在计算上这是一个巨大的胜利。使用懒办法来计算,读取所有变体需要在每个数据中心设置 150 个 ImageBird,而使用 20 天 TTL 的话,只需要 75 个 ImageBird。因此 20 天 TTL 是令计算和存储达到最有效、最平衡的时间点。 </p> <p> 由于节省存储空间和计算资源就是节省金钱,引入 20 天 TTL 之后,在 2015 年 推ter 节省下了 600 万美元。 </p> <p> <strong>客户端优化(安卓)</strong> </p> <p> <a href="/misc/goto?guid=4959671728773023350">在使用 WebP(谷歌创建的一种图片格式)</a>进行了 6 个月的实验之后, </p> <p> 这种图片比相应的 PNG 或 JPEG 图片要小 25%。 </p> <p> 这样一来,特别是在新兴市场,由于较小的图片对网络压力也较小,因而用户参与度也更高。 </p> <p> 由于不支持 iOS 系统,并且只支持安卓 4.0 以上的系统,缺少平台的支持使得 WebP 格式花费巨大。 </p> <p> 于是 推ter 尝试了另一个选项,渐进式 JPEG 格式。由于通过连续扫描的形式来渲染,首次扫描可能是块状的,但在连续扫描的过程中会逐渐自我完善。 </p> <p> 这种格式的性能更佳。 </p> <p> 后端很容易支持。 </p> <p> 这种格式比传统 JPEG 格式的编码速度慢了 60%,由于一次编码,多次服务,因此这不算大问题。 </p> <p> 渐进式 JPEG 图片不支持透明图片,因此保留了透明的 PNG 图片,除此之外其它都使用了渐进式 JPEG。 </p> <p> 客户端由 <a href="/misc/goto?guid=4958869680969840391">非死book 的 Fresco 库提供支持</a>,Fresco 的优点很多。在 2G 网络下,效果令人印象深刻。第一次扫描 PJPEG 图片只用了 10kb 流量,因此加载时间不长,在本地管道还等待加载,什么都没显示的时候,PJPEG 已经显示出了可识别的图像。 </p> <p> 有正在进行的实现结果显示,负载细节如下:减少了9% 的 P50 加载时间,减少了 27% 的 P95 加载时间,减少了 74% 的失败率,慢速连接的用户确实能获得极大改善。</p> <p>来自:iteye</p>