Codenvy架构:第二部分

本文的第一部分中,我们不仅讨论了Codenvy平台和其基础架构,还讨论了云IDE与桌面IDE之间的差别、IDE工作区管理、SDK、插件架构和生命周期、Codenvy.com架构--用户管理和身份认证、公开vs私有项目、IDE协作、多租户等等。

\

4.9虚拟文件系统

\

在Codenvy平台上,一个开发者的工作空间是由多种物理资源虚拟而成的,这些资源用来完成不同的IDE功能。

\

依赖性管理、构建器、运行器和代码助手能在不同集群的物理节点上运行。为了适当地虚拟化对这些资源的访问,我们需要实现一个VFS,它不仅能支撑各种服务和物理资源,而且还本地了解IDE的行为。

\

一个云IDE需要一个来保存用户项目的存储系统。Codenvy使用的VFS需要拥有以下特性:

\

4.9.1要求特性

\
  1. 它应是C/S架构,客户端主要以Ajax请求方式通过HTTP(REST API)来访问其服务器端。不同的IDE浏览器客户端都可以通过这种方式访问项目资源。\
  2. 它的API不应绑定到任何一个文件或内容管理系统。它应是足够灵活的、抽象的,这样才能相对容易地将它们用作一个后端存储库。比如,其API可能已绑定至某个JCR系统或基于POSIX的文件系统。\
  3. 它应是多根的,就是说一旦某个用户进入了一个域或工作区,他们访问自己筛选过的分支。由定义,这就意味着一个单一的VFS能由此拥有着多个视角(每域、每工作区或每用户),而“全局的”VFS则是全体的视图。多根能力为某个视图应用访问控制列表提供了必要的基础,而这对于公开/私有的项目实施来说都是必须的。\
  4. 它应支持文件和文件夹的标准CRUD操作,允许使用路径和UID来相对和绝对寻址。通过使用基于UID寻址的CRUD操作来扩展一个AJAX系统,这样开放了灵活性,允许那些非Codenvy的客户端和浏览器直接与项目空间一起工作。\
  5. 它还应具有其它功能,比如访问权限、搜索(包括全文搜索)、加锁和版本管理。一个具体的VFS实现都应包含有这些能力。\
  6. 它应包含另一个一级的的项目资源类型,它给文件夹增加了特殊的属性和功能。事实上,我们自己的VFS已经扩展成能将不同的文件夹节点分类为不同类型的一级节点,它们随后可以继承特定的行为。该VFS包括了项目、模块和包。完全可想象的是它能扩展成具有诸如源码、库等等其它独特项目特性。\

4.9.2实现

\

由于我们拥有内容管理系统(如eXo、JCR、xCMIS)和REST API(如everREST)实现的经验,决定不采用如WebDAV或CMIS这样基于HTTP的传输方式。因为这些选择过于复杂并有很多冗余数据交换,所以它们不算是一个很理想的解决方案。我们定义了自己的特定于IDE的VFS REST API。

\

我们在开发和改进过程中创建了几种不同的后端实现,这包括:

\
  1. JCR:文件系统作为一个JCR项(节点和属性)保存。其当前用于某个由eXo平台所OEM的Codenvy IDE中。该JCR实现提供了可通过IDE访问的文件的本地版本管理,但同时也可以执行某些git操作,这些操作是文件密集的,非常慢。\
  2. POSIX:这是我们产品当前所采用的实现。POSIX是一个普通的文件系统,工作于一个GlusterFS-分布式文件系统之上。\
  3. 内存驻留(In-Memory):我们为QA单元测试还创建了一个内存驻留的实现。\

4.9.3虚拟文件系统入口点(VFS工厂)

\

登入一个连接到某个工作区的用户帐号后,用户就可以访问工作区相关的VFS视图。在某个浏览器登录后,VFS会为这个浏览器分配一个令牌,浏览器可以将它与VFS API一起使用来访问正确的VFS视图。此浏览器然后就可以直接使用REST来访问VFS了。

\

下面是VFS REST服务一个入口点的URL结构:

\

http(s)://\u0026lt;host\u0026gt;/rest/ide/vfs/v2

\

我们使用JSON响应来表示API所返回的VFS信息,响应中包含有一个唯一的VFS标识符、一个指向根文件夹的指针、支持功能列表、一个URL模板列表,这些URL模板可用作访问某些VFS功能的超链接。

\

可选的功能则依赖于当前的VFS实现,可能包括有控制访问权限的访问控制列表(ACL)、文件版本管理、加锁、查询(搜索)。

\

4.9.4主要资源:项目、文件夹和文件

\

VFS有树状的结构,而项目则位于工作区的顶层。

\

eb5d0ae4ff54bd55b6accb5a0e2ff723.jpg

\

展开树状结构可以看到文件夹、文件,在某些特定的场合还有子文件夹(模块)。我们使用不同的API调用集合来展开树,并且我们区分了项目节点和项目的子结构视觉表现。

\

e36de6f4ac2ee80d3d0ab61d782a46d5.jpg

\

上面有3种不同的资源类型:

\
  1. 文件:可被归为不同的一类,其本身带有有用(可索引的、可搜索的)内容。\
  2. 文件夹:标准的结构单元。\
  3. 项目:一种特殊的文件夹,它拥有一个可帮助识别项目的性质、合适行为和视图等等的属性集。\

这3种资源类型的层次式组织以如下方式管理着VFS的结构:

\

有3个很重要的层次规则管理着VFS的结构:1)只有项目才能是最上层的资源(也就是说它的父节点是工作区的根文件夹);2)项目可以含有文件、文件夹或其它项目(对于多模块的项目而言)子资源;3)文件夹可以含有文件或文件夹子资源。

\

4.9.5 基于JSON的虚拟文件系统

\

所有的文件查找、加载和访问都是通过一个自定义的API。这个API在不同的IDE客户端之间使用JSON来回传递参数。我们来比较下云IDE和桌面IDE的文件访问。在桌面IDE中,应用能本地访问磁盘驱动器,使用着本地命令来操作文件,并依赖于操作系统来为锁定、查找定位和其它形式的访问提供关键的功能。

\

然而在云环境中,位于很多物理节点上的IDE同时在操作。不同的IDE之间使用同样位于分布节点上一套代码助手、构建器、运行器来互相协作。使用不同的IDE、位于不同节点的多个开发者可以同时访问某个工作区。于是一个VFS的角色不仅是提供文件访问,而且还提供分布式、可控制的文件访问。

\

无论客户端是否运行在我们的基础设施之内还是使用一个浏览器直接访问,我们都可以通过结合使用RESTful API和JSON来规范不同类型客户端所使用的技巧。我们需要将与文件操作和访问相关的那些核心系统功能封装成这种格式。

\

4.9.6虚拟文件系统功能

\

Codenvy的虚拟文件系统API为既为步进式资源导航提供了方法,也为直接使用其唯一标识符(UID)或路径来访问特定资源提供了方法。你可以通过根文件夹来访问数据。

\

虚拟文件系统的结构已经允许使用非IDE中的HTML应用来查询、搜索、项目排序。这样开发者就可以创建自己的应用,并和位于VFS上Codenvy工作区直接交互。创建一个使用POST请求参数的查询语句是特定于实现的

\

虚拟文件系统可能也支持很多功能,包括监控、访问控制、文件内容版本管理。每个功能都是特定于实现的。

\

4.10记录、分析和管理控制台

\

我们有着下面的用例,这些用例是关于系统中收集的数据和事件的:

\
  1. 测量用户的获取数、参与度和推广程度,以便改善体验,提高采用程度以及提高客户满意度。\
  2. 洞察用户、雇员、管理员行为以便跟踪管理。\
  3. 导出和生成最终可被产品采纳的见解,能供用户提高生产率。为独特的、企业和ISV客户生成购买合约中所约定的报告和见解。\
  4. 为外部受众的查询、调查和研究使用而开放系统所收集数据。\

d70e76ac78b92865c07101c46918d04e.jpg

\

(点击图像放大)

\

由于需要创建一个在内部工作时也能像在云中一样好的解决方案,所以像loggly这样仅限在公有云上使用的服务就只好放弃。我们需要一个可以被OEM的并可在不同的云环境中工作的系统。

\

我们使用了所有主要的客户端和服务器端事件。它们都是像登入和登出一样的典型事件。但是就如“重构”、“构建”、“调试”、“步进”、“预览”、“导出”一样,这些也是开发者的头等事件。这些事件记录为基于文件形式的消息,它们位于每个物理节点之上。消息存放在可长期保存信息的存储库中,并拥有归档策略,它可以随着消息老化进程而移动消息位置。我们使用pig/hive来编程查询,从而处理消息并从中导出各种度量。消息和度量二者都存放在Hadoop中。因为存在大量的分析、报表、各种管理控制台解决方案---能提供极好地浏览、分析和数据关联体验而且我们可以选择安装的,我们在本解决方案中选择使用Hadoop。

\

现在我们运行着三个提供已分析数据的服务。我们也有一个管理控制台,它是一个可以展示关于用户、采用、参与和推广的分析数据的简易的网站。我们也提供很多CSV、Excel和PDF格式的已生成报告以供管理,这些报告是在可重复或参数化的基础上生成的。最后,你们还可以通过一个RESTful API来查询访问这些数据和度量值。这个API将会最终封装打包并提供给开发者以便他们可以直接使用。

\

4.11托管的API

\

Codenvy中的每个服务器端的服务,比如重构、身份认证、构建、部署等,都是以一个RESTful web service形式构建和提供。可以通过下面的方式访问这些Web Services:

\
  • 内部Shell:预定义的Groovy命令集,使用参数数据来调用Web Services。\
  • 外部程序:其注册了一个id并直接访问Web Services。\

在产品之内已发布了这些Web Services。你可以使用“帮助---REST服务发现”获取关于服务包括传参在内的详细信息。下面是节选自通过URL可访问的函数类型和参数组织部分:

\
\

服务路径

\
\

方法

\
\

消费

\
\

生产

\
\

简介

\
\

角色

\
\

用户服务

\
     
\

/organization/users

\
\

POST

\
\

application/json

\
\

application/json

\
\

创建用户

\
\

cloud/admin

\
\

/organization/users(id)

\
\

GET

\
\

-

\
\

application/json

\
\

通过id查找用户

\
\

cloud/admin,

\

cloud/manager,

\

developer

\
\

/organization/user?alias=alias

\
\

GET

\
\

-

\
\

application/json

\
\

通过别名查找用户

\
\

cloud/admin,

\

cloud/manager,

\

developer

\
\

/organization/users/(id)

\
\

POST

\
\

application/json

\
\

application/json

\
\

更新用户

\
\

cloud/admin,

\

developer

\
\

/organization/users/(id)/remove

\
\

POST

\
\

-

\
\

-

\
\

删除用户

\
\

cloud/admin,

\

developer

\
\

/organization/users/authenticate

\
\

POST

\
\

application/json

\
 \

用户认证

\
\

-

\

4.12 SHELL技术

\

我们当前的shell是一个浏览器层,它可以访问内部的Web Services。我们并没有为用户提供一个直接的bash shell,然而在不久的将来我们会提供一个SSH会话,它可以连接到一个映射到某个私有的构建器/运行器队列的专用虚拟机。这个SSH会话会拥有bash功能。在很多方式上,集成于IDE的非SSH的shell是一个虚拟的shell,它是对我们Web Services的顶层抽象。我们使用开源的EverREST项目简化这些调用,该项目是一个JAX-RS实现。这儿可以了解EverREST更多信息。

\

4.13 IDE、构建器、运行器集群管理

\

IDE和构建器/运行器之间通过Web Sockets连接。在我们的服务器端基础设施中运行着BuilderManager和RunnerManager服务,它们管理来自不同IDE客户端的请求并将之路由至合适的服务。客户端上下文环境(比如付费和非付费)决定了请求所映射到的队列。不同的队列拥有不同的处理策略,这些策略比如有专用的虚拟机、共享虚拟机、或带有SSH访问的虚拟机等等。

\

用于运营IDE集群、构建器集群、运行器集群的物理节点的数目由HAProxy所决定。我们拥有可配置的准则,该准则可以推断在每个集群中什么时候一个节点应扩张或收缩。对于IDE集群,准则是基于活跃的租户数。如果阀值是300个活跃租户的话,还会有一个预冲击阀值,当达到这个值时,将会创建一个新物理节点。同样的过程也会在活跃租户数下降时发生。在我们需要关闭一个物理节点的场合中,我们不会做任何将租户从某个节点迁移到另外一个节点的工作。当下次该租户连接到服务时,它将会在另外一个当前在线的节点上重新激活,而同时也会恢复其服务状态。对于构建器和运行器来说,所发生的过程是类似的,然而每个系统行为的配置准则都是唯一的。就构建器来说,我们优化了构建器的数目,试图消除任何阻塞行为。对于运行器来说,同样也是如此。

\

4.14云连通性服务

\

对于任何需要连接至如像GitHub、App Engine、或某个持续集成服务器这样的外部云服务的IDE功能,我们一直使用第三方所提供的直接API来访问这些服务。我们使用一个位于自己的云基础设施之内的代理服务器来控制所有的通讯。代理服务器可以同时处理向外和向内的来自所有第三方的API调用,我们还可以利用它们的性能和操作的可配置性。

\

4.15集成

\

从逻辑上看,下面就是系统如何全规模运行的情形---同时运行在多个节点上。

\

433f469f4b9210082934334d47e3b2b4.jpg

\

(点击图像放大)

\
  • 客户端的浏览器加载Codenvy网站,并提出某些基于URL的请求。请求有两种类型:正常的(业务逻辑)和元数据的。\
  • 如果是正常的请求,HAProxy则加载负载平衡器来决定其路由。\
  • 如果是元数据请求,云管理节点则执行像租户创建或删除等这样的特定行为。\
  • 当执行元数据请求时,云管理节点可能会更新HAProxy的配置,指导其在以后应如何处理该租户。\
  • 一个业务请求会路由至某个应用服务器上动态部署的一个IDE。\
  • 当执行元数据请求时,云管理节点使用内部的REST请求来向位于某个应用中的执行IDEs池功能的云代理提出请求。云管理节点也能指示系统添加或移除额外的应用服务器节点,这些节点根据扩展规则使用作IDE、构建器或运行器。\
  • 某些元数据请求(比如身份认证)会调用组织的LDAP服务器中的数据库。这些LDAP服务器含有帐号、组织、工作区、用户信息和配置。\
  • IDE调用组织数据库来访问帐号信息、付费/免费状态、还有游戏化度量值。\
  • IDE调用内部如构建器、运行器和代码助手这样的服务。\
  • IDE使用虚拟文件系统接口访问项目、代码、存储仓库的信息。\
  • 统计数据存储从应用获取日志供将来分析使用。IDE访问保存的统计数据的目的是为用户提供统计信息和关于提高生产率的建议。\
  • 向云管理控制台发出的请求会触发我们分析系统的事件记录,事件记录首先是以文件形式保存于文件系统中,但最终会存入Hadoop。\
  • 你可以使用CLI、编程APIs、GUI客户端来管理云管理节点。\
  • 管理者可以通过一个专用的访问Hadoop和其它分析系统的GUI客户端访问控制台、报告和统计数据。\

5.0 发布模式

\

5.1环境结构

\

我们拥有多种环境,这些环境为来自于我们自己的过程的不同的需求提供服务。这些环境如下:\

 \

目的

\
\

部署地点

\
\

产品(production)

\
\

具有全SLA的、技术支持、内建弹性的产品环境

\
\

AWS

\
\

预发布(pre-production)

\
\

运行着一个带有某些面向产品部署的成品功能/问题的完整的Codenvy环境。这些功能可能是在一组sprint中完成的。该环境是用于:和客户一起验证,创建相应的示例的文档化工作,支持为即将发布的特性所进行的培训,便于营销从新版本中创造有用资源。

\
\

内部数据中心

\
\

测试环境(staging)

\
\

是一个可以被来自某个特定sprint的问题所升级的模拟产品环境。这个环境用作扩展性测试、热修复验收、用于配置至在一个云环境中的第三方服务的连接。

\
\

AWS

\
\

验收(acceptance)

\
\

执行开发团队所完成的特定功能,其等待来自某个产品拥有者的验收。我们运行多达5个的验收环境,它们可以通过我们的持续集成系统自动创建。验收环境是单服务器的,不具弹性。

\
\

内部数中心

\

5.2 SCRUM过程

\

作为一个为开发者创造工具和解决方案的公司,我们花费了大量的时间来就项目管理和客户进行讨论。我们将与客户分享Codenvy的内部过程和技巧置于优先的地位。这有助于我们围绕着最佳实践进行讨论,有助于改进我们的内部过程,并且能更进一步地提高对于开发者所面对的复杂问题的洞察力。

\

在过去的5年中,我们使用Scrum作为推动开发的主过程。Scrum是一种迭代的、增量式的开发方法学(IID),它可以帮助指导和塑造我们的日常工作。它是一种灵活的方法,可以帮助开发者集中精力于开发,同时仍能提供能保证一切都按时运转的纪律性。

\

Scrum为我们提供了推动自己快速产品进化所需要的迭代计划、规范、执行、测试和分发能力。

\

我们的产品经理担当sprint项目主管(PO)。非开发者作为PO,我们这些开发者就可以关注于编程而不是基本的项目管理了。按照这种方式,产品发布过程与产品开发过程保持分离。

\

我们使用带有Greenhopper插件的JIRA作为项目的问题跟踪工具。

\

开发工作是在用时约为2-4周的“Sprint”中进行,以便将每个发布都分解成可管理的分段。在那段时间内,我们集中精力于将最新路线图中的特定特性转化为已测试的代码。

\

Sprint的固定周期是基于工作量和团队目前的工作能力。这些周期可以是灵活的,但是只能在审查和讨论过其如何影响Sprint目标之后才能变更。

\

在一个sprint开始之前,我们的开发团队从每个角度检查PO所提出的特性,并创建详细的概括了正确规范的“sprint摘要”。他们将这些摘要展示给PO,确保每个人都对预期目标达成一致。

\

在Sprint中,我们的开发团队举行每日站立会议。团队成员讨论当前工作的状态、任何发生的问题或障碍。我们的会议是短时间的(~15分钟),所以它们不会占用太多的编程时间,而且它们可以帮助大家都处于同一进度。

\

在Sprint结束时,我们的开发者为PO演示这些特性。在演示过程中,我们的PO查找在“sprint摘要”中所提出的特定特性。这个验收工作发生于我们开发环境中所运行的专门Codenvy实例上,在这个环境中可以允许验证单个问题。

\

一旦所有的事情都得到批准,我们的团队和PO在一个回顾会上分析结果,并提出可能在下一次迭代中能得以改进的区域。在一个sprint完成之后,在这个sprint中所编目的所有的问题都被移动到一个预发布和临时工作台环境中。在那里,市场、支持、以及文档人员能在发布成产品之前完成其它工作。

\

我们从Scrum中获得的制度和自由的结合是集二者之长。Scrum给我们开发者提供了创建高质量解决方案所需的灵活性,同时还不会牺牲最后期限的纪律性。

\

5.3自动化测试

\

我们的系统大约有95%的自动化测试覆盖率。在任何IDE和网站功能测试中都使用了Selenium。我们用JUnit做服务器端测试,同时在基于GWT的插件中测试功能性方法。我们对于那些尚无法自动化的用例做日常手工测试,比如与PaaS提供商的集成,在这里连接速度能改变接收到的结果。我们所有的测试工作是作为我们持续集成过程的一部分自动启动的,并且每天至少运行一次,这是在某次检入之后开始。

\

5.4运维技术

\

如果是部署在某个云环境中,我们使用Amazon和Eucalyptus所制作的镜像来配置和部署。如果是部署在某台pc中,我们则使用自制的RPM包和bash脚本。配置环境进一步通过Puppet orchestration来管理。

\

我们使用了一个很简单的monit、logwatch和cacti实现来监控所有系统的可用性。

\

作者简介

\

520b4e7dedbe5bca1047f3e037b81eda.jpgTyler Jewell是Codenvy的CEO,并且是Toba Capital的投资合伙人---他关注于开发者投资。他是Sauce Labs、WSO2、Exo Platform和Codency委员会成员,同时投资于Cloudant、ZeroTurnaround、InfoQ和AppHarbor。

\\

查看英文原文:Codenvy’s Architecture, Part 2

\

感谢杨赛对本文的审校。

\

给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ)或者腾讯微博(@InfoQ)关注我们,并与我们的编辑和其他读者朋友交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值