图床上传系统设计分析
女主宣言
在本篇文章中,女主就带大家去分析一下图床系统的上传模块的设计与实现,让大家能够更清晰的了解,图床系统是如何支撑各业务每天数以千万级的图片上传的。
PS:丰富的一线技术、多元化的表现形式,尽在“HULK一线技术杂谈”,点关注哦!
图床上传系统每天处理各个业务上传的数以千万的图片,是目前360线上正式使用的图床系统,提供HTTP接口和SDK,支持JPEG、GIF、PNG、WEBP、ICO、BMP等主流图片格式。今天我们就来根据图床系统的上传模块的具体执行流程,来分析一下系统是如何设计部署的。
图床上传系统的难点
图床上传目前有几百亿的图片,这么多的图片应该如何存储才能保证数据安全和快速访问?
每天有数千万的上传,峰值的时候每分钟就会有几万的图片需要上传,系统要如何快速的处理这些任务?
问题解决
数据的安全存储和快速访问,这里使用了cassandra分布式数据库。Cassandra 是一个来自 Apache 的分布式数据库,具有高度可扩展性,可用于管理大量的结构化数据。它提供了高可用性,没有单点故障。关于cassandra更多的介绍大家可以到cassandra.apache.org 进行了解。
下面,我们来看一下系统的设计架构:
首先系统将任务平均分配到VIP的其中一台RS上,然后将任务保存在本地Redis队列中,随后被gearman抓取到此任务,然后将任务分配给其它worker进程继续处理直到任务处理完毕。
以下内容如果未特别说明,redis为RS对应的本地redis。
下面,以HTTP上传接口为例,来分析具体执行流程。
PHP伪代码:(上传一个二进制图片数据和一个url地址,并判断是否是二维码)
1
用户调用接口
用户上传数据到接口,系统保存任务到redis队列中,如下图。无论是传递了单张还是多张图片,都会为此次请求任务分配一个唯一的groupid,循环分析每一个IMGSTREAM,如果是url不做处理,如果是图片二进制内容,就将内容保存到redis中,保存的key针对每一个图片都是唯一不变的。
在分析下一步之前,先了解一下下面相关词语。
ReqQueue
正在处理(需要处理)的队列类
PreReqQueue
预处理的队列类,只有ReqQueue的队列长度为0,才会将PreReqQueue加入ReqQueue队列中
Imgkey
图片加密后的名称,不包含后缀,redis和cassandra中的数据都是根据此key存入的,针对每个图片都是唯一的
Groupid
组任务。每次http接口调用或SDK调用,都会分配一个唯一的groupid
Taskid
每一个图片及其处理规则都会包含在一个taskid中
Groupid和taskid的关系
一个groupid可以包含一个taskid
一个groupid可以包含多个taskid
gm_client 任务的发起者用于将任务分配给worker
Worker
处理任务的进程,系统中共有以下几种worker
req_distributor
将redis队列中的数据通过一定算法分配给GroupDistributor
GroupDistributor
将任务根据任务数据明细,分配给TaskFetch或TaskProc
TaskFetch
获取url的图片内容并保存在本地redis
TaskProc
处理rule规则,存储图片到cassandra
GroupComplete
任务结束时的处理程序
GroupCallback
如果注册了回调url,则触发这个worker进行处理
2
gearman client分发任务
在这一步中,RS会有一个req_distributer进程,用来分发ReqQueue和PreReqRueue队列任务,分发到GroupDistributor进程。只有当ReqQueue队列为空时,才会处理不需要及时处理的PreReqQueue队列,防止ReqQueue队列产生积压。
现在,我们看到了任务的两个状态阶段,req_distributor(开始任务分发),GroupDistributor(开始处理任务),除了这两个阶段,任务还有以下四个阶段TaskFetch 、TaskProc、GroupComplete GroupCallback,在第一步中,已经解释过了。当然,一个任务不一定六个状态都会经历,其中req_distributor、GroupDistributor、TaskProc、GroupComplete是必经阶段。
让我们熟悉一下,后五个阶段是如何转变的,如下图:
结合第一步的状态说明还是很好理解的。
3
TaskFetch根据url获取图片内容
如果上传的为二进制数据,则无此步,直接进入TaskProc阶段。下面来看一下它的具体执行流程。
先根据url地址获取图片,如果获取成功,就保存到RS的redis队列里面,key则是根据图片内容计算出来的唯一值(和第一步保存内容是相同的),然后分发到TaskProc。如果图片获取失败,那么会分发到GroupComplete。至此TaskFetch就结束了。
4
TaskProc处理图片规则
这一步用来处理上面的代码里RULES内容的,用来对图片做进一步的处理,像水印、裁剪、缩放、人脸识别、二维码识别等等,都是在这一步处理的,下面让我们用图片方式分析它的执行过程。如下图:
需要注意的是如果一个图片指定了多个规则,会依次按顺序进行处理,所以在指定规则时,要想一想指定的规则和顺序是否合理,否则最终的图片可能不是你想要的结果就不同了。
5
GroupComplete 组任务处理
由于一个组任务可能有多个图片任务,即多个taskid任务,在每一个taskid任务变成GroupComplete后,就需要判断组任务是否已经全部完成,如果未全部完成,标记未完成任务减一,如果组任务全部完成,标记组任务完成。
6
GroupCallback 回调用户url(非必须)
如果用户在调用接口时,传递了回调url,则在任务执行GroupComplete时标记组任务全部完成后,会分发到GroupCallback处理。通知调用者任务已经完成,以及任务的详细信息,类似于支付API里的notify_url功能。
7
补充说明
关于六个任务状态分别分配的进程数:
req_distributor是纯IO的操作,所以分配了1个进程
GroupDistributor 也是起到了任务分发操作,目前分配8个进程
TaskFetch 比较消耗时间,建议多一些,目前分配400个进程
TaskProc 也消耗一定时间,建议多一些,目前分配300个进程
GroupComplete 目前分配50个进程
GroupCallback 比较消耗时间,建议多一些,目前分配300个进程
总结
图床上传系统使用了开源软件cassandra、gearman、redis、nginx、lvs、php等,以上软件在互联网里有着广泛的用户,也证明了这些软件的稳定性是非常好的,也是保证图床上传系统能够保持持续稳定可扩展的原因之一。希望以上的知识对大家在平时学习工作中带来帮助。
图床上传系统设计分析相关推荐
- 四合一图床上传-高速Cdn图床百度/新浪/360/搜狗图床
介绍: 四合一图床上传-高速Cdn图床百度/新浪/360/搜狗图床 网盘下载地址: http://kekewl.net/tpWD1OMzf9L 图片:
- 【PicGo】解决picgo+github图床上传的各种问题
摘要 在使用picgo+github搭建博客图床的时候,通常会遇到上传失败等问题,如下图所示: PicGo并不怎么稳定.下面介绍一种完美解决的方案,亲测有效! (图片OK,但是视频上传目测不可:另,就 ...
- php图床api源码,京东免费图床上传接口php源码
/* *京东图床PHP代码 */ if (class_exists('CURLFile')) { // php 5.5 $post['file'] = new \CURLFile(realpath($ ...
- php京东图床上传接口源码,京东图床上传api接口源码
if (class_exists('CURLFile')) { // php 5.5 $post['file'] = new CURLFile(realpath($_FILES['Filedata'] ...
- 利用Gitee搭建个人图床(上)
利用Gitee搭建个人图床(上) 借助冷文图床操作gitee实现图床功能 更多内容 冷文博客 图床预览http://image.kevinlu98.cn/ 冷文图床简介 一款以码云作为存储平台的图床工 ...
- 再也不怕自己用江苏图采上传证件照了(亲测有效)
再也不怕自己用江苏图采上传证件照了(亲测有效) 一.前言 各位小伙伴即将毕业的小伙伴是不是因为江苏图采不能用前置摄像头而烦恼,是不是因为拍的照片而烦恼.小编也是,然后在网上搜了各种方法,基本上都是用A ...
- 帝国Cms批量上传多图morepic上传超过最大文件2m的限制的方法
情景描述 突破虚拟主机上传文件2m限制,使用帝国cms上传任意大小图片文件. 通常来说,装修.婚纱.小视频类的网站,它们的图片都是异常的大,一般都会大于2m,. 支持上移,下移,删除,图片预览功能 但 ...
- 使用jspsmartupload完成简单的文件上传系统
请不要妄想,一个html的file控件,再加上JavaScript与jQuery语句就可以完成文件上传, 文件上传系统从来是需要配合服务器来完成的 用户把自己的文件上传到服务器上 文件上传系统是很复杂 ...
- tp框架存在的问题 不可多图同时上传
标题 tp框架存在的问题 不可多图同时上传 解决办法 :Upload.class.php 下的getSaveName函数修改即可代码如下 private function getSaveName($f ...
最新文章
- 3ds max 改变模型轴的坐标系位置
- Spring Boot 2.x基础教程:使用Flyway管理数据库版本
- parquet文件格式——本质上是将多个rows作为一个chunk,同一个chunk里每一个单独的column使用列存储格式,这样获取某一row数据时候不需要跨机器获取...
- 【ArcGIS风暴】ArcGIS中国地表覆盖数据GlobeLand30预处理(批量投影、拼接、掩膜提取)附成品下载
- xay loves trees
- java面试题8 牛客:在Web应用程序中,( )负责将HTTP请求转换为HttpServletRequest对象
- Redis, Memcache 基本使用
- Android中你可能忽略的知识点(1)-分辨率那些事
- ***测试执行标准(Penetration Testing Execution Standard:PTES)
- linux mysql导出表中的数据_MySQL导出指定表中的数据
- matlab函数文件||脚本文件和函数文件的区别
- java实现数字转英文_Java实现数字转成英文的方法
- 硬件电路设计之VGA ADL5201
- 腾讯互娱AMS | 我的打包我做主——浅析前端构建
- 深大uooc学术道德与学术规范教育第十二章
- 搭建自己的外卖红包平台,操作外卖CPS实现躺赚
- Spring高手之路——深入理解与实现IOC依赖查找与依赖注入
- 提高班兄弟姐妹一家人
- 渗透测试|移动端 nexus 6p 刷入8.1和获取root权限(magisk)
- 微信分享 | 大规模数据中心自动化运维实践