iJohn.org | 有理义以养其心,则虽老而神明不衰。苟为不然,则昏于豢养,败于戕贼,未老而志衰矣。励志之士,可不戒诸。 - Part 3
9th
八月 2011

Big Data in Real-Time at Twitter
爱因万江斯坦@2011年08月09日 15:27 Post in 系统构架 评论 »

15th
七月 2011

”Twitter搜索现在快3倍啦“
爱因万江斯坦@2011年07月15日 09:49 Post in 系统构架, 性能 评论 »

在2010年春季,为了服务不断增长的流量、提升最终用户的响应时延和服务的可用性、有能力快速开发新的搜索功能,搜索团队开始重写我们的搜索引擎。作为不努力的一部分,我们发布了新的实时搜索引擎,将后端从Mysql迁到了lucene的实时版。上周我们发布新的前端,替换了Ruby on Rails版:我们称之为Blender的Java服务器。我们很高兴地宣布这些改变使我们的搜索时延下降了3倍,同时也使得我们有能力在接下来的几个月里快速迭搜索特性。

性能收益

Twitter搜索是世界上注量最重的搜索引擎之一,每天服务超过10亿的查询。在我们发布Blender的前一周,日本 #tsunami 产生了很大的查询负载,并产生了查询响应时间的峰值。随着Blender的发布,我们的95%时延减少了3倍,从800毫秒到250毫秒,同时前端的CPU负载降低了一半。我们每台机器的容量能服务10倍的请求增长。这也意味着我们能能够用更少的机器支持同样的请求数,从而降低前端服务的成本。

Twitter搜索现在快3倍啦

blender发布前后的95%的查询接口时延对比图

Twitter改进后的搜索架构

为了弄明白这些性能收益,你首先必须明白我们以前的RoR前端是如何地低效。前端运行固定数量的单线程工作进程,每一个做下面的事情:

. 解析请求
. 同步查询索引服务
. 聚合并展现结果

我们很早就知道,同步方式处理请求会低效地使用我们的CPU。经过一段时间,在Ruby的代码层累积欠了重大的技术债,这样很难增加新特性和改进我们搜索系统的可靠性。

Blender通过下面的方式解决了这些问题:

 创建了一个完全异步的聚合服务。没有线程会去等待网络IO完成
. 从后端服务中聚合结果,例如,实时的,最流行的微推和地理分片
. 优雅的服务之间的依赖关系处理,工作流自动处理后端服务之间的传递性依赖

下图显示了Twitter的搜索引擎架构。从网站、接口或内部客户过来的查询请求通过硬件负载均衡设备转发到Blender上。Blender解析请求,然页转发给后端服务,使用工作流来处理服务之间的依赖。最后,将后端服务返回的结果进行合并,以合适的语言呈现给客户。

Twitter搜索现在快3倍啦
Twitter跟Blender有关的搜索架构图

Blender简介

Blender基于Netty http://www.jboss.org/netty打造的Thrift和HTTP服务,Netty是用Java写的高扩展的客户和服务器库,基于它能快速地开发各种协议的客户和服务器端程序。我们没有用其它产品,如Mina和Jetty,主要是因为在其它项目中已经用过它,当然它的接口更简洁、文档也写得不错,这也是我们用它的原因之一。为了让Netty跟Trift一起工作,我们写了解析Thift的代码,专门解析从Netty的channel缓存中的过来的Thift请求,当它从socket读请求或需要封装Thrift响应时,都会调用它些代码。

Netty定义名叫通道的抽象功能,用来封装到网络套接字的连接,提供读、写和连接等IO请求的接口。所有通道的IO请求天然都是异步的。这意味着任何IO调用立即返回一个通道实例对象,以通知请求是否完成、失败或被取消。

当Netty服务器收到一个新的连接,它会创建一个通道流水线来处理这个连接。一个通道流水线不是别的,其实就是通道处理程序的序列,通过它实现处理连接的业务逻辑。在随后的一个小节里,我们会说一下Blender是如何将这些通道流水线映射到查询的工作流处理上的。

工作流框架

对于Blender来说,一个工作流就是一组后端服务,服务之间有依赖关系,每个后端服务都需要处理才能处理收到的查询请求。Blender自动解决后端服务之间的依赖,例如,如果服务A依赖于服务B,首先会请求A,把它返回的结果返回给B。工作流可以很方便地用有向无环图来表示(见下图)

Twitter搜索现在快3倍啦
6个后端服务的Blender工作流示例图

在上面的示例图中,我们有6个服务{s1,s2,s3,s4,s5,s6},之间有依赖。从S3到S1的边意味着先要访问S3,之后才是S1,因为访问S1时需要访问S3后的结果。对于这样的一个工作流,Blender框架先会进行拓扑排序以确实所有服务的顺序,它们也必須以这样的顺序依次调用。上图的服务执行顺序将是{(s3,s4),(s1,s5,s6),(s2)}。这也表明s3和s3可以在第一轮里并发调用,一旦它们返回结果,S1、S5和S6可以在第二轮里并发调用,最后才调用S2。

一旦Blender确定了工作流的执行顺序,工作流将会映射成Netty的流水线。流水线是一个处理程序序列,请求依次会通过这些处理程序。

复用进来的请求

因为工作流映射成了Netty的管道,我们需要将进来的客户端请求转发给合适的流水线。因为这个原因,我们设置了一个代理层,它负现复用并转发客户端请求到流水线上:

. 当一个远程Thrift客户端跟Blender建立一个长连接时,代理层会创建一组本地的客户,跟每个本地的工作流服务对应。注意当Blender进程起动时,会在同一个java虚拟机里起动所有的本地工作流服务
. 当从套接字上收到一个请求时,代理层读取这个请求,计算出需要请求那个工作流服务,然后转发给对应的工作流服务
. 类似地,当收到本地的工作流服务的响应时,代理层读取结果,并把结果转发给远程的客户

我们利用Netty的事件驱动模型来异步完成上面的所有任务,这样也没有任何线程需要等待IO。

分配后端请求

一旦请求转到了工作流流水线,将依次由工作流定义好的服务处理程序处理。每个服务处理程序创建一个合适的后端请求,转发给远程的服务器。例如,实时处理程序会创建一个实时搜索请求并异步地将它发给一个或多个实时索引服务器。我们使用twitter commons库https://github.com/twitter/commons(最近开源了!)来提供连接池管理、负载均衡和死主机检测。

当请求分配给所有后端之后,请求对应的IO线程就将被释放。一个定时线程每隔几毫秒就检查有没有后端的请求返回,并设置对应的标记,表明请求成功、超时或者失败了。在一个查询请求的存在周期内我们为它维持一个对象,用来记录上面这些状态信息。

成功的响应会聚合在一起,再发给工作流中的下一批处理程序。当第一批所有请求的响应的返回之后,将异步地发出第二批请求。这个过程会一直重复直到我们完成工作流或者超出工作流设置的超时时间。

你能够看出,在工作流执行期间内,没有任何线程会去等待IO。这让我们有效地利用Blender机器的CPU,并且处理大量的并发请求。我们能将大量请求并发发给后端去执行,从而也能减少请求的时延。

Blender部署及以后的工作

为了在我们的系统中增加Blender的时候,能确保提供高质量的服务。我们用老的RoR前端作为代理,转发请求给Blender集群。这样使得我们在对后边的技术进行大的调整时,给用户一个一致服务体验。我们下一阶段部署时,会从搜索的服务栈中完全去掉RoR,让用户直接去连接Blender,从而进一步降低访问时延。

原文链接:
Twitter Search is Now 3x Faster

7th
七月 2011

技术型领导
爱因万江斯坦@2011年07月07日 11:38 Post in 互联网产品 评论 »

Facebook前工程总监黄易山撰写了一系列文章,很好地总结了Facebook卓越研发文化中的宝贵经验。本文是这一系列文章的第五篇,也是最后一篇。

何谓技术型领导

所有从外部聘用的管理人员包括技术部门负责人,都必须能够编写代码,并且要达到炉火纯青的地步。如果是一家技术公司,CEO也应如此。

现在有个误区就是认为编程不是高管或者经理的必备能力,仿佛只是一种花哨的打字形式。但其他专业化行业都不这样认为:银行业高管必须能够阅读资产负债表;汽车业高管则需要了解催化转换器等。

有人可能会说,技术的精通程度无法检验,因为一个杰出的管理候选人最近几年可能只关注于管理,与技术已无直接的接触。而且,一个杰出的经理可以管理一切事情。显然,这是不真实的。

当然,并不是希望候选人能用当前有限的扩展性技术创建一个大规模系统,或者在芯片集这种底层进行优化,或者能记住特定语言或框架的详细语法。但检验一个经理候选人是否具有较强的个人技术背景是合理并且可取的。当然我指的是基本技能测试,如果候选人曾经是一个称职的技术人员,他肯定能通过编程测试,包含某些简单迭代或递归算法,以及计算机基础学科中指针、散列和操作系统原理等概念题。

即使是一些门槛很低、许多人可能认为任何一个程序员都会的问题,还是有很多程序员搞不定(我并不是说能够做到这一点就意味着是一个优秀的程序员,但做不到这一点则意味着你肯定不是一个优秀的程序员)。在其职业生涯早期,他们发现自己不是优秀的程序员,但又恰好处在一个技术要求没那么严谨的组织中,因此他们能够被提拔,完全是因为他们碰巧很擅长与人打交道(或善于用人)。现在,他们中的许多人已经进入了技术管理和高管候选人的行列。此外,他们通常非常善于谈论一场精彩的比赛,听起来就像他们知道自己在做什么(否则他们也不会到那个位置)。

检验一个候选人是否具备技术实力的唯一方法是:给他们出一些简单的代码题目进行测试或者找一些他们写过的开源代码直接评估检验。不能通过测试或者没有可供验证的公开技术记录的候选人将不会被雇用。

原因是显而易见的——那就是管理者需要纵观大势,以便作出明智的决定。一个有经验但无技术背景的经理可能会有好想法,但在同等情况下,一个有类似技术背景的经理则可能有更突出的表现。换句话说,前者肯定提供不了技术领导力,如果希望你的公司成为行业的技术领导者,你的领导者首先需要具备技术。

为什么需要技术型领导?

一个没有技术型领导的“技术”公司往往会失败,原因可以归咎于以下两者或者其中之一。

领导无法分辨技术人员执行的工作是否符合标准,因为在面临技术挑战时他们无法区分是技术人员执行力太差还是确实遇到了技术瓶颈。进而,也就无法实行绩效管理,这会导致业绩平庸,并将最终导致彻底甚至反复的失败。

业务需求导致领导不顾技术人员的建议或者想法。当今严酷的商业环境要求企业领导推进企业不停地超越旧边界,这意味着领导不仅要告诉他的员工警惕“该死的鱼雷”,还要能够深化拓展,不能仅求安逸。不幸的是,非技术型领导人没有个人能力来衡量首要技术问题的实际风险状况(例如:某些特殊情况下已经非常过时的限制),并往往会推翻那些不应该被推翻的建议。

在Facebook之外,我见证了不止一个由于管理层缺乏核心技术力而导致的大型公司的失败。而在Facebook,个人技术能力恰巧是所有工程管理人员所必需的,甚至包括部门领导及CEO(是的,Mark Zuckerberg还在继续参与Hackathon编程活动)。这使得该公司敢于多次进行技术冒险,以达到更大的产品创新目标并实现一贯快速的前进步伐,正所谓越了解游戏规则,玩得就好。

作者介绍:黄易山,1997年毕业于卡内基-梅隆大学。2001年加入PayPal,曾任高级工程总监。2005-2010年在Facebook领导研发,在公司研发环境的建设上发挥了重要作用。

9th
六月 2011

Optimizing MongoDB: Lessons Learned at Localytics
爱因万江斯坦@2011年06月09日 21:38 Post in 性能 评论 »

29th
五月 2011

马化腾是个好产品经理
爱因万江斯坦@2011年05月29日 23:40 Post in 互联网产品 评论 »

24th
五月 2011

美国记者镜头下的中国市井角落(一)
爱因万江斯坦@2011年05月24日 00:19 Post in 一千零一夜 评论 »

希望有一天也能带个相机出去扫荡

21st
四月 2011

天涯社区的进化经验(二)产品篇
爱因万江斯坦@2011年04月21日 13:16 Post in 互联网产品 评论 »

产品与技术
• 拙劣的产品设计,会对技术设计造成很大的麻烦
– 产品设计要平衡技术特点,技术设计要为产品提供思路
– 尽可能去理解业务及其目标,才有可能设计出最恰当的技术方案
• 和产品人员共同决策
• 不要增加太多新功能,创建容易维护难,会分散不多的产品及技术资源,更重要的是分散了用户关注。
• 创新不是发散的,要基于核心功能创新
• 支持产品快速优化,前端代码要易维
• 追求完美的设计只是美好的愿望, 做实用主义者。
• 优先解决让用户最恼火的问题。
• 综合考虑时间成本、服务器成本、技术风险、现有人员能力。
• 维护轻重缓急任务清单,优先做重要的事情,当前重要的事情不要超过三个。

保持技术朴素
• 尽量保持简单、低成本,易维护性、可扩展性,不一味追求新技术,适合的才是最好的,让技术保持朴素。
• 通过简单、常见的技术来组合出灵活的系统。
• 试图了解和利用现有技术,保持技术的连贯性。
• 不要为将来做太多技术准备,很多事情可以放在以后做,把握做事的最佳时间点。

21st
四月 2011

天涯社区的进化经验(一)技术篇
爱因万江斯坦@2011年04月21日 13:05 Post in 系统构架, 性能 评论 »

设备投入
– 1999 1台服务器
• 2000年,在线用户300
• 2002年,在线用户1000
• 2003年,在线用户8000
WEB+DB共用在一台服务器上
– 2004 4台WEB 2台DB
• 2004年,在线用户2万
WEB及DB剥离。同时WEB不断增加,DB进行分库(4台WEB,2台DB)
– 2005 7台WEB 4台DB
• 2005年,在线用户14万
– 2006 11台WEB 4台squid(页面缓存) 6台DB
• 2006年,在线用户20万
– 2007 +双线接入 F5设备
实现双线双IP,购置F5实现本地及全局负载均衡,haproxy部署,动静剥离
– 现在 136台应用 38台DB
2008年,数据库双机(事务复制),IBM架构咨询。
• 2009年,在线用户40万
Memcache,数据访问层,服务器虚拟化。
• 2010年,在线用户54万

大多数网站发展初期遇到的技术问题,不是没有采用多层架构、没有使用内存缓存、没有购买好的服务器,而是数据结构及检索设计出了问题。
数据库调优是一个长期的过程,建立模拟环境,来跟踪每条请求的反应时间。

数据库设计注意事项
• 在对产品及业务深度了解的前提下进行数据库设计
• 表记录规模的增加对查询不要有性能问题
• 合理的索引(不要犯常识性错误)
• 慎用联合查询(几乎不用),通过一定的数据冗余来回避联合查询
• 必要时通过合并数据,减少结果集大小
• 尽量通过WHERE来定位分页数据
• 在设计时尽量考虑数据规模增长后的拆分问题

WEB服务扩展
• 无状态服务
– 不要用session保留用户数据,Cookie(或会话Cookie)保留用户标示,用户数据统一保留在数据库,或内存中)
• 应用拆分
– 按不同业务拆分,按流量拆分
• DNS轮询、或通过应用控制轮询

构架完善:
双链路接入双IP
– 使用了2台F5-GTM-1500做链路判断。
• 负载均衡
– 使用了2台F5-LTM-6400实现负载均衡
– LVS(IP层负载均衡)
– 反向代理(haproxy 7层负载均衡
• 动静分离
– 使用lighttpd来提供静态资源服务。
• 代理服务
– 使用haproxy提供七层负载均衡,通过ACL拆分应用。
• 页面缓存
– 2005年,使用squid-2.6在前端实现页面级缓存。
– 已经替换成varnish,增加压缩模块。
• 内存缓存
– Memcache

建立服务可用性监控
• 要预警及报警机制和故障点快速定位
– 应用运行中的错误监测
– 应用可用性监测
– 服务器及网络设备健康监控
– 网络流量监控
– 全国访问质量监测

29th
十二月 2010

三类程序员:人族、虫族和神族
爱因万江斯坦@2010年12月29日 16:20 Post in 一千零一夜 评论 »

世界上有三类程序员,人族、虫族和神族。 人族程序员的代码既不性感也不优雅,但他们能利用任何可负担的工具,让工作顺利完成,他们比较适合创业公司,或是担任公司的技术领导。一个典型的人族公司是37 signals。虫族程序员顾名思义是做基础工作的,他们需要现成的IDE,他们的一切依赖于主宰女王,绝大多数外包公司都是由虫族程序员组成。神族程序员比较稀少,他们的数学相当强,他们使用的语言是Lisp或ML,Google的PageRank就出自神族程序员之手,他们让Google成为一家神族公司。

27th
十二月 2010

Sun JDK 1.6内存管理 -调优篇
爱因万江斯坦@2010年12月27日 23:23 Post in 性能 评论 »