架构君:你和牛人的差距全在本文里。
要成为一名专家级的程序员,你需要精通大量的知识,包括:语言、API、算法、数据结构、系统和工具等等。这些知识的发展日新月异,新的语言和编程环境不停地在涌现,并且似乎这些新东西还很热门,人们都在使用它们。对程序员来说,保持知识不落伍以及对知识做到精通是非常重要的。一个木匠需要知道如何选择合适的锤子和钉子,并要能够把钉子笔直地敲进去。
同时,我发现十几年前的一些观念和策略在当前的很多情形下仍然适用。我们知道底层设备的性能或容量发生了数量级的变化,但是有关系统设计的某些思路一直有效。这些抽象的观念比具体的系统实现更为重要。了解一些常见的思维方式对复杂系统的分析和设计非常有帮助。
谦卑与自负
不仅仅是在编程方面,在像计算机这样一个不断发展的领域里,我们需要在谦卑和自负之间寻找一个平衡点。如果你愿意去学习,总会有学不完的东西,也总有一个人可以帮助你学习。一个人既需要谦卑地承认你所不知道的东西,也要有信心去精通一个新的领域并应用已经掌握的知识。我曾经遇到过这么一个人,他在一个独立的领域工作了很长很长时间之后,“忘记了”如何去学习新的事物。 的学习是撸起袖子亲自去建立一些东西,哪怕它只是一个原型或者小技巧。我认为,一个 的程序员需要对技术有着广泛的了解,同时也要花一些时间去深入研究某些技术,并最终成为专家。当你真正遇到困难的时候,就是你开始深入学习的时候。
端到端的观点
早在年,JrrySaltzr、DavRd和DavClark就在互联网和分布式系统方面做了早期的研究,并写下了他们对端到端观点的经典论述。现在在互联网上有很多关于这方面的内容,但是有很多都是错误的,所以你应该去阅读原始的论文。他们谦虚地认为端到端的观点并不是一个发明。因为从他们的角度来讲,这只是一个普通的工程策略,除了通讯领域之外,还可以应用在很多领域。他们只是把这些观点写了下来并收集了相关的例子。这里有一小段解释:
在实现系统某些功能的时候,只有在掌握了系统性的知识并亲自动手的前提下才可能正确的完成任务。在某些情况下,系统中某些内部组件的部分实现可能是影响性能的重要因素。
这在SRC论文中被称为“观点”,尽管它已经在维基百科和其他一些地方被提升为“法则”。事实上,还是把它看作是一个观点比较好,在论文中提到,对于系统设计师来说,最难的一个问题就是如何在系统组件之间划分职责。这个问题最终会成为一场争论,因为在切分功能的时候需要权衡利弊以及隔离复杂性,并想办法设计一个可以灵活应对不断变化的需求的可靠而又高性能的系统。世上没有简单的规则可供遵循。
互联网上的大部分讨论都集中在通信系统上,但是端到端的观点适用于更广泛的情形。有一个分布式系统的例子,就是“最终一致性”这个观点。最终一致的系统可以通过让系统的各个组件进入临时性的不一致状态来进行优化和简化,因为有端到端的流程可以解决这些不一致。我比较喜欢可横向扩展的订单系统例子(例如亚马逊所用的)。这种订单系统并不要求每个请求都必须通过中央库存控制节点。中央控制点的缺失可能会导致出现两个终端同时出售某本书的 一本的情形,但在任何情况下都需要有某种类型的决策系统,例如,通知客户该书需要延期交货。当然, 的那本书也有可能会在处理订单时被仓库里的铲车碾过而不能出售。一旦你意识到端到端的决策系统是必需的并且在当前系统中已经建立起来,那么可以充分利用这个决策系统,让系统的内部设计得以优化。
系统在对外提供服务以及进行不断性能优化的过程中,会体现出设计的灵活性,而这种灵活性正说明了端到端方法的强大。端到端的方法能促使系统内部运行的灵活性,并促使整个系统更加强大。这说明端到端的方法是“反脆弱”的,并且随着时间的推移,彼此之间互相促进。
端到端的方法提到,在添加系统层次和功能的时候,你应该非常小心,因为这会影响到系统整体性能(或其影响到其他方面,但性能往往是很重要的)。如果你知道当前正在创建的那个层的原始性能,端到端的方法可以帮助你优化这个性能以满足某些特定的需求。如果你破坏了性能,那么即使提供了重要的附加功能,你也可能牺牲了设计的灵活性。
当你有一个足够大而又复杂的系统,并且需要安排整个团队的人员去实现其内部功能的时候,端到端的观点将与组织设计融合在一起。团队在扩展系统功能的时候,通常以牺牲设计灵活性为代价来提供端到端的功能。
在使用端到端方法的时候,可能会遇到的难点之一就是确定“端”到底在哪里。“小跳蚤生出了更小的跳蚤……如此往复……”。