Moonless.net首页

Cutsin受难记

Home Blog 归宿美林湾 Labs

2008年10月22日星期三

css sprites,鸡肋还是良药?

今天技术部门的领导发给我们一封邮件,大体上是推荐css sprites,并要求我们在今后的工作中多作应用。

我的第一感觉是:我们不是闭塞虫~必须得争口气,先列举一些缺点再说…囧~

遂回复如下:
css sprites是一个比较早的概念,关于它的优点说得比较多的是:
1、减少请求数
2、减少并发连接数
3、用户体验好,用css动态交换图片没有延迟及闪烁
4、下载速度快,用户体验好
5、便于维护

但实际上这5条存在如下问题或误解:

1、http1.0没有keepalive,所以在处理一次页面请求时,小文件很多,浏览器和服务器之间除了处理数据的发送/接收还要不断“握手”,效率很低;http1.1提出了keepalive和Pipelining,服务器响应后不是马上关闭连接而是维持连接状态,当页面包含很多文件时,浏览器是排队下载的,传送多个小文件和传送一个大文件应该差不太多,但Pipelining默认都是关闭的,firefox中需要手动才能打开;

2、浏览器对每个主机名请求时的并发连接数是固定的,ie8以前是2或4,目前似乎没有超过8的,所以不存在减少并发连接的问题;

3、在IE6中,背景图片默认不会被缓存,所以即使写成background:url() no-repeat 10px -10px这样的形式,再通过background-position改变背景图位置,也是会重新请求这张图片(表现就是闪烁),以下几种情况例外:这张图片是不透明的、这张图片尺寸足够大、用js强制缓存;

4、我们都看到邮件中的那张图有23K,下载它是需要时间的,这就是说,如果使用css sprites,那么用户在浏览的时候可能出现的情况是:开始页面中没有图标,过了一会儿所有图标全出现了,我觉得不如分成一张张小图片分别加载给用户的感觉会更好些;

5、
css sprites要求图片按照规则很好得码放起来,位置很精确,相应地,在css中的定位也要非常精确,这样做肯定是要花费时间的,而且一旦需要改动,就会出现以下问题:

a. 我们知道gif、png-8都是有损压缩,生成适合web显示的图片时是要减少色彩并通过“仿色”去弥补损失的,我们生成一张图的时候,工具根据图片中的色数、灰度进行复杂的计算,最后生成图片;如果另一个人想要改这张图片(比如增加一个图标),这样整张图片的色数会发生变化,压缩时需要重新进行图片仿色,如果这张图片花花绿绿,什么颜色都有,生成的图片的每一个局部很难保证和原稿保持一致,图片尺寸越大、色彩越多,这种损失表现得更明显,多数情况下直观的感觉是“图片颜色发浅”;

b. 我们的图片服务器是有缓存的,所以假如用css srpites放置所有图标,想在增加/修改一张的话,只能重新上传一整张图片,这样,所有引用这一整张图片的css定义都要跟着修改。


总之,是有利有弊吧……
css sprite这个东西,觉得在流量特别大的地方应该着力应用,平时还是应该权衡一下,我们一直也有在用,但只用在该用的地方,还是分类处理比较好。

个人愚见,有关底层的东西估计理解的不对,还得请技术牛人给解释解释~


很多同事回复,贴个老大的出来^^:

a. CKA (Client-side Keep-Alive) 我们都是关掉的,在达到一定的访问量后,不
关掉CKA的同学会遭受 tcp 连接数过高的困扰,目前只有这两种情况下 CKA 是开的:

1。用 L4~L7 交换机做 TCP offloading,顺便打开 CKA 提升用户感受。以新闻静
态池而言,我们虽然有强大的 L4~L7 switch ...还是关掉了 CKA, 原因见前述。
2。流量小到开不开无所谓。。。


b. 浏览器的 pipe line 限制(允许同一domain name 下打开的并发连接数量限
制)正是合并细碎图形的优势所在。考虑 IE 4~ IE7 访问的情形, 缺省情况下同
一 domain name 下的内容无论有多少种 url , 只能同时存在两路连接,你有20个
细碎修饰图,就需要两个、两个、两个。。。一路排队下来。你可以说,在理想的
网络条件下,20个个图排两个队,也比1张图一次 load 下来要快。但事实上,由
于没有 CKA 的帮助,每个细碎修饰图都要发起一个单独的 http 请求,在现实世
界里,20 次 network round trip 消耗的时间远远大于传送图片那点时间开销。

对于服务器负载以及客户感受来说,把20张小图拼成一张大图,是很大的节约,首
先省掉了20个前文说到的 network round trip , 这包括 20 次 tcp 三路握手,
服务器和客户端保持 20 个 tcp session 的状态,完成 http 请求后 tcp 连接不
会立刻断掉,要在 time_wait 状态保持两倍 MSL 时间 --- 这一条就是为什么很
多访问量较大的服务器上总是有上万条 time_wait 状态的 tcp 连接的原因。

除了网络方面造成的 over load 以外,还有 20 次 tcp 连接造成的开销,客户端
我们就不计了,服务器端要接收 20 次 HTTP 请求并且作出一系列回应,这些都要
消耗 cpu 和内存。另外,你不可能控制每张图的尺寸正好凑一个或更多整数个
1500 MTU 的 tcp 包吧?每张图多出一个字节,就要多打一个包出来,20张图拼成
一张,省5、6个 tcp 包不算夸张。

对于这种难于压缩的小图片,合并起来是节约带宽和服务器资源的重要优化手段。
整个算下来,就是用制作和维护页面的辛苦以及客户端不用白不用的浏览器渲染能
力,把小图拼到一起,做了 tcp 和 http 的 offloading.


另一个老大:

顶~~~!但是在机器有足够的内存的情况下,我不认为关闭CKA是好办法,一般情况下同域名N个请求的情况下,开启5-15S的Keep-alive是有好处的,能够大量节省反复请求的网络开销。

CSS Sprites解决的不单单是用户端体验的问题,而且会给我们的L4和L7大大地减轻负载,同时也能够给服务器节省大量的请求。

如果将现在页面上的元素进行合并的话,做一个计算,Blog首页平均下载图片元素是25-30多个不等,总共下载数据也就在50K以内,如果能够合并这些图片中的大部分,对网络交换、磁盘IO节省的开销都是相当可观的,特别是小文件服务的服务器磁盘IO开销,N次*4K的磁盘寻址和1次50K的磁盘寻址,舒服不止一点点。



so,关于并发连接和请求数量的讨论可以告一段落了,但还是偶还是有些不赞成大规模使用css sprites的理由,遂回复如下:

原来如此……谢谢老大~
那在没有持续连接的前提下,剩下的问题就是:

1、由于gif和png-8只有256色,设计师在设计图标的时候,允许单个图标的输出出现仿色,但多个图标放在一起,全部共享这256 色,出现偏色是必然的,这样就违背了设计师的初衷,除非让设计师不使用宽色域(限制在256之内),但我觉得设计师不会接受的……【如果可以放弃IE6中的图标透明(需要设计师对IE6单独设计此类图标)则没有此问题】

2、使用css sprites是会丧失css的灵活性的,为了使用它可能会增加标签和样式的数量,必须在项目的开始、结束时安排专人做这件事并统一处理需求变更,但这不适用于紧急项目,在能够冻结项目需求的情况下我们非常渴望这样做;

3、以前出现过这样的情况:由于某些原因,由css sprites构成的一张大图无法正常加载,页面所有图标都显示不了,造成用户投诉,这个风险该如何处理呢?


讨论仍未结束,但结果其实已经很明显了:运营、设计师、Builder各有各的考虑,都很有道理,怎么办呢?仍然是那个古老的方式:事物是变化的,我们只能不断寻找其间的平衡,一时的完美是一种追求也是一种自我实现。

标签:

收藏到网摘:新浪VIVI  365Key  POCO网摘  和讯网摘  我摘

5 条评论:

发表评论

订阅 博文评论 [Atom]

<< 主页