放翁(文初)的一亩三分地

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  210 随笔 :: 1 文章 :: 320 评论 :: 0 Trackbacks

       周六,参加完SD大会,Facebook的蒋博士被邀请到杭州的淘宝做一次技术分享。由于没有参加北京的velocity大会,上海的SD大会蒋博士的内容又由于时间问题被压缩的变形,所以周六无论如何都去听一次。原定10点开始的会议,9点50分诺大的淘宝培训室就没有座位了,后续不断地还有同学涌入,当然我看了一下,集团的每个子公司的人都有,各种岗位的人都有,其实今天的优化分享主要还是侧重于前端,而那么多人来听,我觉得和我来的出发点一样:“技术不分领域和语言,设计触类旁通”。
       这里只是记录自己的一些学习理解和体会,其中的思考一些是自己看的清楚的,一些还是比较迷惑的,因为毕竟不是做前端的,欢迎讨论,具体的内容参看PPT:http://velocity.oreilly.com.cn/ppts/ChanghaoJiang.pdf。
       网站的请求其实可以分割为多个步骤:网络传输消耗,服务端业务处理消耗,页面渲染消耗。(如果更细致,其实可以将网络传输消耗细分成DNS解析,连接建立及网络传输消耗)Facebook从局部和整体的角度考虑优化,提出了三个优化方式:Quickling,PageCache,BigPipe。每个优化都有适用的场景,所以每个技术优化点前面我先写一下场景。
       Quickling优化场景:用户页面切换频繁。优化方式:通过ajax方式模拟页面内容切换。优点:降低传统页面切换对于资源载入和卸载在前面提到优化场景的损失,服务端对于可重用的内容不必再做重复渲染。缺点:页面复杂度增加,包括模拟传统页面的前进后退,爬虫对页面的信息获取,缓存资源必须在一定时间内批量释放。
       思考:浏览器载入和卸载页面的消耗究竟在什么地方?编程复杂度的提高(模拟浏览器页面行为)和收益(特定场景,复用性)。因此这点对于网站来说最多也是部分页面的适用或者部分场景的适用,同时带来的维护成本有点高。当前很多场景开始使用Comet的模式(如果用ajax模式,那么就和Quickling一样),通常情况下,Comet用于单个页面的增量数据推送,不存在页面切换的那些复杂模拟问题。

       PageCache优化场景:用户行为在多个热点页面中反复切换。优化方式:基于Quickling的流程,在客户端做数据缓存。优点:热点页面渲染快,服务端压力下降。缺点:数据即时性问题。(当前可以模拟单客户自己的操作行为,保证显示及时性,但是如果服务端状态变更,消息无法通知,页面数据较老)
       思考:其实就是将可以缓存的数据尽量缓存,提高页面渲染速度,过去切割页面用ajax局部渲染,现在整体都用ajax,本来的局部渲染需要通过内部实现,但缓存最大的问题就是状态及时性,对于用户数据显示要求不高的可以用这种方式。(我的淘宝页面不可以用,及时性要求太强,虽然这是热点页面)。总体上来说还是多页面的Comet实现中缓存的一部分。
       延伸:服务端管道化模式中,可以考虑部分管道结果缓存。简单来说原来一个请求一个事务,现在被切割成多个小任务通过事件驱动的方式或者简单的管道串联的方式执行后,可以将某一个环节的中间结果缓存,那么可以提高部分子任务的执行效率,在原来一条道走到黑的情况下做起来很复杂也很难看。

       BigPipe优化场景:整体页面可以被切割(无强依赖),每个切割块之间可以并行被执行。优化方式:页面切割为多个Pagelet,交由Ajax框架调度并行或者串行执行请求(当前主要使用串行化,通过局部增量显示,提升用户体验)。优点:用户体验增强。

      在开放平台服务请求中,我们的Pipe支持演进和BigPipe很类似,如下四图:

     

      常规的web请求,容器负责业务线程的管理,业务请求直接在一个Service方法中完成。

     

      还是常规的Web容器,但是将一个服务处理方法切割成多个Pipe,包含三个部分,准备,执行,释放,传统任务被分割,不同子任务资源生命周期缩短,资源利用率提升,如果采用Lazy解析数据流,则可以更好的提升上行带宽的利用率,另一方面可以缓存部分pipe的中间结果,提升部分pipe的处理性能。

     

       采用支持异步化的容器,将业务线程池和容器线程池分开。容器线程池线程依然可以执行部分管道(消耗较低的管道),返回部分处理结果,业务线程池可以根据业务规则来区分对待不同的服务请求(在线程资源有限情况下优先保证重要服务被执行,Bigpipe也提到对于不同的pagelet的优先权重不同可以先后处理),最后返回剩余全部结果。

 

      

       支持批量API请求和QL服务请求(前者是并行服务组合,后者是串行服务组合),容器执行公用的管道(消耗较低的管道),如果是QL call,则容器线程池顺序执行多个API call,最后返回结果。如果是batch call,则启动多个业务线程工作者,并行执行任务,随机返回部分结果。好处就是减少连接损耗,合并多个请求共同处理的消耗。

       其实很多优化理念看似简单,但是作起来很多细节特别重要,就好比Quickling如何用ajax模拟前进后退历史,cache如何可选择的部分监听数据更新,bigpipe如何对不同客户端请求或者爬虫做支持。当然听完分享更需要注意的是自己的场景如何借鉴。

posted on 2010-12-12 19:43 岑文初 阅读(3433) 评论(4)  编辑  收藏

评论

# re: Facebook优化分享后记 2010-12-12 20:16 爱品者
好文章,忍不住想交流一下:
1浏览器载入和卸载页面的消耗究竟在什么地方?
个人觉得在两个方面一是常规资源(css,javascrpit,图片,css等)重复加载,即使前台缓存浏览器也需要放请求看是是否返回304而浏览器(IE)一个域只能加载两个连接二是javascript重新解析,目前我们也想做这种优化但是这样做会增加开发人员的学习成本,原来一个 form跳转的问题现在恐怕很困难,纠结中
2关于页面缓存问题,我们原来使用googlegear但是由于缓存同步问题让我们浪费了很多实施工作量,除了插件问题重要的就是同步问题,基于时间戳的同步实现,由于本身需要使额外连接查询是否过期,给人感觉减少了优化的优势
3管道这块原来没有学习过,有个问题向楼主请教http是不状态的,服务器是推不回来的(常连接暂时不算)这里的servicework是如何推回来的呢?  回复  更多评论
  

# re: Facebook优化分享后记 2010-12-12 20:47 岑文初
@爱品者
我还是一个前端盲:),你回答的很不错了,第一点再次请求带来的消耗(虽然是304只返回消息头)和一个域下最多2个链接的却是挺大的问题(我记得有些人就压缩合并在一起了),js重新解析我到不知道,是不是如果页面不卸载,指向同一个js的时候也不会再解析一次。
至于缓存我觉得不论前端后端都一样,关键还是更新和读取比例的问题,不合适的话,同步反而成为累赘。
管道这块其实和前面两个没啥关系,只是服务端和客户端都可以用,将一个大事务切割成为多个小任务的时候,串行执行可以减少每个阶段自有资源的生命时常,可以提高复用效率,并行执行可以提高多个大任务执行中对于各个阶段资源消耗的利用率。
你的回复前两点,我提交到我的微薄上去,挺好的  回复  更多评论
  

# re: Facebook优化分享后记 2010-12-12 20:55 爱品者
@岑文初
事务切割如果涉及多个请求的话可能涉及到补偿问题,补偿问题也是一个令人痛疼的问题,不过楼主说的串行(中间结果复用)和并行(多CPU调度)确实是一个好的思路  回复  更多评论
  

# re: Facebook优化分享后记 2010-12-12 21:00 岑文初
@爱品者
hehe,千万不要提补偿,做事情一定要简单粗暴,如果一定说要保证一致性,那么有些必定要一致性的过程就不能拆分,否则搞死自己:)  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: