淘宝网黄小勇:rails3在淘宝测试平台的应用
发表于 2011-11-12 22:23:00

 继在上海成功举办两届Ruby技术交流大会后,第三届Ruby技术大会11月11日在上海光大会展中心国际大酒店盛大开幕。本次大会由CSDN主办,ITeye和Shanghaionrails协办,现场有超过500名来自于全国各地的Ruby技术开发者参会。下午,来自淘宝网的黄小勇带来了以《如何用rails3构建小应用集群——谈rails3在淘宝测试平台的应用》为主题的精彩演讲。

在企业应用中,随着业务的不断复杂,单一应用的技术方案变得臃肿低效、难于维护,即便采用rails3这样的敏捷Web框架也不例外。淘宝的技术架构变迁充分的印证了这一技术趋势。据悉,淘宝网(局部应用)了利用rails3整合了Merb框架,提供railtie/engine机制,使得构建应用集群变得更容易。目前已在淘宝的kelude测试平台进行了尝试,用8个子应用来构建一个测试平台。

在现场演讲中,黄小勇分享了Rails集群配置、实战部署,以及在淘宝网测试平台里的应用,为参会者勾画了一幅淘宝网Rails的应用场景,在面对复杂的业务需求和系统应用时,这些宝贵的实践经验相信能够起到指路明灯的作用。

淘宝网测试平台工程师 黄小勇

以下是演讲文字实录:

    大家下午好,自我介绍一下,我是来自淘宝网测试平台的一位工程师,今天想跟大家分享一下我们在用Rails 3进行测试和大的应用时面临的一些问题以及处理的方法。

    我是2008年加入淘宝网的,之后就一直负责淘宝测试平台的开发,到现在总共有两年的Rails开发经验,不算久,也不算“嫩”。相信大家对淘宝网都比较熟悉,淘宝网是在2003年5月份开始的,其实当时是一个非常简单的网站,就是基于PHP做的一个网站,应用非常单一。再看看现如今的淘宝网,大家会发现它的变化是非常大的,现在已经有250多个应用,有一大堆的快捷键。这个技术变迁的背后推动到底是什么?

    最重要的是我们淘宝网的业务确实是要比以前复杂了很多,业务太复杂了,我们必须把它拆开才能搞定。小时候我们玩的是家长送的玩具,可能小朋友对它会不熟悉,他们就会把这个玩具拆开来。我们做系统也是一样的,当一个系统非常复杂的时候,我们就要弄清楚它的内部模块,这样会帮助我们认识整个系统。另外团队太大了,因为你要做一个非常复杂的系统就要进行人员扩张,由一个人来做的话是非常吃力的,一个人指挥整个大堂的几百号人不太现实,这时为了让整个团队运作起来,我们就会按照业务单元进行拆分,一个业务单元有十号人把它玩得转就OK了。第三个其实就是我们技术层面,这个系统太过庞大,我们把它弄到一起就会发现各种技术,做下来就会发现整个界面都是耦合在一起的,这个时候我们必须把它拆开。

    这是我去年接手的工作,当时我们要做一个测试平台,这里的业务非常多,面对这么一大堆乱七八糟的需求应该怎么办呢?我们现在的做法就是把它拆开,按照我们的业务模块、业务逻辑一个一个地拆开,按照业务的独立性,一块业务构建一块Rails应用。我们会根据业务的独立性一个变八个,最后提炼出八个子系统,每个子系统就是一个Rails应用。

    在诉求设计上,我们为每个用户设计了一个数据库,当然,这个数据库不一定会独立占用一太物理的Server,我们现在就是用一台Server进行存储数据。在数据库设计方面我们是实现独显分离,这非常简单,我们首先是用备份的方式,每个数据库会建一个主库和一个备库,直接从备库中读取就可以了。整个Rails应用基本都是这样的,中间这一部分主要是强调我们是按照应用模块来进行的,底层是储存备份的数据库,再上一层就是提供一个Bridge引擎,让组件之间能够相互沟通。还有就是基于底层构建一系列的Rails应用。对用户来说我们还是会把业务逻辑串联起来,给用户看到的是一个完整的、前端体验一致的系统。

    把Rails应用被拆开之后会面临一些问题,比如前端的公共资源和统一展示,还有就是Rails的环境设置是如何来管理的。我们是通过建立一个Master Server引擎来管理,最主要的就是这些。第一就是我们的静态资源,第二就是我们Rails应用的配置,包括用户认证等等。对于静态网页的管理可以非常简单地实现,我们可以把各个应用的静态文件放在一个公共的专用文件夹里,各个Rails应用都有自己特有的文件,我们可以把它单独放在自己的文件夹里管理。所以最终的文件价格结构看起来就是这样的。大家可以看到这里有一些公共文件,还有各个Rails应用所特有的文件。所有的应用组件都是从这里获取的。这里只需要做一个简单的配置就可以实现刚才的访问,对于Rails来说,我们是可以用Public获取文件,通过这种配置可以访问到其他路径的静态文件。

    下面我们看一下Rails的应用配置,这包括很多种,比如本地市区的Location,你会发现重复配置很麻烦,这样我们可以提取一个公共配置来保存文件,然后在各个应用中加载这个文件就OK了。现在我们可以看到它是从一个Master文件中Config文件,这就是Rails的特有配置,仍然放在Rails的专用配件里。

    接下来是Rails的环境配置,Rails在提高生产力方面确实挺高效的,为我们开发了测试、生产、应用三各环节,但是当你的环节变得比较复杂时,你会发现这三各环节其实并不够用,就我们的团队而言,我们新增了一个Build up Box,还有Online Production,我们需要在Data层面构建起来。这种环境启动的时候就会加载相应数据库的环境配置,通过增加额外的环境,你会发现环境的管理变得非常简单,在本地上就以Developer进入就OK了。这种配置是可以通过Ngex的环境设置来搞定,这可以简化Rails在不同环境应用下的部署。

    额外增加的3种公共环境也是放在专用的功能中去,如果要让Rails访问这些公共环境的话,我们只需要在Rails应用中做一个额外的配置就OK了,这是一个Configration,只要把路径改一下就OK了。

    GM Fire里通常有几十项配置,这种配置也可以提取很多公共的东西出来,对于这种文件我们也可以直接在GM Fire加一些代码,把它直接Load进来。首先把公共的GM Fire文件找到,然后下面用一个Instance,就会把公共的GM Fire文件加入进来。我在网上搜了一下,如果想要同时找到GM Fire文件,可以使用代码,然后直接在公共文件中改就OK了。

    在分成多个应用之后,整个系统的用户认证应该如何进行?其实有两种方式,第一是使用单点登录系统,可能有些同学对此比较陌生,单点登录系统就是这个意思,就是我有一个登录服务器,当用户访问进来的时候我会检查一下用户有没有登录,如果没有登录,我们会把用户登录的请求发到单点登录服务器上去,由服务器对它进行认证,反馈用户的一些登录信息。这样做的好处是所有的应用都不用去管,只需要把登录请求发到单点登录服务器上去就OK了,这是单点登录的好处。另外一种方式就是共享Session,或者用同一套来完成,我们可以非常广泛地使用,把它存在数据库里去,所有的都访问同一个库的同一张表,就可以完成不同登录的问题,现在我们使用的是单点登录的模式,也是在这个应用配置里,我们会向Application Controller提供API,用户在访问的时候就会走到单点登录的步骤中。

    我们还有一些公共的东西,比如我们广泛使用的Healt,用于前端代码页面,在应用之后同样还是需要把它提取出来。这里举一个例子,我们会把各个应用的Route导航链接写下来,然后是整个公共系统级别,比如前端文件的Load,我们会提供这种类似的Help。当用户访问我们测试平台每一个应用的时候,你所看到的导航就是下面的这张图,这是由一个Helt来生成的。其实它并没有什么高新的技术,整个Master就是一个Rails引擎,这是Rails 3.0中的概念,事实上它可以理解为一个GM包,但它可以控制Rails的初始化过程。Master这个引擎在其他应用启动的时候会Manage进来,所以提供的所有功能和API都可以在其他应用里访问得到,这就是一个简单引擎的格式。我们会在Master里创建一个引擎文件,然后进行一些相关配置的代码。然后在其他GM Fire文件中引用进来就OK了。

    接下来如果我们要创建10-30个应用,我们是不是要把刚才讲的所有改动都写一遍?其实不需要,Rails中有一个很好的功能,我们可以通过Rails应用,实际上这个秘密是支持参数的,我们可以指定Rails生成、应用的一个模板,我们在这个模板里把一些要改的东西写进去,你通过这种创建的应用自然就符合我们小集群的规范了。

    在应用创建好之后每个应用都可以按照我们之前所熟悉的方式来开发,接下来有一些问题,就是应用之间有一些数据进行交流。我们的实现方式是通过一个Pridge来实现用户之间访问交互的数据。先看一下应用之间的几种数据交互方式,第一种就是直接通过Ruby的API来读写和修改数据,这是非常直接的。第二种是通过Work Service的方式来交互数据,还有就是通过消除机制和Workbook的方式来订阅,我今天重点讲一下第一种数据交互方式。第一种是通过Ruby API的方式来交互数据,我们需要程序员做一个事情,这个Service需要提供一个Client Leak,通过这种工具来Load数据。其中有3种APL,第一种是数据读和写的APL,第二种是用于生成页面的Help,第三种是加载路由,就是我有一个应用,可能有些UL想暴露给别人提供服务,这个时候我可以把部分路由暴露给他。

    在数据访问层面,我们是通过这两种方式来实现其他应用对我们应用数据的读写分离,我这边会有两个文件夹,一个是Read Only文件夹,在这里我写Model还是正常的方式来写,但是提供的API只是访问数据、读数据的API,另一种就是删除所谓的API。如果要使用API需要调用一个Bridge的API,需要指定我需要访问哪个Rails应用的Model,然后在相关的Leap文件夹中load进来。这是Read Only文件代码,我们会有一个Read Only的Molel,在这个Leak的最下方会设置这个Model到底需要访问哪个数据库。这个Model也可以开放给别人,它的访问数据是TKS Service所能提供的。

    另一方面是路由,大家知道,用户点击页面链接,浏览器发了一个请求过来,这个路由就要根据请求里面的UIL转化为后端的代码调用,这是它的第一个作用,就是解析UIL。第二个作用是生成页面的Link,比如我们系统的右端会有一个用户退出,这其实是一个超链接,所对应的地址是有路由Healt来生成的,同样,我们在做这个子应用集群的时候也会遇到这种情况,就是我在我的应用里可能需要访问到需要提供、需要链接到别的用户里面,这个时候就需要别的应用机制,这个时候我们就需要把对方的路由文件加在进来,对方的路由文件也是比较简单的,就是在应用的Application文件中加几行代码。比如Bridge Remote,加载项目管理的Service路由,这样启动之后就会发现在你的应用里可以直接调用对方应用的路由方法来生成UIL。

    接下来就是我们的Remote Help,就是项目管理应用,我们会提供整个系统全局的导航,我们会把它作为Help公开出来,同样Help的加载也是非常简单的,就是使用我们提供的Remote Help的方法。访问其他的数据有很多种方式,一种是通过Ruby代码在后端完成,这个时候就需要有一些Ruby的客户端工具,通过这个工具我们可以向一个UIL发起请求,得到它的响应。另一种方式是我们可以在前端访问它的数据,最简单的就是我们可以在前端发出一个请求来Load另外一个应用的部分数据,我们可以直接调用Script,把别的数据加载进来。另一种访问对方数据的方法就是可以通过Message用Banner组件来使用,这个组件的原理就是当我的数据有变化的时候会广播一条消息,对应的其他应用会订阅感兴趣的消息,这个消息一旦产生其他应用就会收到对应的消息,然后可以做一些逻辑上的处理,实现系统之间数据的交换。

    下面我讲一下Rails集群的部署,我们现在所使用的部署方式就是用NS Passenger的部署,在部署应用的时候我们会为每个应用的路由设置一个Scope,在处置的时候就知道什么样的UIL应该到什么样的应用中去。我们会把整个系统的RIZ放到服务器上去。在线上我们会使用自己配置的一些环境。

    简单地看一下Scope Route,对于项目管理所有的UIL我们都会包一层,称之为Scope Project,这样写好之后,当我们的用户在页面上点击链接,你的请求就会发到项目管理应用这边来。我们会用一个Location来匹配UIL,发现它有项目管理的时候我们就会把它转移到项目管理应用中去。通过上面的部署,你会发现在后端虽然有应用,但是对于用户来说感觉到的就是在同一个运营下的同一个系统。

    我们在Rails开发的时候还会用到其他常用的公共技术,这里跟大家分享一下,第一个就是Active-support的通知机制,现在大家所看到的这个是同一进程的广播消息,也就是说我在应用A里面有一个Model数据发生了改变,这个时候我发了一条消息,同时我在应用A里还有另外一个Model消息需要处理,我就可以定这个消息,当用户的消息出发就会在Model把事件处理掉。其实如果不用这种方式,Rails还有其他方式,你会发现Model一旦多起来之后这种函数注册就会非常多,可能这个跟你不相关,但是一旦要写在这个Model里面会非常麻烦,遇到这种问题,我建议使用这种方式。

    另外就是后台处理,总会有一些操作比较费时间,这个时候你又不想让用户久等,我们就会有一些用户登录,这个足见用起来是很简单的,可以把用户的请求转换成一个后台登录。还有异常通知的组件,我们在程序上线之后可能会有一些问题,用户一点击就出错了,接下来就是定位问题,如果你有异常通知邮件的话就会非常简单了,一旦出错,这个组件会把对应出错的信息发到你设定的邮件地址中来,你只需要看你的邮件地址就知道线上有没有错误,这可以在很大程度上帮助我们纠正线上问题。

    最后就是需要关心性能了,我们的RZ分析就是非常好的图形,我们有一个Rest Log Online组件,这样可以很容易地定位、分析到一些性能评级。另外如果你要进一步定位,你可以用一个免费版的商业环境,这里左边的每一个一级导航都是我们的一个RZ应用,大家可以看到它的界面风格其实是一样的。整个代码结构大概是这样的,这里会有8个Rails应用的代码,还有一些相关的引擎。我们在做这个系统中使用的软件是基于Ruby 1.1来做的,这个应用的好处就是整个系统就像搭积木一样,你可以快速开发,当你发现这个项目管理不适合你了,你可以重新写,其他的应用不受影响。我们可以让一两个人负责它的开发,整个开发会非常扁平。额外的好处就是人员成长非常快,大家都处于同一个水平线上就非常有利于新人的成长。我相信现在各家公司新进的人应该不少了,淘宝虽然做了七八年,但是你会发现新员工还是在不断进来。面对这种团队,我们就必须给大家提供一个非常好的成长空间。

    拆了之后还有一个好处,就是代码的物理意义就分开了,不会呈现出一些幻象,会以最简单的方式来进行。比如在A model里就不会这样做了,这有助于整个代码的质量控制,然后自然而然就会形成一些公共的应用组件,比如我们这边已经形成了4个GM包。实施Rails有几个前提条件,一个是你的业务真的是挺复杂的,你在开发上还会有一些额外性的工作,虽然不会显著增加。另一个是你的团队真的很大了,如果是两个人一个Rails团队就可以继续做,但是如果是5-10个的话还是拆开的好。还有就是我的团队里要有一个人控制拆分之后的变化,因为拆分之后需要有一些新增的功能,如果这个搞得很烂拆分就失败了。还有就是要有老板的支持,因为这是一个技术性工作,并不一定可以直接看出产出,所以需要有后台支持,当时我们这个项目主管是很支持的,花了两个月的时间把原来的系统拆掉,替换后用上了新的交互设计系统。

相关链接:2011中国Ruby技术大会现场直播

CSDN官方微信
扫描二维码,向CSDN吐槽
微信号:CSDNnews
微博关注
【免责声明:CSDN本栏目发布信息,目的在于传播更多信息,丰富网络文化,稿件仅代表作者个人观点,与CSDN无关。其原创性以及文中陈述文字和文字内容未经本网证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本网不做任何保证或者承诺,请读者仅作参考,并请自行核实相关内容。您若对该稿件有任何怀疑或质疑,请立即与CSDN联系,我们将迅速给您回应并做处理。】