有损服务-不完美主义者的胜利
前言:这是我最近在公司内部分享的一篇文章,大家反响比较强烈,所以也分享到博客里来。
一转眼,来公司已经三年多了。
这三年里,所属部门在变,地理位置在变,技术也日新月异,但是有很多设计原则却是一直不曾改变的,而这次就是我用自身的实践来谈谈我对其中的一个的理解---有损服务。
记得当年qwang用一个很形象的比喻来解释有损(原话记不太清楚了):
比如一个人在沙漠里迷失了寻找水源,那么在他还能走的时候,就尽量走;实在走不动了,用爬的;最后爬也爬不了了,起码要保证自己活着。
所以我们从这个比喻中起码可以获得如下几个信息:
接下来就从自己印象比较深刻的有损服务项目讲起吧。
一、空间应用列表有损服务优化
想当年,苍井空还是处女,玛利亚还姓圣母。好吧,扯远了,想当年第一款国民级应用《QQ农场》横空出世,其空前的火爆导致空间个人中心应用列表的农场图标变得如此重要。
然而由于各种网络等各种原因,这个列表的展现总是会有一定的失败率,而且只要稍微失败就会招来大批用户的投诉。
我们分析一下这个模块的功能:
于是优化开始了……
Step1. 应用信息本地cache
由于应用列表第一个要获取的就是应用自身的信息(包括URL,名称等),而这部分数据本身又是较为固定的,所以就直接cache在了webserver本地。一旦当网络拉取应用信息失败时,就会使用本地的存储。
这样做了之后,其实严格来说体验上并没有任何损失,但这才是第一步。
Step2. 忽略过滤已安装应用列表失败
接着我们发现过滤已安装应用列表接口也存在一定的失败,之前采取了简单而粗暴的方式,一旦报错则直接返回。
然而后来我们考虑到,如果这个时候我们返回一个默认应用列表,同时在这个默认列表中加入那些平台基础应用和火爆应用(农场),是不是体验会更好呢?
再然后我们尝试了,确实证明了这样带来的效果更好。对比一下:一个是想玩农场找不到入口;一个是没装过农场,但是看到了农场的应用图标。高下立分。
这是体验的第一次降级,我们尝到了甜头。
Step3. 前台协助
但是我们很快发现,只有上面的方案是不行的。
所以我们马上联系前台同学优化了两个逻辑:
在这里,我们把有损的设计从后台延伸到了前台,并再次证明好的设计一定是前后台共同实现的~再次感谢当年鼎力相助的晓晓同学~
Step4. 闭环
然而,有损服务毕竟是对体验有影响的,此时如果不对用户做好提示和限制,就会导致用户使用很多功能报错,反而还会增加投诉的数量。
比如用户如果在有损的情况下去编辑应用列表,或者添加应用都会报错,如果没有限制又没有合适的提示,用户很可能会认为自己数据丢失,招来投诉。
所以我们又做了几件事:
OK,到了这里,应用列表的整个有损服务优化就基本告一段落了。虽然后来我们优化了server,提高了成功率,但这里的有损逻辑却被永远的保存了下来,毕竟,什么样的系统能完全没有错误呢?
也正因为有这个项目的铺垫,为我后来做OpenAPI设计时的有损奠定了根基。
二、OpenAPI有损服务优化
OpenAPI是平台与应用之间沟通的桥梁,因此对可用性的要求极高,因此当部分功能出现问题时,保证有损服务,也就是必然的事情。
先来简单看一下OpenAPI的架构图吧(这个之前在QCon已经分享,所以不算泄密~):
当请求进入OpenAPI接口机的时候,接口机会根据参数、URL分别将请求转发到对应的业务CGI,之后再经由接口机返回给调用方。
所以我们再次开始有损优化之旅:
Step1. 业务之间互相屏蔽
从描述可以看出,由于不同业务的CGI都挂载在接口机上,所以一旦某一个业务出现问题时,势必会影响到其他业务。
所以我们对每个业务都分配了单独的L5 ID,当失败量或者超时量太高时,webserver的IP分配就会失败,从而保证业务之间不会受到相互影响。
Step2. CGI运行最长超时设置
刚才提到OpenAPI对性能的要求极高,所以要求CGI都能尽快的返回,否则就会被Step1里面的技术打击到。
但是具体怎么做呢?
我们将有损服务具体化为一个CGI设计原则:
在能容忍的最长时间内,将最重要的事做完
比如下图:
当我们执行到3的时候,发现CGI的运行时间已经太长了(比如超过1秒),那么为了避免其他请求被堵死,我们就直接直接返回给调用方了。
这个时候虽然数据不是完整的(丢了4的数据),但是我们在数据完整和快速响应之间做了一个平衡。
这样就保证了在服务出现问题的时候,大部分的应用还是可以正常使用,只是体验上稍微差一点。
Step3. 智能调整最长超时时间-EMA算法
但是我们很快发现,仅仅做到这里还是不够的,我们刚才提到了能容忍的最长响应时间,但是这个最长响应时间的值怎么指定呢?
如果指定的很长,比如1秒,那么一旦出现问题的时候,相当于每个进程每秒钟只能处理一个请求,根本没有达到我们预期的容灾的效果。
但如果指定的很短,比如20毫秒,那么一旦出现一次偶然的网络波动,即使很快会恢复也会导致我们的OpenAPI大面积失败。
这两种设置方法都不完美,那么还有什么办法呢?
那就是EMA算法,公司之前将预测股票走势的EMA算法引入来预测CGI运行时间的变化,而EMA的一个核心原则就是:
当CGI运行时间越短的时候,给CGI设置的最长超时时间越长;当CGI运行时间越长的时候,给CGI设置的最长超时时间越短。
如下图所示:
可以看出平均响应时间和动态超时时间基本是沿响应时间上限 对称的关系,很直观的描述了这两者之间的关系。
所以到此为止,有损服务才能真正的发挥作用。
建议继续学习:
- WEB系统需要关注的一些点 (阅读:14065)
- 30分钟3300%性能提升――python+memcached网页优化小记 (阅读:12110)
- 基于SSD的数据库性能优化 (阅读:7386)
- jQuery性能优化指南 (阅读:7303)
- 一次简单C程序的性能优化 (阅读:5582)
- mysql sql 百万级数据库优化方案 (阅读:5034)
- 一次神奇的MySQL优化 (阅读:4870)
- PHP最佳实践 (阅读:4921)
- Linux 64位, MySQL, Swap & Memory 优化 (阅读:4460)
- PHP 性能优化技巧-google (阅读:4388)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:Dante 来源: Vimer
- 标签: 优化 有损服务
- 发布时间:2011-11-23 23:55:44
- [67] Go Reflect 性能
- [67] Oracle MTS模式下 进程地址与会话信
- [67] 如何拿下简短的域名
- [61] IOS安全–浅谈关于IOS加固的几种方法
- [60] 图书馆的世界纪录
- [59] android 开发入门
- [59] 【社会化设计】自我(self)部分――欢迎区
- [56] 视觉调整-设计师 vs. 逻辑
- [49] 给自己的字体课(一)——英文字体基础
- [47] 界面设计速成