Python是Rackspace的核心技术
引言
要成为托管服务行业的领导者,您必须快速灵活。通过使用Python实现我们的企业数据系统,Rackspace可以快速有效地更改其内部系统,以跟上行业和我们自身业务流程的变化。我们通过一个名为“CORE”的中央客户信息系统来实现这一点,该系统用于客户关系管理(CRM)和企业资源规划(ERP)。Python和CORE是Rackspace提供我们的狂热支持(Fanatical Support™)和更快客户服务的关键因素。
背景
Rackspace的中央客户数据库最初是一个简单的ERP系统,用于配置和跟踪托管服务器。它最初规模不大,只是一小部分PHP页面,对于Rackspace最初的几百台服务器客户来说,运行良好。
随着Rackspace的发展,这个小小的PHP系统成为了Rackspace业务的中心。每当出现自动化流程的机会时,它都被整合到这个系统中。
几年后,结果是成千上万个PHP页面和模块的庞大、难以维护的混乱局面,这些页面和模块主要由一个人编写和维护。PHP(当时是版本3)的限制已被推到极致,系统对于一个人来说过于庞大,而且很难引入新人来协助维护。

Rackspace托管服务在最先进的数据中心提供定制服务器 放大
我们第一次尝试更新系统是在PHP版本4发布时。该版本承诺提供更好的面向对象功能,并且是Rackspace投入更多人员到该项目的合适时机。
该系统从头开始彻底重新设计,包括新的数据库模式和应用程序设计策略。此时,我们将项目重新命名为“CORE”,它是“核心对象随处复用”(Core Objects Reused Everywhere)的首字母缩写,以反映CORE的整体设计目标:公司所有系统中的模块化和可重用性。考虑到这个目标,我们的团队开始使用PHP的面向对象功能。
虽然我们能够重新调整应用程序并增加功能,但该项目最终失败,很大程度上是由于在使用PHP提供的对象框架时遇到的问题。
内存泄漏、接口不一致、内部数据模型不一致、随机释放对象、尽管明确使用引用仍有多个对象副本、内部PHP错误以及无法追溯的代码故障几乎使得在PHP中完成任务成为不可能。
即使我们获得了一个相对稳定的代码库,我们也远未达到“核心对象随处复用”的目标,因为我们不得不偏离纯粹的面向对象方法,仅仅是为了规避PHP固有的问题。很明显,PHP不适合我们的大规模、任务关键型项目。必须找到新的解决方案。
Python在CORE中
我们一直认为Python是实现我们企业系统的优秀选择,但最初我们放弃了它,转而继续使用我们已有的(庞大)PHP代码库。当时,我们认为通过引入更结构化的系统设计,PHP可以在CORE中成功使用。
不幸的是,这不足以克服我们在PHP方面遇到的其他问题,因此我们重新评估了我们的情况。Python 2.2的第一个Alpha版本最近发布,我们决定开始使用该版本中的新功能开发新的CORE框架。
内省的强大功能
编写新框架的首要任务之一是构建其数据库接口。
Python的内省模型在Python 2.2发布后得到了显著增强。我们决定使用它来构建一个基于DBI 2.0兼容数据库连接器的通用数据库接口类。在这种方法中,不是手动编写查询或表特定的包装器,而是通过元类将所有数据库查询抽象为一个干净的API。
我们创建这个元类的派生类,为每个表创建一个API。每个表的类都包含一些描述数据库中列的类常量。这样,我们可以在不担心任何特定表的实现细节的情况下,快速简单地向整体API添加新表。
该API还使用元数据自动验证和转换传递给数据库的值。这是通过一个“规范化器”函数完成的,该函数将通过API传递的Python数据类型转换为有效的SQL值。该函数还验证数据库或Python不一定检查的类型和格式,例如电话号码和邮政编码。
对象随处复用
数据库API完成后,我们在其之上创建了第二层类。这个更高层次的API实现了特定应用程序的业务逻辑,例如联系人管理或故障工单处理。它还阻止用户执行与Rackspace业务实践不一致的操作,或分配可能导致数据库中其他类型高级数据损坏的数据。
随着第二层的创建,我们实现了“核心对象随处复用”的最初目标。公司内的程序员开始使用这个API来实现应用程序功能的接口。这与我们的API开发团队几乎没有交互,并且可以在不担心滥用API的情况下完成。
虽然我们主要为核心企业应用CORE设计了API,但它在Rackspace的许多其他系统中得到了重用。例如,一个团队在API之上构建了一个SOAP服务器,以便从他们的PHP应用程序中访问它。其他应用程序直接使用API,看到我们的工作如此轻松地被重用并与其他系统集成,令人非常满意。
将Python与Apache集成
有了API之后,我们开发CORE的下一个任务是找到一个有用的模板模块,将我们的Python代码与运行在Apache网络服务器上的HTML页面集成。
在查看了许多可用的基于Python的模板模块后,我们选择创建自己的简单解析器。我们的方法是将服务器端模板页面转换为Python服务程序,其输出由HTTP服务器发送到用户的浏览器。
虽然这是一个相当简单的练习,但我们确实遇到了一些问题,这些问题源于我们CORE数据库元类的设计。我们发现,在运行时更改类和模块(如元类所做的那样)违反了Python可选的受限执行环境所施加的准则。由于我们认为受限执行是支持持久Web模块的必要组件,因此我们选择使用CGI而不是mod_python或类似的持久解决方案来部署CORE。
由于快速硬件和多台服务器随处可用,并且由于我们的模板解析器预编译并缓存其生成的Python服务程序代码,CGI解决方案足以满足我们的需求。它还允许我们解决诸如数据库连接池和限制Python之外的执行环境等问题。
单元测试
多亏了Python自带的单元测试模块,我们的项目在投入生产时产生的bug比我们使用PHP时想象的要少得多。在使用PHP进行维护时,总会有一个问题,即一个地方的更改是否会破坏应用程序的另一部分。
我们现在在设计API时为每个API编写单元测试。这意味着我们可以通过运行整个API的单元测试来验证一个模块的更改以及它对所有其他模块的影响。
自从引入Python和单元测试以来,我们在已部署应用程序中看到的bug的性质已经发生变化,主要包括用户界面中的问题,例如布局问题或错误的事件处理。
现在,很少有bug来自API本身,即使有,通常也是应用程序部署过程中修订管理不善或DBA协调不力造成的。Python无法解决开发过程中的所有问题,但它确实为我们减少了关键系统缺陷的数量。
文档
文档缺失是我们之前开发工作中的一个主要问题。我们尝试了多种工具和策略来记录我们的PHP工作,但最终这些都失败了。代码变化太快,而且当时可用于PHP的代码级文档工具过于挑剔,不值得投入精力来使文档正确解析。此外,尽管有周密的计划和编码策略,PHP和HTML的混合使得解读和理解代码更加困难。
幸运的是,Python在设计时考虑了文档,为模块、类和方法使用了“文档字符串”。由于文档本身就是语言的一部分,并且pydoc是Python发行版中的标准模块,因此很容易将API文档提取到HTML和其他格式。
随着时间的推移,我们发现Python的语法结构使得代码具有极高的可读性,这本身就有助于文档化和维护代码的整体任务。
结论
Python极大地改进了CORE项目的开发流程,并缩短了开发时间,加快了发布速度,使我们能够跟上Rackspace不断变化的业务流程。
Python使我们能够创建一个复杂而动态的数据模型,它灵活且易于使用,可以抽象数据库操作。有了它,我们实现了“核心对象随处复用”的目标。
Python集成的单元测试和文档工具极大地增强了我们部署和维护更稳定、无错误产品的能力。
最终结果是一个成功的企业应用程序,它对Rackspace托管服务(Rackspace Managed Hosting)在托管行业中兑现其狂热支持(Fanatical Support)、无与伦比的速度(Unmatched Speed)和无限灵活性(Unlimited Flexibility)的承诺至关重要。
关于作者
Nick Borko是内部应用开发总监,也是Rackspace企业数据库应用程序CORE的项目经理。Rackspace托管服务是向中小型企业提供托管服务的领导者。所有客户平台都包括最先进的数据中心、定制服务器、可突发连接、99.999%正常运行时间SLA、专用客户经理、即时紧急响应以及24x7全天候访问实时专家技术人员,以支持所有硬件和核心软件。Rackspace成立于1998年,总部位于德克萨斯州圣安东尼奥,为80多个国家/地区的客户管理服务器。