Giter Site home page Giter Site logo

zimgtree's Introduction

ZimgTree

Zimg提供如下功能
   1)所有图片默认返回质量为75%,JPEG格式的压缩图片,这样肉眼无法识别,但是体积减小
   2)获取宽度为x,被等比例缩放的图片
   3)获取旋转后的图片
   5)获取指定区域或固定大小的图片
   6)获取特定尺寸的图片,由于与原图比例不同,尽可能展示最多的图片内容,缩放之后多余的部
      分需要裁掉
   7)获取特定尺寸的图片,要展示图片所有内容,因此土坯那会被拉伸到新的比例而变形
   8)获取特定尺寸的图片,但是不需要缩放,只用展示图片的核心内容即可
   9)获取按指定百分比缩放的图片
   10)获取指定压缩比的图片
   11) 获取去除颜色的图片
   12)获取指定格式的图片
   13)获取图片的信息
   15)删除指定图片
     Zimg是针对图片处理服务器而设计开发的开源程序,它拥有很高的性能,也满足了应用在图片方面
   最基本的处理需求,

总体思路:
     想要在展现图片这件事情上有最好的表现,首先需要从整体业务中将图片服务部分分离出来,使
   用单独的域名和建立独立的图片服务器有很多好处。比如:
        1)CDN分流。 热门网站的图片地址都有特殊的域名,比如微博的是www.sinaimg.cn等等,
           域名不同可以再CDN解析的层面就做到非常明显的优化效果。
        2)浏览器并发连接数限制。 一般来说,浏览器加载HTML资源时会建立很多的连接,并行的
           下载资源。不同的浏览器对同一主机的并发连接数限制是不同的,比如IE8是10个,
           Firfox是30个,如果把图片服务器独立出来,就不会占用对主站资源连接数的限制,一定
           程度上提高网站的性能。
        3)浏览器缓存。 现在的浏览器都具有缓存功能,但是由于cookie的存在,大部分浏览器不会
           缓存带有cookie的请求,导致的结果是大量的图片请求无法命中,只能重新下载,独立
           域名的图片服务器,可以很大程度上环节此问题。
        
       图片服务器被独立出来后,会面临两个选择,主流的方案是前端采用Nginx,中间是PHP或
    者自己开发的模块,后端时物理存储,比较特别一些的,比如facebook,他们把图片的请求处理
    和存储合并一体,叫做haystack,这样做的好是haystack只会处理与图片相关的请求,比例了
    普通http服务器繁杂的功能,更加轻量级,同时使得部署和运维难度降低。

       Zimg采用的是与Facebook相似的策略,将图片处理的大权收归自己所有,绝大部分事情由自己
    处理,除非特别必要,最小程度地引入第三方模块。
       在Zimg的1.0版本,设计面向图片量在TB级别的中小型服务,物理存储暂时不支持分布式集群,
    分布式功能将在2.0版本中完成。
架构设计:
   为了极致的性能表现,Zimg全部采用C语言开发,总体上分为3个层次
       1)前端http处理层
       2)中间图片处理层
       3)后端的存储层
   http处理层引入基于libevent的libevhttp库,libevhttp库是一款专门处理http请求的库,它
   太适合Zimg的业务场景了,在性能和功能之间找到了很好的平衡。图片处理层采用imagemagick库,
   imagemagick库是现在公认功能最强,性能最好的图片图片处理函数库,存储层采用memcached缓存
   加直接读写硬盘的方案,更加深入的优化将在后续进行,比如引入TFS4等,为了避免数据库带来的
   性能瓶颈,Zimg不引入结构化数据库,图片的查找全部采用哈希来解决。

   事实上图片服务器的设计,是一个在I/O与CPU运算之间的博弈过程,最好的策略当然是继续拆:
      CPU敏感的http和图片处理层不属于运算能力更强的机器上,内存敏感的cache层部署于内存更大
   的机器上,I/O敏感的物理存储层则放在配备SSD的机器上,但并不是所有人都能负担得起这么奢侈
   的配置,Zimg折中成本和业务需求,目前只需要部署在一台服务器上,将压力放在CPU上,事实证明
   这样的思路基本没错,在硬盘性能很差的机器上效果更佳明显:即使以后SSD全面普及,CPU的运算
   能力也会相应提高,总体来说Zimg的方案也不会太失衡。
代码层面:
       虽然Zimg在二进制实体上没有分模块,现阶段面向中小型的服务,单机部署即可,但是代码上
    是分离的。

main.c是程序的入口,主要功能是处理启动参数:
-p 监听端口
-t 线程数,默认4,请调整为具体的CPU核心数
-k 最高保持连接数,默认1, 不启用长连接, 0为启用
-l 启用Log,会带来很大的性能损耗
-M 启用缓存的连接IP
-m 启用缓存的连接端口
-b 每个线程的最大连接数,默认为1024

Zhttpd.c是解析HTTP请求的部分,分为GET和POST,GET请求会根据请求的URL参数去寻找图片并转给
图片处理器层,最后将结果返回给用用户,
POST接收上传请求然后将图片存入计算好的路径中。

在Zimg中图片的唯一key值就是图片的MD5值,这样既可以隐藏路径,又能减少前端和Zimg自身的存储
压力,是避免引入结构化存储部分的关键,所有所有的GET请求都是基于MD5拼接而成的。

设想一下,加入网站的某个地方需要展示一张图片,这个图片的原图的大小为1000 * 1000,但是你
想要展示的地方只有300 * 300, 一般还是依靠CSS来进行控制,但是这样的话会造成很多流量的
浪费。为此,Zimg提供了图片裁剪功能,你锁要做的就是在土片的URL后面加上w=300&h=300(width,
height)即可,另一个场景是图片灰白化,比如某天遇到重大自然灾害,想要网站所有图片变成灰白
的,那么只需要在图片URL后面再加上g = 1(gray)即可。

当然,依托于imagemagic所提供的完善的图片处理函数,Zimg将在后续版本中逐步增加该功能,比如
水印等。

在图片上传部分,其实能玩的花样很少,但是编写代码锁消耗的时间最多,现在,再假设另一种场景,
如果我们的图片服务器前端采用Nginx,上传功能用PHP实现,需要写的代码很少,但是性能如何呢?
答案是很差,首先PHP接收到Nginx传过来的请求后,会把Http协议分离出其中的二进制文件,存储在
一个零时目录里,等我们在PHP代码里使用$_FILES["upfile"][tmp_name]获取到文件后计算MD5再
存储到指定目录里,在这个过程中有一次对哦文件是多余的,起止最好的情况是我们拿到Http请求中的
二进制文件(最好在内存里),直接计算MD5然后存储。

Zimg.c是调用imagemagick处理图片的部分,这里先解释一下在zimg中图片存储路径的规划方案。
现阶段zimg服务于存储量在TB级别的单机图片服务器,所以存储路径采用了二级子目录的方案。
由于Linux目录下的子目录数最好不要超过2000个,再加上MD5的值本身就是32位16进制数,zimg
就采用了一种非常取巧的方式:
    根据MD5的前6位进行哈希,1~3位转换为16进制数后除以4,范围正好落在1024以内,
    以这个数作为第一级子目录;
    4~6位同样处理,作为第二级子目录;
    二级子目录下是以MD5命名的文件夹,每个MD5文件夹内存储图片的原图和其他根据需要存储的
    版本,假设一个图片平均占用200KB,一台Zimg服务器支持的总容量就可以计算出来了:
        1024 * 1024 * 1024 * 200KB = 200TB
    这样的数量应该已经算很大了,在200TB的范围内可以采用加硬盘的方式来扩容,当然如果有更
  大的需求,可以试试Zimg后续的版本。

除了路径规划,zimg另一大功能就是压缩图片,从用户的角度来说,zimg返回来的图片只要看起来
跟原图差不多就行了,如果确实需要原图,也可以通过将所有参数置空的方式来获得,zimg.c对于
所有转换的图片都进行了压缩,压缩之后肉眼几乎无法分辨,但是体积将减少67.05%,具体的处理
方式为:
    图片裁剪时使用LanczosFilter滤镜
    以75%的压缩率进行压缩
    去除图片的Exif信息
    转换为JPEG格式

经过这样的处理之后可以很大程度的减少流量,实现设计目标。

zcache.c是引入memcached缓存的部分,引入缓存是很重要的,尤其是图片量级上身以后,在zimg
中缓存被作为一个很重要的功能,几乎所有zimg.c中的查找部分都会先检查缓存是否存在,比如:
    我想要a(代表设计MD5)图片裁剪为 100 * 100之后再灰白化的版本,那么过程是先去找
  a&w=100&h=100&g=1的缓存是否存在,不存在的话去找这个文件是否存在,还不存在就去照这个分辨率的彩色图缓存是否存在,若依然不存在就去找彩色图文件是否存在,若还是没有,那就去查询原图
  的缓存,原图缓存依然未命中的话,只能打开原图文件了,然后开始裁剪,灰白化,然后返回给用户并
  存入缓存中。

  可以看出,上面过程中如果某个环节命中缓存,就会相应的减少I/O或图片处理的次数,众所周知,
  内存和硬盘的读写速度差距是巨大的,那么这样的设计对于热点图片抗压就十分重要。

zimgtree's People

Contributors

qiuqiuxiaomaomi avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.