位运算的一些规则_一些好的规则

位运算的一些规则

进行标准化有何明智?

想象一下与一个非常特别的人的第一次约会。 当您到达自己喜欢的餐厅时,您被笼罩在完美的黑暗中:所有的灯都熄灭了。 奇怪的是,厨房发出的声音表明它照常营业。 您会听到女服务员走来,等待引导您进入未坐好的座位。 您的同伴感到困惑,有些害怕。 您会留下还是会找到更传统的用餐场所?

Web应用程序-就像餐馆一样-取决于它们提供的全部体验。 即使是短暂的中断也会严重损害服务提供商的声誉或底线。 政策和准则在防止代价高昂的停机中起着重要作用。 不幸的是,它们还可能导致非理性的决定,弊大于利。 例如,在公司内部建立了一个“ DevOps团队”,这导致所有操作知识都孤立在一个团队中。 尽管可以将这样的管理指令称为DevOps,但仅此而已。

工程师鄙视不合逻辑的,官僚主义的规则,这些规则阻碍了进步,但似乎每家公司至少都有一些。 很有可能在过去的某个时候颁布了它们。 随着时间的流逝,它们逐渐被弃用,但是原始作者无法(或不敢)撤销它们。 任何出于历史原因而禁止使用STL的C ++代码库,或者坚决拒绝超过该语言的1.4版本的Java项目的人都知道,这些措施可能会适得其反。

我们应该忘记所有规则吗?

面对作为障碍的规则,很想摆脱所有障碍。 不幸的是,“放任自由”公司通常不是很成功。 良好的规则是关于长期策略,过去汲取的宝贵经验以及关于用户需求的发现的一种重要交流方式。 理想情况下,组织随着时间而制定的规则可使个人对自己做出良好决策的能力充满信心。 在实践中会发生这种情况吗?

Netflix成为具有真正有效指导方针的公司的典范。 至少那是人们从阅读他们的博客和他们开源的代码中获得的印象。 例如,即使不与Netflix的任何工作人员交谈,我也可以肯定 构建,运行 是他们如何进行开发与运营的良好总结。 另一个明确的原则是,他们编写代码以构建可靠且可扩展的服务,而不是相反。 他们公开开源了许多自己编写的后端软件,这一事实最能雄辩地证明了这一点。

Netflix已构建了Netflix内部Web服务框架(NIWS),这是一个自定义软件堆栈,用于创建可在云中可靠运行的内部Web服务。 NIWS通常采用传统上不如其他替代技术流行的技术来走少走的路。 背离通常的最佳做法需要极大的信心; 毫无疑问,这可以部分归功于使工程师能够“跳出框框”思考的授权政策。

平衡Netflix的负载

我最喜欢Netflix挑战规范的例子是他们如何在NIWS堆栈中实现负载平衡。 面向客户的流量仍由传统的负载均衡器(标准的Amazon EC2 ELB)处理,但对于Netflix服务器之间的流量,他们选择了完全不同的方法,称为客户端负载均衡。 基本思想很简单:客户端本身维护可用后端节点列表,而不是运行将流量转发到一组后端服务器的专用负载均衡器节点。 客户端发出请求时,它将直接与选定的后端实例联系,从而使负载平衡器不再需要。

Netflix并未发明客户端负载平衡,但它们是最早将整个基础设施押在其上的知名公司之一(公平地说,Twitter和Yahoo也在同一时间尝试了这一概念)。 在多个后端服务器之间平衡请求的标准方法是通过负载均衡器(例如Amazon EC2 ELB)或运行软件(例如HAProxy)的服务器。 对于这样的关键组件,保守一点并致力于许多工程师熟知的技术是很有意义的。 但是,在Netflix出现之前,很少有公司尝试客户端负载均衡的真正原因是他们从未考虑过

从事大型应用程序的软件工程师被他们每天使用的库和组件所包围,就像鱼在水中一样。 经过数年(也许数十年)成功地以一种特殊的方式成功构建系统之后,质疑经过战斗验证的配方或其构建基块似乎是在浪费时间。 在许多公司中,这些决策都被编码为基本不变的策略。 然而,由于采用了客户端负载平衡,Netflix获得了可观的收益。 首先,他们从通信渠道中消除了单点故障(在EC2实例频繁终止而没有事先警告的情况下,这是一个巨大的胜利)。 第二,通过将负载平衡逻辑集成到客户端中,负载平衡策略可以考虑客户端容易获得​​的信息。 例如,考虑以下负载平衡规则:

向客户端的EC2可用区中的任何节点发出请求(如果有)。 如果不存在这样的实例,请在当前区域中找到一个正常运行时间大于一天的实例。

传统的负载平衡器并非旨在执行这种自定义逻辑。 他们通常也不会对客户端了解太多(例如,客户端属于哪个EC2可用区或区域)。 自定义负载平衡逻辑成为应用程序的一部分,以与其余代码库相同的语言编写。 这意味着为传统上被认为是“基础设施”的代码编写单元测试很容易。 因此,不仅可以做出更复杂,更明智的决策,而且可以更有信心地确保它们按预期工作。 NIWS在某种程度上将DevOps提升到了一个新水平:开发人员和运营工程师不仅并肩坐在同一个团队中工作,他们还使用相同的语言并提交相同的存储库。

普雷兹(Prezi)加入俱乐部

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 )
} 

Netflix的工程师可以设计NIWS,而不必太担心挑战技术现状,因为他们的公司规则使他们能够这样做。 即使任何人都可以使用NIWS堆栈,但是只有具有相似心态的公司才能使用它来构建产品。 具体来说,那些期望工程师主要根据技术优势做出决定的公司,以及那些不追求完美主义的公司。

Netflix测试

期望所有工程决策都完全摆脱办公室政治,宠物技术和对变革的恐惧,这是一项艰巨的任务。 然而,将这些声音的影响最小化在确保发展不会被忽视方面还有很长的路要走。 一支不受限制的军队通常会使工程师的设计失去创造力和功能性。 相反,一些好的规则限制了问题空间并弄清了约束条件,从而提高了产品质量。

根据NIWS堆栈的来源,Netflix在决定如何实现组件时通常会考虑两件事:

  1. 组件故障的可能性和后果是什么?
  2. 当建立组件的假设开始改变时,修改组件的行为是否容易?

我把这些问题称为Netflix测试 。 它们密切相关:甚至可以说第一个问题只是第二个问题的专门化。 使它们具有重要意义的是,它们能否很好地反映Netflix提供可靠和可扩展服务的业务目标。 拥有这些目标的其他公司可能会从此测试中受益,但是该测试的真正力量在于缺少的东西。 没有提及任何特定的技术或供应商

完美主义者无需申请

令Netflix代码真正令我惊讶的是,它如何专注于足够好,仅此而已。 别误会,到目前为止,我所看到的代码很容易阅读,并且单元测试的覆盖率很高。 话虽如此,但我并不期望如此关注Netflix的特定用例。 例如,在代码的许多部分中,启动后台线程时没有任何方法可以稍后将其停止。 在您意识到Netflix不升级节点上的软件之前,这似乎是一个大问题。 他们通过启动新的EC2实例集群来部署应用程序的新版本,并在监视证明新版本可以处理负载而没有意外问题时杀死旧集群。 如果采用这些部署工具(它们也是开源的),那么僵尸线程就不是问题。 但是,如果尝试从Glassfish之类的应用程序服务器使用netflix库,则每次重新部署该应用程序都会触发内存泄漏。

慷慨地散布在整个代码库中的大量单例类也是意外的。 当我们尝试以Netflix无法预见的方式重用其中一个NIWS库中的代码时,我们很快发现自己陷入了涉及多个类加载器的混乱黑客的困境,以解决这些问题。

最终,虽然记录netflix代码的Wiki页面非常有用,但数量很少,还没有发现很多东西。 文档经常是源代码。 我已经在github问题跟踪器中多次找到解决与NIWS相关的特定问题的最佳建议。

我的许多第一次遇到Netflix生态系统的同事都有些不知所措。 他们的第一React是谴责编写代码的工程师过于随意或懒惰。 我听到他们说:“ 应该有关闭不需要的线程的规则 ”。 但是对于Netflix而言,NIWS列出的所有缺点都不是真正的问题。 在关闭线程上花费的工程时间已在其他地方得到更好的利用。 如果人们尝试以不受支持的方式重用代码,则单例类仅是一个问题。 最后,虽然文档通常是一件好事,但可读的代码和大量的内部专业知识使其成为可选项。 通过制定有关线程管理,皱着眉头的设计模式或最少文档的规则,Netflix可能会从其工程师面临的主要问题上夺走焦点。

实际上,我已经意识到Netflix堆栈之所以成功是因为它的报废性。 Netflix“偷工减料”不仅可以接受,而且实际上可以带来更好的产品。 编写大量描述代码的文本,这些代码在不断发展,只是保证文档不会过时。 编写人员不使用的功能会给开发人员带来动力,难以为他们的团队辩解,并且对社区不利,因为该代码不会在生产中进行测试。 在Prezi,我们有数十个项目一直希望开源数月至数年,但由于缺乏时间来添加所需的抛光剂,到目前为止,我们一直无法打开它们。 Netflix成功地将如此大量的代码开源了,而且没有间断,因为它们的目标是可读性和单元测试,而不是过度修饰和面向未来。 Netflix强制执行的一些良好规则使工程技术能够跟上其快速增长的用户群,甚至开源他们在一边写的内容。

那么所有特定的规则是否有害?

如果将Netflix测试重新制定为一套准则,那么结果将是非常普通的。 诸如“ 至少花费10%的时间用于减少技术债务 ”之类的来之不易的智慧的具体块,或诸如“ NodeJS版本0.6.1导致我们的Web应用不稳定,请不要使用它”之类的技术信息呢? 忘记断电后我们从验尸中学到的教训,这会浪费很多吗?

这些建议以及最佳实践和众所周知的组件通常是有价值的盟友。 多年来,他们通过证明自己在加速开发和促进系统操作方面的优点而赢得了工程师的信任。 例如,在Prezi,我们的大多数后端系统都是用Python编写的,并使用gunicorn Web服务器,Django Web框架和MySQL数据库。 在公司初期,此堆栈使开发人员可以稳定地专注于新产品功能。 多年以来,“ 使用Django和MySQL编写您的服务”在我们看来就像“ 在周五的下午3点之后不部署 ”一样明显。 这些都不是Prezi的书面规则,但两者都可以。

随着注册用户的数量从0增加到超过4000万,导致采用该平台的许多事实不再成立。 例如,当所有网站流量都由单个应用程序提供服务时,将所有用户数据存储在单个MySQL数据库中是有意义的。 如今,Prezi由数十种独立服务组成,它们在延迟,可靠性和一致性方面的要求千差万别。 这些服务中的许多服务都在EC2中运行,并且使用数据库作为键值存储通过单个主键访问数据。 在Prezi成立的第一年,没有任何技术准则能够制定出当前的工程挑战(尽管当时有用)。

只要没有达到到期日期,标准技术和特定规则就可以提高工程师的产量。 特定规则的问题在不再适用时开始出现,但仍然可以执行。

固定在石头上的接口

已失效的一种特别糟糕(且也很常见)的细节形式已弃用的软件接口。 我最喜欢的示例是Java Servlet API。 即使它并不是真的不推荐使用! 实际上,这是一个很好的界面:直观,稳定,文档完善并由许多不同的应用程序服务器实现。

当Prezi决定探索JVM作为我们受信任的Django堆栈的替代平台时,我们选择了一个轻量级的代理应用程序作为我们的试验项目。 我为使用Jetty和Servlet API而不是无名的Scala网络服务器(这是团队考虑的另一种选择)进行了激烈的争论。 六个月后,我们取消了原始代理,并使用Spray (我投票反对的技术)编写了一个新代理,部分原因是它对于我们的用例效率更高,因为用例的响应时间主要是传出HTTP请求的往返时间。 我在代码级别上进行思考:我们要使用哪些对象和接口,如何编写单元测试以及开发人员社区的规模。 这是Servlet API解决的抽象级别。 我应该一直在思考(并谈论)它将如何利用底层硬件。 具体来说,瓶颈在哪里:处理传入请求是否需要大量的CPU或IO资源? 在我们的情况下,否,因为大部分时间将花费在等待传出HTTP请求的响应上; 这就是代理的性质。 鉴于此,为每个传入请求分配专用的硬件线程(这就是servlet的工作方式)不必要地限制了可以并行处理的请求数量,从而导致内存使用效率低下。

Servlet API不能很好地解决此问题这一事实并不有助于抹杀古老的接口或Java编程语言。 成千上万的公司使用Servlet API来构建出色的产品,其他编程语言具有具有类似语义的Web服务器接口。 这个故事的士气是我根据上下文应用了特定的准则。 接口解决特定问题。 当该问题不再是您要解决的问题时,给定的接口就不是一个很好的选择(不管它有多广泛或新颖)。

DevOps中的规则

DevOps的力量来自于技能差异很大的人们的协作。 一个团队的成员随机分布在全胡子的sysadmin类型和功能性编程的狂热分子范围内,比同质的团队更有可能构建可靠和可扩展的服务。

这种背景差异加剧了团队制定明确规则的需求。 开发人员不一定需要了解为什么他们使用的定制Linux内核具有特定的编译时选项集合的全部原因。 同样,并非每个人都需要担心代码中存在多少个单例对象。 诸如“ 没有shebang行就不要编写shell脚本 ”或“具有对用户数据进行分析的类的单元测试”之类的标准适用于团队中的每个人,并且可以帮助那些在给定领域没有足够经验的人根据习惯做正确的事。 只要仅在适用时才使用特定规则,它们就可以创造奇迹。

更通用的规则(例如Netflix测试的规则)仅适用于更高级别的决策,而适用时间更长。 经营团队有两种,诀窍是要注意何时我们逐渐依赖的规则不再达到其目的。

如果我们回到本文开头的隐喻餐厅,然后打开冰箱门,那么各种包装盒上的失效日期范围可能是从几个月以后的任何一天(例如番茄酱)到生鱼的几个小时。 膳食由各种成分组成,每种成分都有自己的有效期。 确保所有厨师都新鲜到足以使最终产品味道鲜美是厨师的工作。 本着同样的精神,真正的智慧不仅需要决定什么 ,我们规范,还能最大限度地减少需要多长时间我们通知,当我们的标准不再有意义。

翻译自: https://www.infoq.com/articles/wise-standardize/?topicPageSponsorship=c1246725-b0a7-43a6-9ef9-68102c8d48e1

位运算的一些规则

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值