魅族图片服务2.0

魅族图片服务2.0

图片服务1.0现状及问题

  1. 使用MFS作为存储,有单点失效问题IO性能差,经常不可用.
  2. 代码耦合度高,不易拆分功能模块,难以维护和扩展新功能.
  3. 调用第三方图片处理工具的效率低下,每秒处理图片不足20张.

图片服务2.0功能需求

  1. 对图片进行处理,按需要转换为指定的尺寸.
  2. 对gif图片进行静态化处理
  3. 图片文件存储方式灵活可靠,具备横向扩展能力
  4. 图片上传/下载支持自定义路径
  5. 支持用户直接上传图片到图片服务器,避免占用业务服务器带宽.

设计说明

设计目标

  1. 模块松散耦合,可以简单拆分,预留演化为分布式的空间 2. 存储设备可以灵活选择替换,并且高可用
  2. 业务可以低成本接入
  3. 为业务提供丰富的上传/下载图片方式

图片模式表达式设计 模式表达式分为尺寸说明和修饰符两部分,一个模式表达式可以包含一组尺寸说明和多个不同的修饰符.

尺寸说明表示为[X*Y*]W*H*[.ext], 表示期望图片处理得到的结果的最终尺寸,“*”可以替换 为数字.

  • W*H* : 结果图片的宽高
  • X*Y* : 左上角在源图上的坐标,可选 .ext : 结果图片的格式扩展名

修饰符表示从处理源图得到目标尺寸结果的方法,例如“居中裁剪”,“等比缩放”等等.多个修饰符尺寸说明间使用“_”进行分割.

现有的修饰符如下:

  • CENTER : 居中裁剪
  • MAX : 不超过W*H*指定的尺寸
  • CUT : 从源图的X*Y*开始裁剪W*H*
  • AUTO: 自动降低图片质量
  • FIT : 先按W或H进行等比放大,然后裁剪为目标尺寸 B : 处理后的结果图片边界尺寸不能超过原始图片 GIF1 : 取gif图片的第一帧

实例:
X50Y50W100H100_CUT : 从源图的(50,50)坐标点开始裁剪长宽均为100的图片.

W200H200_B_GIF1 : 取出gif图片的第一帧,如结果图片尺寸<200*200,则保持原有尺寸 不变.

图片处理方案

图片处理能力沿用1.0使用的第三方工具GraphicMagick(gm)+im4java,升级到当前稳定版 的最新版本.1.0中使用gm命令处理图片,该命令每次启动一个进程处理完图片就退出了, 在并发处理图片时进程频繁创建销毁效率低下.

通过查阅GraphicMagick文档发现 gm batch 命令处理完图片之后不会退出进程,而是会 从标准输入中等待下一张图片进行处理.利用该特性,重新实现im4j的ImageCommand接 口.并对 gm batch 进程进行池化管理,提高图片处理效率.最终实现经过测试,在魅族标准 化服务器环境下(6核CPU),每秒可以处理270多张图片,是1.0的20倍左右.

元数据结构设计与存储

图片上传后需要保存图片的元数据,用于进行图片在存储设备中的定位和缓存图片的尺 寸格式信息.数据结构可以表示为如下形式:

{
  "_id": "c5f41e85dccc4445eba7ef92e9e3045a",
  //图片的唯一标识
  "bizId": "uc",
  //图片所属的业务id
  "storageId": 1,
  //保存图片的存储设备id
  "url": "uc:/83/44/39/20/00/8344392",
  //图片的自定义url可以为null
  "size": 7,
  //占用的磁盘空间,单位KB
  "files": [
    //图片文件列表,第一个是源图,其余是被访问后生成的图片
    {
      //图片的模式表达式
      "model": "W300H300.PNG",
      //文件的md5
      "md5": "3b80b0347254e9ef511ebcb6daea39e7",
      //文件在存储设备上的路径
      "path": "group2@M00/00/00/rBADO1cN_DmAAIvCAAAeQnH7sUY998.PNG",
      "size": 7
      //文件占用的磁盘空间
    },
    ...
  ],
  "updateTime": "2016-04-13T07:58:48.318Z"//最后更新时间
}

该数据结构解释为如下描述:

一个“图片”隶属于一个“业务”,可以包含多个文件,保存在同一个“存储设备”上.

对图片元数据的查询需求99%都是根据图片ID的定位查询,对其的操作也无须事务保障. 基于此,使用nosql数据库可以更加简单的维护上述数据结构.

mongodb作为一种相对成 熟的方案,具有原生的分片集群方案,具备良好的横向扩展性.

在运维方面,mongodb的分片方案也比较容易部署,在公司内部也有实施经验.

对开发人员来说集群是透明的,不需要额外的编码支持.相比mysql这类关系数据而言,往往需要在编码层面提供分表分库支持,才能组织利用集群,且扩容时很难避免数据迁移操作.这类操作的运维成本往往较高.

安全性上,mongodb集群提供副本集能力,且在API级别提供丰富的操作副本的能力,对当个文档的操作提供原子性保障.

性能上,经过测试对上述数据结构基于ID的查询支持每秒2万次以上(不是极限性能,只是 根据当前图片服务访问量需求进行的指标测试)

故图片2.0选用mongodb3进行元数据存储

高可用文件存储存储设备方案

在图片服务2.0中,建立存储设备抽象隔离具体使用的存储设备,理论上可以支持任何存 储方案,例如NFS,MFS,FastDFS.最终经过咨询和资料调研,选择了FastDFS作为主要存储设 备方案.FastDFS适合小文件的分布式存储,而图片类文件一般都符合FastDFS的小文件定 义,且FastDFS没有1.0使用的MFS的单点问题.
存储设备定义:
1. 可以持久化保存图片文件的设备.

  1. 上传图片到该设备返回字符串标示(例如底盘上的存储路径),根据该表示可以定位读 取该文件.

  2. [可选]提供HTTP下载能力

存储设备可以配置为公共的,或者某个业务独享的.多个存储设备间可以配置为加权轮询方式使用,提供IO的横向扩展能力,和一定的容灾能力.
这里写图片描述

软件架构

图片服务2.0分为4个解耦的独立模块

  1. 接入服务 : 暴露对外的上传/下载接口

    • 上传 业务服务器直接上传图片,需要传入业务id和预分配的secret_key,并对请求进行签名.以防止非法上传文件. 外部用户上传图片,需要先通过业务服务器申请授权token以识别上传的图片隶属于哪个业务.

    • 下载 下载服务是公开的,使用CDN进行缓存.

    下载可以使用三种URL
    1). http://image.meizu.com/image/{业务ID}/{图片ID}
    2). http://image.meizu.com/get/{自定义或原始图片地址} (图片地址由上传时传入的参数 决定)
    3). http://{业务原始图片服务域名}/{业务原始图片服务地址}

  2. 图片处理 : 调用gm batch命令进行图片处理,管理命令进程池. 处理命令抽象为三步,解析模式表达式->生成gm命令参数->执行命令->返回结果

  3. 存储服务 : 管理存储设备和业务关系,对其他模块提供图片读写服务
  4. 授权服务 : 对外部用户上传图片操作进行鉴权/授权 授权token设计为业务ID+16位随机字符串,可以由业务设置有效时间.

下图为各模块与外部协调交互完成上传/下载操作的示意图:
这里写图片描述

部署架构

这里写图片描述

业务接入方式设计

  1. 如果业务没有原始图片,可以直接使用提供的JAVA-SDK进行接入.

  2. 如果业务原本使用其他存储方案已经保存了大量图片,迁移图片的过程是痛苦的. 图片服务2.0提供了托管下载模式. 流程图如下:
    这里写图片描述
    通过将业务的原始服务器内网ip地址配置在图片服务2.0的配置中心,然后直接将域名DNS解析到图片服务的ip地址即可对外不间断提供图片下载服务(使用下载地址3)方 式).不改代码,不改图片地址,完全无缝接入. 如果受条件限制不能配置DNS解析,则需 要更改原始图片下载地址的前缀为图片服务约定前缀(下载地址2)方式). 无须改动业 务逻辑代码.

猜你喜欢

转载自blog.csdn.net/u012631045/article/details/81482665