• Feeds

  • Posts Tagged ‘facebook’


    新兵训练营的故事

    受到《打造Facebook》一书的启发,以及对改善环境的美好期望,春节后几个同事都信誓旦旦的表示要搞一个团队内的新兵训练营,尽管大家的出发点及理解不太一样,但没有影响积极前行的信心。

    最开始是由L同学在前期张罗,L同学的核心办营理念是打造具备综合素质的人才(原话不一定如此),因此需要一个丰富的课程体系,让新人从无到有掌握应有的技术技能。即使有一些具备丰富经验社招的同学不需要部分内容,L同学的观点是这些课程可以根据对象进行裁剪,类似大学的学分制。

    由于一些原因,大旗转移到另一个T同学来主导,T同学更偏精英团队营造,认为在老的群体中有一些不好的做事方式及技术体系,需要从新人开始全部隔绝,“需要一个全新的开始”。T同学也开始小范围的训练营试点。

    这时候出现了一些办学观念的碰撞,比如“是否只考虑校招不含社招”、“是否课程目的主要为传授知识点或经验”、“是否不考虑团队现在的,通过新人创建一个理想的团队”等之类问题。

    L同学在QCon大会上跟新兵训练营可仰望的Harry交流了一些细节,Facebook新兵训练营的做法

    1. 了解公司公共的技术体系(共性的,帮助以后更好的了解兄弟部门业务)
    2. 公司文化及业务介绍
    3. 推荐及撮合部门,介绍新人去合适的业务团队
    上述说明在《打造Facebook》一书中有详细描述。

    经过一段时间的讨论,都已经基本达成共识,认为较为可行的新兵训练营的思路是通过案例讨论的形式,了解并分析目前技术体系现状,鼓励改进及创新的想法,辅助传递核心团队文化。新兵训练营每一堂课程除了新人之外,还有各个领域的核心员工及技术主管,新兵训练营的重要的思路是让新人了解目前体系,融入现有的团队文化。

    新兵训练营倾向于讨论没有标准答案的技术案例,甚至倾向选择有争议性的话题,以便讨论过程中了解争议的前因后果,以便更好的理解各种技术及业务场景。

    最新的新兵训练营由Q同学在主导,第一期新兵训练营,讨论开放平台的技术组成部分、以及搭建中可能遇到的技术问题。

    服务管理框架的尝试

    大型软件系统开发需要模块化,在分布式系统中,模块化通常是将功能分成不同的远程服务(RPC)来实现。比如可以用Java RMI、Web Service、Facebook开源的Thrift等一些技术。同样,在一个大型系统中,服务化之后服务的可维护、可管理、可监控以及高可用、负载均衡等因素同服务本身同样重要。

    服务管理目前并无直接解决方案,Thrift作者Mark Slee提到

    It’s also possible to use Thrift to actually build a services management tool. i.e. have a central Thrift service that can be queried to find out information about which hosts are running which services. We have done this internally, and would share more details or open source it, but it’s a bit too particular to the way our network is set up and how we cache data. The gist of it, though, is that you have a highly available meta-service that you use to configure your actual application server/clients.

    Source: [Thrift] Handling failover and high availability with thriftservices

    如果开发一个自己的服务管理框架,需要具备以下功能

    • 快速失败,这个在本厂意义重大,很多远程服务调用是在关键路径中,它可以容忍失败,但是不能容忍堵塞
    • failover,客户端failover支持,并支持自动失效探测及恢复调用
    • 中心化配置及推送功能,所有client在同一时刻配置的一致性,并且client会跟配置中心保持长连
    • 负载均衡策略:支持round robin,least active, consistent hash,或者基于脚本的动态路由策略。这个都是由配置中心来控制
    • 动态启用及停用服务及节点:可以动态启动及停用服务(热发布),由于有推送功能,相对容易实现
    • 跨语言:支持client能使用常见主流语言来访问
    • 版本管理:同一服务可以有不同的版本并存
    • 访问统计及动态运行参数查看:可以对方法级别进行访问统计及实时观察

    访问策略

    服务框架倾向于直连的方案,即client是直接连接server,而不会增加中间物理上的代理层,服务框架只做中心配置、访问策略、服务发现、配置通知等职责。

    路由的特殊需求

    通常的服务访问,使用上述round robin等3种策略即可,但是在实际工程实践中,我们发现有些不同的需求。比如计数这样的远程服务,读操作可随机访问一台远程节点,但写操作需要访问所有的服务节点才能实现。因此我们需要有广播式的访问需求。由于计数服务对实时性和一致性要求较高,不适合采用异步如Pub/Sub这样方式去实现,因此在client还需要支持同步的广播调用。

    耦合及侵入的矛盾

    在设计服务管理系统之前,我们希望不跟一种具体的技术(如Thrift)绑定,比如client和server服务实现方不需要太多关心底层技术。但是在实际实现过程中碰到不少矛盾。

    IDL侵入

    在使用Thrift之后服务实现很难绕过Thrift IDL,使用方需要自己维护IDL以及Thrift生成的代码,服务框架支持将Thrift服务注册到配置系统中。虽然也可以绕过IDL来实现服务,但是框架相关功能的实现和维护成本比较高。

    RPC框架的侵入

    Thrift Transport可以使用TCP(Socket)或者是HTTP
    这个也是非常好的特性,在某些情况Transport使用HTTP会带来很多便利,使用HTTP虽然有一些额外开销,但是HTTP的周边配套设施的完善足够抵消这种开销。使用TCP很多状态实时监控都需要服务系统从头做起。

    Thrift的Version与服务的version存在一定的重复
    服务牵涉到版本管理,我们希望通过发现服务来管理,但是Thrift本身也有版本的设计。

    这些矛盾的本质就是服务框架需要的一些功能是自己实现还是依赖Thrift来实现,很多Thrift使用方如Twitter rpc-client干脆就直接在Thrift框架基础上增强。

    虽然存在上述一些待解决问题,厂内第一个使用服务框架管理的服务即将上线,很快每天会有数十亿的调用将会在此之上产生,同时也会有新的挑战出现。


    Figure 1: Facebook Service Management Console
    (来源:http://www.slideshare.net/adityaagarwal/qcon Slide 27)

    FarmVille(美版开心农场)谈架构:所有模块都是一个可降级的服务


    在2009年Facebook Developer Garage Shanghai活动上,Five Minutes程延辉 介绍开心农场架构,让大家了解了SNS game的一些挑战和设计模式。

    由于农场游戏风靡全球,最近highscalability.com网站采访了美版开心农场FarmVille的Luke Rajlich,他介绍了FarmVille的部分架构资料(1)。

    所有模块都是一个可降级的服务

    For any web application, high latency kills your app and highly variable latency eventually kills your app.

    由于大型的网络应用需要依赖各种底层及内部服务,但是服务调用的高延迟是各种应用的最大问题,在竞争激烈的SNS app领域更是如此。解决此问题的方法是将所有的模块设计成一种可降级的服务,包括Memcache, Database, REST API等。将所有可能会发生大延迟的服务进行隔离。这可以通过控制调用超时时间来控制,另外还可以通过应用中的一些开关来关闭某些某些功能避免服务降级造成的影响。

    上面这点我也有一些教训,曾碰到过由于依赖的一些模块阻塞造成服务不稳定的现象。

    1. 某Socket Server使用了ThreadPool来处理所有核心业务。
    2. 不少业务需要访问内网的一个远程的User Service(RPC)来获取用户信息。
    3. User Service需要访问数据库。
    4. 数据库有时候会变慢,一些大查询需要10秒以上才能完成。

    结果4造成3很多调用很久才能执行完,3造成2的RPC调用阻塞,2造成1的ThreadPool堵塞,ThreadPool不断有新任务加入,但是老的任务迟迟不能完成。因此对于最终用户的表现是很多请求没有响应。部分用户认为是网络原因会手工重复提交请求,这样会造成状况并进一步恶化。上面的问题根本是没有意识到远程服务可能会超时或失败,把远程服务RPC调用当成一个本地调用来执行。

    解决思路一:RPC增加Timeout
    解决思路二:将RPC改成异步调用。

    另一分布式大牛James Hamilton谈到(2)上面这种做法就是他论文Designing and Deploying Internet-Scale Services中的graceful degradation mode(优雅降级)。

    FarmVille其他数据

    • FarmVille基于LAMP架构,运行在EC2上。
    • 读写比例是3:1。
    • 使用开源工具来做运维监控,如nagios报警,munin监控,puppet配置。另外还开发了很多内部的程序来监控Facebook DB, Memcache等。
    • 到Facebook接口的流量峰值达到3Gb/s,同时内部的cache还承担了1.5Gb/s。
    • 另外可动态调整到Facebook与Cache之间的流量,Facebook接口变慢时,可以利用cache数据直接返回,终极目的是不管发生了那个环节的故障,能够让用户继续游戏。

    小结

    尽管FarmVille公布了上面一些技术资料,凭借上面这些资料无法全部了解FarmVille的架构。但是所有模块都是一个可降级服务的概念值得设计大规模应用的同行参考。

    Resource

    1. How FarmVille Scales to Harvest 75 Million Players a Month
    2. Scaling FarmVille
    12