热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

又拍云图片处理集群架构

又拍云图片处理集群架构|黄慧攀,又拍云CTO。最早在2001年开始web开发工作;2006年创办yo2.cn优博网(W

黄慧攀,又拍云 CTO。最早在 2001 年开始 web 开发工作;2006 年创办 yo2.cn 优博网(WordPress 博客平台);2010 年加入又拍云开始构建第一代云存储和云 CDN 服务。曾从事前端、后端和服务端等工作,目前主要从事技术架构工作。

又拍云的云处理服务包括图片和音视频处理服务,其中图片处理系统每秒处理图片数量 3000 多张,一天要处理 1 亿张图片左右。图片处理服务面向的客户主要有电商、图片社交两类,他们也是图片处理需求的大户,其他类型的客户对图片处理需求比较少。
选择适合业务场景的系统架构
我们今天不谈具体产品,只讨论系统架构,很多人关注在图片处理领域选用 GraphicsMagick、ImageMagick 或者软编码或硬编码的性能高低。这些方案都各有利弊,需要按业务场景来选择。
又拍云因为是公有云处理服务,使用场景和作图功能要求很泛,什么打水印、模糊、加特效等,因此用软编码的方式是唯一选择。
对于业务只有做缩略图功能要求的,肯定是硬编码的性能高。
又拍云图片处理集群规模及架构
图片处理集群规模
30 台 24 核、48G 内存的服务器,相当于有 30 * (24 - 1) = 690 核的处理能力。

这是我们的狗眼监控系统,对平台每个子服务都有 QPS 和平均处理耗时等关键指标的监控。上图是作图集群的 QPS 统计,处理能力、处理量都很稳定。
现行架构

前端部署了 8 台 nginx 做 7 层负载均衡,这里没用 LVS 做 4 层负载均衡,由于这个场景下 nginx 本身不存在瓶颈,因此我们简单使用了 IP 轮询方式,并在业务代码中来做容错。
Nginx 中配置 30 台 GmServer 的 upstream。这其中 28 台为普通的 GmServer,另外 2 台是 BigGmServer,这个是非常特殊的角色,Why?
因为我们提供的是公有云服务,客户传什么图进来,我们是不知道的,各种各样,甚至有几十兆的 GIF 图。但这种图所占整体的比例非常小,远低于 1%。所以我们只部署了 2 台 BigGmServer 来做这部分的处理任务。
自研的 GmServer
GmServer 最重要的策略特性是:
Server 只并发处理 CPU 核数以内的任务,如果超出了就返回 502,让 nginx 做容错处理,选择下一台处理服务器。
这个架构策略比选用哪个图片处理库重要得多。
因为在并发数超出 CPU 处理能力的时候,整体的处理性能下降比较严重,大家都在抢占 CPU,结果是大家都做不好。
GmServer 是基于 Linux + epoll + GraphicsMagick 开发的,在可控范围内做到全部内存处理图片,不走磁盘 IO。
对于 GraphicsMagick 本身还有不少处理逻辑会使用到本地磁盘 IO,我们把这部分放到 /dev/shm 上。
服务器 48G 内存,才 23 个并发任务,所以是绝对够用的。完全基于内存做处理,可以避开磁盘 IO 的损耗,取得最高性能。
另外一个大头是修复 GraphicsMagick 的 BUG 和新功能的添加。因为是公有云,所以接收的图片各种各样,甚至有些是缺损的或者是经过“变态”压缩的 gif,GraphicsMagick 不一定能够识别和处理。
我们有专人长期在为此而战斗,并且这些 BUG 修复一般都会提交给 GraphicsMagick 官方,用以给开源社区一些贡献。
比如最大的一个就是 WebP 格式的支持,是我们工程师给 GraphicsMagick 提交的。

又拍网到现在的又拍云,使用 GraphicsMagick 有 6~7 个年头,在这方面的技术和经验积累非常多。如果您在使用过程中遇到特殊无法处理的图片,可以邮件联系找我们看看是否能做到兼容处理:huipan.huang@upai.com。
任务调度逻辑详解
处理图片任务 a(普通图片)
8 台 nginx 中随机选 1 台,再 nginx 把任务随机分配给 1 个 GmServer,处理完成。
处理图片任务 b(大图片或者大 GIF)
8 台 nginx 中随机选 1 台,再 nginx 把任务随机分配给 1 个 GmServer,处理 5 秒超时返回 413。再由 nginx 把任务分配给 BigGmServer。
这个 5 秒超时是很特殊的经验值,对于小图片处理都是几十毫秒的事,2k 分辨率的也就百毫秒,所以 5 秒以上的图片就特别变态了。
为了保障绝大部分普通图片的处理服务,所以我们把这种变态图片扔到 BigGmServer 去处理,BigGmServer 配置的任务超时时间是 60 秒。
为什么要扔到 BigGmServer?请想象一下普通处理集群,被变态图片占满会出现什么效果?
因为 nginx 的 7 层负载均衡还带容错能力,1 个变态图片进来处理不了,会尝试其他机器,不一会儿整个集群都被这个变态图片给占了,所以我们有必要把任务分类处理的。

(任务 a、b、c 示意图)
处理图片任务 c(普通图片)
这里有个前提假设:我们的 GmServer 只能做 2 个并发任务(否则我画图得画 24 个)即目前状态下 GmServer 不会再接收任务。新来的 c 任务会返回 502,让 nginx 重新选择一台 GmServer 来处理任务。即使遍历集群也就 20ms 以内,一般下一跳就能得到处理了。
现行架构的优缺点分析
一般每周 review 一下处理的 QPS,关注一下吐出的错误码比例,能准确判断到集群是否过载,提前能做好扩容工作。
当前架构优点
服务稳定,过载时业务不会全面受到影响。
架构简单、通用。
当前架构不足
动态扩容不友好,因为架构太简单,动态扩容的实现复杂度高一些,因为需要跟 nginx 做联动。为此要配置自动发现和 nginx 动态配置 upstream 等(当然这块用 nginx + Lua 很好做)。
最近 Docker 很火,我们也有在关注这方面的技术。综合分析下来,打算做一套新的架构,把我们图片处理和音视频处理,原来两套独立的集群混合起来,把资源利用率做上去。
未来的新架构方向
Nginx 改为使用自己研发的 ServiceServer,基于消息队列实现任务排队。此前的 GmServer 转为 GmWorker,主动对接消息队列来处理任务。

这个架构的优点是:Worker 轻量级,且很容易做动态扩容,因为 Server 端不需要配置 Worker 信息,Worker 在启动时主动向 Server 申报身份和认领任务。接下去配合 Docker 的动态扩容就非常方便。
这里有个重点是
ServiceServer 可支撑图片集群、音视频处理,甚至普通 Web 请求任务。
Worker可混合部署。
Worker 不需要做服务监听,可以很方便的用 docker 横行扩展。
如果想走捷径,可以考虑 nginx Plus 版本的 7 层负载均衡支持队列功能,也能达到这个效果。但也有最大的缺点:$1900 / 单机 / 年。当然这个 nginx 的方案,做 docker 的横向扩展时,还是逃不掉跟 nginx 做联动、自动发现等事情。
运营中遇到过的坑
集群自身是没遇到过什么大的坑,只有些小逻辑 bug 的问题。但在服务上有缓存失效和业务攻击的问题,需要做自动降级和适当屏蔽。
先参考下我们的服务架构

缓存失效时候的高可用设计
数据中心缓存有磁盘损坏或者服务器故障时,会导致大部分的缓存失效,从而导致落到作图服务的请求数增大好几倍。而作图服务是无法承受如此大压力的,所以我们允许向用户吐 503 错误码。
注意这个错误码要配置起码 1 分钟以上的缓存失效时间,以避免用户重复刷新请求。如果不设置一个让客户端缓存的时间,那这个 503 错误码吐得没什么意义了。
CDN 缓存一般不会出问题,因为它是分布式、多缓存节点的架构,服务器数量太庞大,即使有磁盘坏或者机器故障所产生的震荡都很小,不必担心。
不同租户隔离与高可用设计
但还要担心的一个是“恶意”请求,这里说的恶意是带双引号的,因为它并不是真正意义的攻击,很可能只是客户一个小变动导致。比如修改了一个缩略图版本号配置,这个操作就会导致旧版本的缩略图缓存全部失效,而要重新到作图服务处理。
如果这是个小客户,那没啥事,但如果是像花瓣网这样的大客户,就问题很严重了。平时花瓣网的图片处理量就已经占集群超过 50%,一下子翻几十倍的处理量进来,肯定会对作图服务造成影响。一个客户影响整个平台!
为此我们在 nginx 上加了针对客户的峰值控制系统,来避免这种情况而影响整个平台。
针对具体场景的优化与设计
缩略图版本号的使用确实给业务带来非常大的方便,随时可针对业务的需求切换使用不同的缩略图格式,点下鼠标马上生效。
但这也是有代价的,就是上面所说的影响。无法完美解决这个问题,要不把作图集群扩到完全无缓存都能处理的能力,要不就接受繁忙时会出现部分图片 503 错误。
而我们会考虑到成本,显然无法提供到峰值的处理能力,那势必要接受一定的错误量。但这个也是可以尽量避免,比如应用方要做缩略图版本切换时,可以考虑提前预热一段时间,灰度切换,使得这个峰值能得到一定的均衡。
图片在线服务的安全问题
另外一些缺乏经验的云厂商,也提供在线作图服务,且更方便。比如 http://a.com/b.jpg?w=100   通过参数自由配置想要的缩略图大小,试想一下,被人恶意组合url参数来刷你的作图集群,会是怎么个效果。
上面提到,如果客户有类似需求,最好自动化控制单客户占用资源,我们也是去年才提供通过 url 参数来作图的功能。 建议大家在新建这样的服务时,要多考虑周到。
Q & A
1. 前端部署了 8 台 nginx 做 7 层负载均衡,这里没用 LVS 做 4 层负载均衡。为何如此设计?
黄慧攀:这个不是性能的问题,只是开发多几行代码,或运维多一个 LVS 管理的事而已。我们是在业务代码上, {s1….s8} 随机选 1 台的。LVS 大多起负载均衡作用,但在这个场景下 nginx 本身压力很小并不存在瓶颈,因此我们简单使用了 IP 轮询方式,并在业务代码中来做容错。
2. 后端存储图片的数据库用的是什么 ?
黄慧攀:这个我们是存在云存储里面的。建议你用 Key/Value 数据库也行。
3. 后续有没有考虑将图片的处理用 GPU 做?
黄慧攀:前面说到过我们的业务需求复杂度比较高,用 GPU 会大大增加我们的研发难度和投入。目前的场景选用 CPU 的方案最适合我们。
4. 能否简单对比下 GraphicsMagick、ImageMagick 优缺点?
黄慧攀:你可以这么理解,gm 是 im 的一个基础库,im 在 gm 上做了更好的功能封装。套了层壳,性能是 gm 最好的。
5. 又拍云的图片服务是否提供 OCR 服务?
黄慧攀:暂时没这样的计划。
6. 老架构按业务区分流量和服务,胜在稳定。新架构在业务上混搭,彼此间是否有权重和流控,会不会有某类流量陡增对其他类业务产生冲击,或者说如何保障每类业务稳定?
黄慧攀:这个就看我们怎么做 Worker 部分的开发。我们每个 Worker 启动都会锁定 1 个  CPU 核上的,不会对其他 Worker 造成影响;
另外说到的任务权重,和个别业务需要突发处理的情况,我们有做考虑。先分成 2 类任务, 1、同步任务(如图片处理);2、异步任务。 我们优先处理同步任务,对每单个客户要做好全局的资源限制。
7. 我们的系统通过参数来处理图片,而业务方可能直接用链接,这样导致每次都走一遍图片处理逻辑,有什么优化方案?
黄慧攀:自己内部的服务,可以考虑增加权限及 IP 访问频率等限制即可。 如果是云服务商可以参考我上面方案。
群友:可以对参数做加密,时间戳也打进去,一方面鉴权,一方面验证请求有效期。
黄慧攀:Good idea 。其实,我还是建议用缩略图版本号。
群友:处理过的图片会存储磁盘吗?
黄慧攀:处理过的图片,不存磁盘。 但上面有 2 层缓存。
8. 上文所说 nginx 请求 gm_server 时,能否用连接池代替上面逐台尝试的做法?
黄慧攀:用连接池会导致负载不均衡的。 遍历池子的损耗很小。另外如果考虑连接池了,用上面新架构模式或许更好, 放到消息队列,Worker 来消费。
9:超时判断是在 nginx?那样虽然返回错误码了,但 gm 的转换还在进行,还是会占用资源?
黄慧攀:超时判断是 gmserver 做的,gmserver 是多进程的,自己内部直接把自己杀了。如果用 nginx 来做肯定面临你说的问题,所以非常必要自己开发这个 gmserver。
http://www.dataguru.cn/article-9063-1.html

推荐阅读
  • 第二章:Kafka基础入门与核心概念解析
    本章节主要介绍了Kafka的基本概念及其核心特性。Kafka是一种分布式消息发布和订阅系统,以其卓越的性能和高吞吐量而著称。最初,Kafka被设计用于LinkedIn的活动流和运营数据处理,旨在高效地管理和传输大规模的数据流。这些数据主要包括用户活动记录、系统日志和其他实时信息。通过深入解析Kafka的设计原理和应用场景,读者将能够更好地理解其在现代大数据架构中的重要地位。 ... [详细]
  • 2016-2017学年《网络安全实战》第三次作业
    2016-2017学年《网络安全实战》第三次作业总结了教材中关于网络信息收集技术的内容。本章主要探讨了网络踩点、网络扫描和网络查点三个关键步骤。其中,网络踩点旨在通过公开渠道收集目标信息,为后续的安全测试奠定基础,而不涉及实际的入侵行为。 ... [详细]
  • 直播带货系统中的推流技术详解
    本文介绍了RTMP(实时消息传输协议)及其在直播带货系统中的应用,并详细探讨了带货直播系统的连麦方案,包括服务端合流和客户端合流的优势与劣势。 ... [详细]
  • 本文详细介绍了Java代码分层的基本概念和常见分层模式,特别是MVC模式。同时探讨了不同项目需求下的分层策略,帮助读者更好地理解和应用Java分层思想。 ... [详细]
  • 您的数据库配置是否安全?DBSAT工具助您一臂之力!
    本文探讨了Oracle提供的免费工具DBSAT,该工具能够有效协助用户检测和优化数据库配置的安全性。通过全面的分析和报告,DBSAT帮助用户识别潜在的安全漏洞,并提供针对性的改进建议,确保数据库系统的稳定性和安全性。 ... [详细]
  • 如何将TS文件转换为M3U8直播流:HLS与M3U8格式详解
    在视频传输领域,MP4虽然常见,但在直播场景中直接使用MP4格式存在诸多问题。例如,MP4文件的头部信息(如ftyp、moov)较大,导致初始加载时间较长,影响用户体验。相比之下,HLS(HTTP Live Streaming)协议及其M3U8格式更具优势。HLS通过将视频切分成多个小片段,并生成一个M3U8播放列表文件,实现低延迟和高稳定性。本文详细介绍了如何将TS文件转换为M3U8直播流,包括技术原理和具体操作步骤,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 服务器部署中的安全策略实践与优化
    服务器部署中的安全策略实践与优化 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • 在处理 XML 数据时,如果需要解析 `` 标签的内容,可以采用 Pull 解析方法。Pull 解析是一种高效的 XML 解析方式,适用于流式数据处理。具体实现中,可以通过 Java 的 `XmlPullParser` 或其他类似的库来逐步读取和解析 XML 文档中的 `` 元素。这样不仅能够提高解析效率,还能减少内存占用。本文将详细介绍如何使用 Pull 解析方法来提取 `` 标签的内容,并提供一个示例代码,帮助开发者快速解决问题。 ... [详细]
  • 深入探索HTTP协议的学习与实践
    在初次访问某个网站时,由于本地没有缓存,服务器会返回一个200状态码的响应,并在响应头中设置Etag和Last-Modified等缓存控制字段。这些字段用于后续请求时验证资源是否已更新,从而提高页面加载速度和减少带宽消耗。本文将深入探讨HTTP缓存机制及其在实际应用中的优化策略,帮助读者更好地理解和运用HTTP协议。 ... [详细]
  • 在Java分层设计模式中,典型的三层架构(3-tier application)将业务应用细分为表现层(UI)、业务逻辑层(BLL)和数据访问层(DAL)。这种分层结构不仅有助于提高代码的可维护性和可扩展性,还能有效分离关注点,使各层职责更加明确。通过合理的设计和实现,三层架构能够显著提升系统的整体性能和稳定性。 ... [详细]
  • 小王详解:内部网络中最易理解的NAT原理剖析,挑战你的认知极限
    小王详解:内部网络中最易理解的NAT原理剖析,挑战你的认知极限 ... [详细]
  • Nginx不仅是一款轻量级的高性能Web服务器,还具备出色的负载均衡和反向代理功能。它支持复杂的正则匹配规则、动静内容分离以及灵活的URL重写功能,使得配置和管理更加便捷高效。此外,Nginx提供了多种负载均衡算法,如轮询、加权轮询、最少连接数等,以满足不同应用场景的需求。 ... [详细]
  • HTTP(HyperTextTransferProtocol)是超文本传输协议的缩写,它用于传送www方式的数据。HTTP协议采用了请求响应模型。客服端向服务器发送一 ... [详细]
  • Android开发技巧:使用IconFont减少应用体积
    本文介绍如何在Android应用中使用IconFont来显示图标,从而有效减少应用的体积。 ... [详细]
author-avatar
mobiledu2502878243
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有