|
英文原文:A Few Good Rules
什么是明智的标准化?
想象一下第一次和特别的人约会。当你到达最喜欢的餐馆时,所有的灯都熄灭了,你身处黑暗之中。奇怪的是,从厨房传来的声音又表明这里像往常一样正在营业中。你听到一位女服务员走来,等待着引导你到没有灯光照射到的座位上。你的同伴不知所措,并且有一点害怕。你是打算留下,还是找个正常点的地方吃饭?
Web应用就像餐馆一样,人们通过其所提供的体验对其进行评价。即使是短暂的中断也会影响服务提供商的口碑或服务水平。政策和指导方针在防止代价高昂的服务中断中扮演着重要的角色。不幸的是,它们也能导致不理智决策的产生,从而造成更大的损害。比如公司内“DevOps团队”的建立。这将导致所有的运维知识都被隔离在一个单独的团队中。尽管这样一个管理层指令可能预示着DevOps的到来,但它什么都不是。
工程师鄙视无逻辑的、官僚主义的规则。这些规则是前进的障碍物。然而,每家公司至少都会有一些这样的规则。在过去,可能有好的理由在一些问题上制定这样的规则。渐渐地,这些规则过时了。但是,规则制定者不能(或不敢)取消它们。当使用C++代码库时,由于历史原因,被告知不能使用STL;参与的Java项目被坚定地拒绝从1.4迁移到新版本。任何有过这样经历的人都明白有些措施可能会对生产力产生消极的影响。
我们应该忘记这些规则吗?
面对这些像障碍物一样的规则,我们都很想将它们废除。不幸的是,“无为”的公司通常都没有成功地废除它们。好的规则是一种重要的交流形式。这种形式关乎到长期策略、从过去吸取到惨痛教训、以及来自用户需求中的发现。理想情况下,一个组织制定的与时俱进的规则,可以帮助个人增强做出正确决定的信心。在实践中, 这样的情况真的发生过吗?
一家公司是否拥有真正有效的指导方针,NETflix就是一个很好的例子。至少通过阅读他们的博客和开源的代码会给人留下这样的印象。比如,即使没有和NETflix的任何员工聊过,我也能确定,“构建它,运行它”是一个他们如何把开发和运维结合起来的不错的想法。另一个明确的原则是:写代码是为了构建一个可靠的、可扩展的服务,而不是为了其他目的。他们开源了所写的大部分后台软件。这个事实比任何事都更具有说服力。
NETflix已经构建了NETflix内部Web服务框架(NIWS)。这是一个自定义的软件栈,用于创建可靠地运行在云上的内部Web服务。NIWS采用了一些不太流行的技术和不太常用的方法。使用这种与最佳实践背道而驰的方法需要有相当强的自信。毫无疑问,部分可以归因于落实的政策。这些政策让工程师可以不受限制地考虑问题。
NETflix的负载均衡
在NETflix如何挑战常规的例子中,我最喜欢的是他们是如何在NIWS中实现负载均衡的。面向客户的流量仍使用传统的负载均衡处理器(一个标准的Amazon EC2 ELB),但对于NETflix服务器之间的流量,他们选择了一个完全不同的方案,称作客户端负载均衡(client-side loadbalancing)。基本思想很简单:取消专门用于负载均衡的节点。这些节点用于在NETflix服务器间转发流量。客户端本身维持着一张列表,记录了可用的后台节点。当客户端发送请求时,直接与所选的后台实例交互。而这样就没有必要使用专门的负载均衡器。
客户端负载均衡并不是NETflix发明的。但是, 它是有名的公司里第一个在基础架构中完全使用这种技术的(公平地说,同一时期内,Twitter和Yahoo也在做基于相同概念的实验)。在多个后台服务器上做均衡的标准方法是:通过一个负载均衡器,如Amazon EC2 ELB,或者在服务器上运行类似HAProxy的软件。对于这么关键的组件,使用保守的方法和一种大多数工程师都熟悉的技术是很有意义的。但是,几乎没有公司在NETflix之前试验客户端负载均衡的方法。其真正原因是,他们甚至都没有考虑到这种方法。
对于从事大规模应用程序开发的软件工程师,每天都要和各种库和组件打交道。这有点像鱼和水的关系。在能使用一种特定方法成功地构建系统这么多年后(也许几十年) ,对已经经过考验的方法或者系统的构建模块提出疑问,这看起来是在浪费时间。在许多公司里,这些决定已经被写进政策中。这些政策基本上是不可变的。但是,NETflix采用了客户端负载均衡的方法,并因此取得了显著的成功。首先,他们从系统中移除了一个单点故障点(对于频繁地在没有警告下就停止服务的EC2实例,这是一个重大的胜利)。其次,通过将负载均衡的逻辑集成进客户端,负载均衡的策略可以参考客户端提供的信息。比如,考虑以下的负载均衡规则:
向客户端的EC2可访问区域(EC2 Availability Zone)中的可用节点发送请求。如果这样的实例不存在,则在当前区域中找一个运行已超过一天的实例替代。
传统的负载均衡器并没有被设计成用来执行这种自定义逻辑。它们也无法获取太多关于客户端的信息(比如一个客户端所属的EC2可访问区域)。自定义负载均衡逻辑变成了应用的一部分,使用相同的语言编写。这意味着编写代码的单元测试用例变得容易。而在传统上,这被认为是“基础设施的东西”。因此,这不仅让制定更复杂、更智能的决策成为可能;也使得人们对工作能如期完成更有信心。从某方面看,NIWS将DevOps带入了下一个层次:开发人员和运维工程师不仅坐在一起,在同一个团队中工作;而且他们使用相同的开发语言,向相同的代码库提交更新。
Prezi加入客户端负载均衡俱乐部
用一个内部的客户端负载均衡实现替代标准的负载均衡器,这种让NETflix受益的技术只适用于NETflix吗?不一定。在prezi.com,我们对内部流量也采用了这种技术。我们的一些应用服务器运行着若干个服务。当这些服务通信时,我们希望它们优先选择本地的服务实例,而不是向网络中发送请求。然而,如果需要访问的服务没有运行在同一台服务器上,那么就可以访问任何一个该服务的实例。对于Prezi,获得的好处是,尽可能地避免了网络流量、减少了在AWS上的支出和响应时间。目前运行于prezi.com产品上的负载均衡逻辑由以下的这段Scala代码实现:
override def choose(key: Scala.Any): Server = Option(getLoadBalancer).map(lb => lb.getServerList(true).filter{server => server.getHost == config.getHostname && serverIsAvailable(lb, server) }).getOrElse(Seq()) match { case Seq() => super.choose(key) case matchedServers => matchedServers(0)}
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。