干货 | 携程图片服务架构

标签: | 发表时间:2018-04-18 21:34 | 作者:
出处:https://mp.weixin.qq.com
作者简介 

胡健,携程框架高级研发经理,目前负责多媒体服务的构建和研发工作。


近些年携程业务突飞猛进,用户遍及世界各地。公司对用户体验也越来越重视,每一个小的功能改动、页面改版的背后,都有大量的A/B实验提供保障。与此同时,与用户体验息息相关的媒体文件的应用质量也被放到重要位置,如图片加载延时、成功率、清晰度等数据。


本文将分享携程图片服务架构,包括服务架构的演变过程,以及在生产上实际遇到的一些问题,避免大家重复踩坑。 


一、服务架构


1、初始阶段


携程图片的服务架构主要经历了三次比较大的调整。早些年为了满足业务快速上线的需求,我们做了简单实现,架构如下:



这个架构开发工作量不大,因为当时业务对图片尺寸的需求单一,也没有复杂的图片组合处理需求,因此有大量图片都被Squid缓存住,缓存命中率很高,取图速度非常快。


图片裁剪命令的执行,则由业务发布的时候上传处理。存储通过NFS让整个Nginx服务集群共享。直到移动端流量开始爆发的时候,这个架构有点力不从心。    


首先,同一张原图需要裁剪出大量不同尺寸的小图片,占用了大量存储资源。其次,业务图片越来越多加上大量不同尺寸的小图片的出现,导致Squid缓存命中率变差,大量流量穿透到NFS上,I/O迅速变为瓶颈。


从监控看,当时的NFS Read I/O一直处于高水位水平,告警更是24小时不断,回源流量的上升也导致Squid服务集群开始变得不稳定,经常需要重启。鉴于这些问题,我们做了下面架构上的调整。

 

2、发展阶段



用Varnish替换了Squid,作为缓存和反向代理服务。


从实际监控情况看,同等压力下Varnish的表现比Squid更稳定,Varnish虚拟内存swap机制比Squid自己管理的更好,因此性能上更优,并且Varnish配置方便,对运维友好。


当然Squid也有更适合的使用场景,选择Varnish是因为在当前场景下更符合我们的需求。


为了解决Varnish节点宕机会引发大量缓存数据失效,LB上对URL做了一致性Hash,这样能尽量减少缓存失效带来的其他节点数据的迁移,同时也解决了Varnish利用率的问题。


Nginx内嵌Lua脚本用于在图片访问的时候直接对图片进行处理,而不是上传的时候处理,这样很多不同尺寸的小图不用在存储上保留,存储上少了大量I/O,并且减少存储量的同时也会减轻运维的压力。


从访问效率看,因为图片需要实时处理,服务响应延时相比上一个版本有大幅上升,平均延时大概在300毫秒左右。但是这个影响实际对端的影响有限。


首先,国内CDN普遍质量较好,95%以上的图片资源访问都会被CDN挡掉,正常情况下回源流量不会太大。其次,我们Varnish集群命中率大概在40~50%之间,所以整体图片实时处理压力占整体流量约1%~2%之间,这些流量访问延时会上升300毫秒左右是完全能够接受的。


存储用FastDFS替换了NFS,当时Ceph还不像现在那么稳定,FastDFS的特性又能够满足我们需求,并且架构简单,源码能完全掌控。事实证明,FastDFS集群完全支撑了每天数亿次的原图读写操作,并多次在多机房DR演练中完成各项指标。


当时这个架构的核心是Lua的图片处理模块,Coroutine的性能非常好,当有大量图片回源请求的时候,CPU不会浪费在线程的context switch上,开发也很直白,在I/O操作的时候不需要用异步方式编码,并且Lua的执行在Nginx里足够高效。


这里唯一的缺点是Lua扩展性相对较弱,很多模块需要自己写,比如对接我们自己的监控系统的时候就遇到难题。 


随着业务的发展,用户对图片的处理要求越来越高,多重滤镜的应用,需要在Lua里实现很多功能,并且很多基础数据结构都要自己写或者依赖第三方,不仅开发工作量大,稳定性和正确性的验证也需要花费不少的精力。


是不是还有一种技术方案可替代,既能享受协程带来的简单,高效。又能兼顾扩展性和完善的功能包,不用重复造轮子。

 

3、现阶段


我们选择了Golang做为当前版本的开发语言,架构如下:



采用多进程单协程图片处理模型。图片库主要依赖的是GraphicsMagick,和少部分ImageMagick,通过封装cgo调用实现。


Golang调用cgo会申明一个进入syscall的指令,意味着调度器会创建一个M去执行goroutine。因此当有大量并发调用,并且图片处理足够慢,比如一张像素特别大的原图,就会引发大量线程同时存在,造成不必要context switch,CPU load看上去很高,实际效率很低。


因此我们通常会通过Master进程fork出和CPU相等数量的Worker进程做图片处理,每个进程只有一个协程来处理图片,每个进程会创建一个可配置的buffer用于保存原图的blob, 这样能最大化利用单协程的利用率。


采用这种架构当时主要还为了规避GM本身的一个问题,参考我们向作者提交的issue:

https://sourceforge.net/p/graphicsmagick/mailman/graphicsmagick-help/?viewmonth=201708.


问题描述是setjmp函数和longjmp函数在某些操作系统非线程安全,作者需要一个全局锁来保证线程安全。因此多线程调用本身是低效的。


这个问题在java或者.net封装的GM也会存在。上一个版本的Lua不存在这个问题,因为Nginx本身会fork多个Worker进程进行图片处理,并且只可能存在一个正在运行的协程。事实上Linux执行这两个函数本身是线程安全的,作者可以通过build的时候来决定是不是需要加上线程安全的flag。在发表本文的时候,作者已经在最新的release中修复了这个bug。


这里的Nginx不仅仅用来做LB,因为Nginx能提供很丰富的脚本,可以省去很多开发工作量,并且当有获取原图的需求,可以通过Nginx sendfile直接从存储取回,节省不必要的系统开销。


LB算法并不是简单的RR,我们会根据每个进程的CPU消耗,以及原图像素,buffer消耗等维度动态算出各进程的负载量,如果Nginx RR到一个负载非常大的进程,可以通过返回重定向状态码让Nginx重新跳转,这里可能会出现几次网络跳转,但是因为是Loopback,网络上的消耗相对图片处理的消耗可以忽略不计。


Master进程用来管理Worker进程,当有Worker意外Crash,则会重新拉起一个Worker进程,始终保持和CPU数量一致。 Master进程的健康安全会定期Report给监控系统做告警。 

二、小结


当前的图片服务架构,支撑了携程每天上亿次原图处理,平均图片处理延时控制在200毫秒以内,图片处理失败率小于万分之一,从发布至今节点没有出现宕机现象,偶尔Worker进程有性能问题和Crash也通过日志和分析工具逐一解决。 


如上所述,携程图片服务架构经历了三次改版,从一开始没有设计复杂的架构,只是为了解决碰到实际问题而重构,到后来根据遇到的问题,不断调整,也说明了没有完美的架构,只有适合的架构。


当然,要提供稳定图片服务,架构是一方面,也必须有其他技术上的支持,比如图片本身质量和尺寸的优化,盗链和版权问题,端到端的实时监控和预警机制,不良内容识别,产品图片管理和编辑功能,以及海外用户图片访问加速问题。这些问题每个都能写下不少篇幅的文章,有时间再和小伙伴分享。 


目前,携程图片服务已在github上开源了小部分功能,开源地址:https://github.com/ctripcorp/nephele

后续会逐步完善,欢迎PR。





相关 [干货 携程 图片] 推荐:

干货 | 携程图片服务架构

- -
胡健,携程框架高级研发经理,目前负责多媒体服务的构建和研发工作. 近些年携程业务突飞猛进,用户遍及世界各地. 公司对用户体验也越来越重视,每一个小的功能改动、页面改版的背后,都有大量的A/B实验提供保障. 与此同时,与用户体验息息相关的媒体文件的应用质量也被放到重要位置,如图片加载延时、成功率、清晰度等数据.

12款实用的HTML5干货分享

- - HTML5资源教程
今天我们要来分享12款实用的HTML5应用插件,内容涉及到按钮、表单、进度条、图片等,大家一起来看看这些干货吧. 1、漂亮的CSS3动画进度条 可自定义进度条颜色. 今天我们要再来分享一款很漂亮的CSS3动画进度条,我们可以用它来显示每一项数据的所占的比例,效果很不错. 之前我们也有分享过很多功能强大的CSS3进度条,像 纯CSS3进度条 华丽5色进度条示例、 CSS3 SVG 进度条 Loading 动画 炫酷发光特效都和今天分享的这款比较类似,可以看看.

纯干货!创业失败“备忘录”

- - i黑马
【i黑马导读】“创业不是好玩的事情,90%以上的创业一定会死,能活下来的绝对是祖坟冒青烟. 而本文作者@ 许怡然  便是那90%中的一员,作为一个屡创屡败的网游创业者,他用近八千字分享了自己遇到的融资、团队、利益兑现等问题,特详尽,特干货,特别推荐. 经历太多次创业,发现创业实在太难,一开始我认为是我的运气稍微差了一点,每一次创业失败的原因都不尽相同,使我经历了各种各样的创业痛苦,不过后来看看我周围跟我一起创业的弟兄们,发现创业的人生就是如此.

“携程们”的危机

- - 派代网 - 资讯
今年的在线旅游市场,热度绝对不逊于电子商务的任何一个领域. 继6月份艺龙、芒果网、酷讯网和途牛网等在线旅游网站陆续推出“返利促销”优惠活动之后,在线旅游行业老大携程也加入了这场混战:7月6日,携程宣布投入5亿美元(约合32亿元人民币)开展低价促销,促销活动从7月起持续一年时间,涉及酒店、机票和旅游门票等,并宣称此次促销将“拉开国内在线旅游业以价格战为前奏的洗牌大幕”.

爬取携程信息

- - IT瘾-geek
print("评分为:{}".format(userRating)). print("评论内容为:{}".format(commentText)) '''. 数据库操作 ''' #获取数据库链接 connection = pymysql.connect(host = 'localhost',.

跟易到用车CEO周航聊O2O干货

- - 云科技
易到用车是约租车领域的领头羊. 创立于2011年7月,比美国UBER早一个月. 周航:第一,必须已经有大量的存量资源,就等着互联网来整合. 第二,这些资源必须非常碎片化,微型化. 周航:餐馆对大众点评网依赖高,但快捷酒店对携程依赖就低. 团购主要瞄准了餐饮,可团购只干了营销撮合的事. 它跟传统产业的关系是增值和依附,起不了主导作用.

干货:一个网站完整详细的SEO优化方案

- - 互联网分析
根据自己的个人经验完成了这篇文章,希望对SEOer有点帮助,高手直接跳过,请勿喷水. 一个完整的SEO优化方案主要由四个小组组成:. 接下来,我们就对这四个小组分配工作. 首先,前端/页编人员主要负责站内优化,主要从四个方面入手:. 合理规划站点结构(1、扁平化结构 2、辅助导航、面包屑导航、次导航).

干货:从刷榜说起你不知道的行业内幕!

- - @i黑马
今日鸟哥接到消息,刷榜公司重新开启接受预约,预计一周内将重新开启刷榜接单,这是什么节奏. 刷榜界玩的就是心跳,不适应你就玩不了. 今天和大家探讨一个话题----刷榜到底公平吗. 大家都知道,AppStore的排名和下载量是相互作用的,有排名就有下载,反过来有下载就有排名. 这里拓展一下影响AppStore排名的因素,主要因素是下载量和时间段内的下载量变化量,也有人说还有评论、激活、活跃度以及一下特殊情况加权等,我不确定有没有这些因素,但是可以断定,即便是有,占权重也不大,那么归根到底权重最大的就是:下载量.

产品经理干货:可用性测试的那些事

- - 人人都是产品经理
可用性测试是指通过对典型用户实施测试来对产品或服务做出评价. 在一次典型的测试中,用户要完成一系列典型任务. 与此同时,观察者会在一旁观察、倾听、做笔记. 可用性测试的目的就是为了发现可用性问题,收集定性和定量的数据,并评估用户对产品的满意度. 可用性测试有助于设计和研发团队在产品成型之前发现问题.

深夜干货:如何学会视频剪辑?

- - 知乎每日精选
Q: 如何真正学会视频剪辑. 马上要大一了,虽然报了个工商管理但是从初中时就喜欢视频剪辑,从自己手里的视频里不断的加入音乐,特效,文字,不断的拼凑,我觉得让我有一种充实感,我想,如果我对它的热情在毕业后还没有递减,不出八九我以后就会进入这个行业,我打算利用大学空余时间来学习这个,我想问一下,我该需要学习些什么呢.