【本文为WOT2016互联网运维与开发者大会直播内容。全新主题WOT2016企业安全技术峰会将于2016年6月24-25日在北京珠三角JW万豪酒店隆重举行!】现在我们去任何地方都要先问有没有Wi-Fi。网络显然已经影响了我们的生活。互联网的诞生就是为了服务大量的用户。在这个时代,几乎没有应用是为单机而生的。每个公司的每个产品都会面临用户不可预知的海量请求。显然,这是通过分布式程序来解决的,比依赖单机要可靠得多。不幸的是,如果一开始你的架构设计不具备可扩展性,不管你有多少台机器,有多少个云解决方案,你顶多是把单机程序跑在一个虚拟的单机上。接下来,让我们回到WOT2016互联网运营与开发者大会,跟随滴滴出行的顶级架构师,了解分布式时代架构设计和程序开发面临的新挑战,以及滴滴出行的应对思路。李令辉,滴滴出行高级架构师,2014年年中加入滴滴。他经历了滴滴的快速成长阶段,见证了滴滴从打车软件到出行平台的转变。资深移动互联网从业者,对移动互联网技术发展趋势和技术团队组建有独到见解。多年互联网架构设计经验,擅长高性能、高并发、高可用的架构设计。曾主导滴滴打车技术迭代中核心服务架构的升级。分布式时代的困境单机应用将不复存在很少有应用能够准确预测用户数量。因此,从一开始就为数亿用户设计一个极其复杂的分布式架构,几乎是不可能的。因为这不仅会带来极高的成本,还会牺牲整个系统的灵活性。并不是每家公司都像谷歌一样,在创业初期就有为全球所有数据开发分布式文件系统的雄心。大多数公司必须从几台服务器开始。随着用户不断增长,并发请求越来越多,业务越来越复杂,白林不得不将程序从单机迁移到多机。将单个进程拆分成多个服务的问题。每个人的工作量缺乏分布式开发工具,是由互联网上的多个节点组成的分布式环境,通过网络耦合。这种分布所带来的不可避免的复杂性被无缘无故地增加了。然而,真正的分布式开发工具还远未成熟。程序员可以使用的工具还是古老的VI,四十多年前的Emacs、十几年前的Eclipse等单机开发工具,服务之间的依赖关系完全无法管理,日志格式和日志内容也无法保证一致且可追溯。上线、扩容、降级等运维工作和规范没有很好的设计。任何问题或开发都需要多人协作,效率极低。重新发明轮子的解决方案似乎是百花齐放的行业解决方案。但实际上大部分都是基于开源的RPC方案,几个比较成熟的方案包括ErlangOTP、ScalaAkka等。公司使用各种定制的解决方案来解耦,管理彼此之间的关系,相互依赖,一起做一件事。较大的公司将执行操作和维护规范。每个公司或社区都使用自己对这种分布式环境的理解。这样做的后果就是大家在开源社区的基础上重复同样的事情,这是一件非常昂贵的事情。此外,许多解决方案是根据特定的业务场景制定的。例如,通信软件对实时性和高可用性的要求很高。但是电商不太在意一个请求能否快速返回,而是强调数据的一致性。因此,每个业务特性决定了有不同的解决方案,很少有为分发而生的解决方案。它们都是从单机解决方案演进或逐渐变化而来的。这些问题会让每一个从中开发的人不得不知道,全局对研发效率是一个巨大的伤害。分布式确实是一个足够复杂的领域,很难有一个通用的解决方案。那么,在设计分布式系统架构时应该考虑哪些方面呢?分布式架构设计容错的基本要素在分布式环境中,错误无处不在,无时无刻不在发生。此外,错误不仅仅是机器故障。当上百人参与研发的时候,肯定有人会犯错,每个人都会犯错,正常情况下都会犯错。因此,研发团队不仅要思考如何避免错误,更要思考如何在小错误下不影响业务的情况下保持服务的健康运行。而一旦不加考虑地降级架构的各个模块,势必会带来巨大的灾难。数据格式数据格式实际面临的困境与依赖管理一样。因为每个人只负责单个模块,并不关心整个业务用什么数据格式来沟通。有多少代码用于验证数据?打包/解包数据使用了多少?如果不统一,就会陷入泥潭,工作效率低得无法接受,日志收集和监控几乎无法实现。路由层路由层没有优劣之分。只要能解决业务问题,降低运维成本和开发成本,就是很好的解决方案。但是,重要的是尽量避免同时使用多个解决方案。函数调用是路由,反射是路由,URL是路由,IP+Port+RPC的Function也是路由。虽然,并不是所有的服务都可以统一路由。路由的灵活性和标准化决定了运维的难度,一味的追求灵活性无缘无故地增加了一个数量级的运维工作。架构的本质是控制复杂性。主要方法是分而治之,解耦,耦合本质上就是路由。服务为了满足用户的新需求,紧跟市场的新步伐,各家互联网公司的研发团队从未停下脚步,确保服务的不断演进和升级。这也带来了很多问题:如何稳定高效地迭代?那些依赖于刚刚迭代的服务的遗留服务呢?我想对某个服务/模块做ABTest怎么办?多个模块可以同时做ABTest吗?如果不是,研发变成系列发射真的好吗?看这些问题,一定要从大局出发,最重要的是接口的统一,形成一个统一的标准,让大家在一个共同的尺度上。监控现在大家在做的监控,基本上就是监控机器的状态。事实上,在几百台机器的较小规模上,这样做意义不大。真正应该监控的应该是程序。要严格控制程序的状态,只能靠日志了。因此,每个架构师都必须考虑如何设计一个可以监控服务并提供可监控接口的日志系统。每个架构师都应该考虑你的服务是如何被监控的,你必须提供一个可监控的接口。对于采集区间,一般来说,规模越大,采集粒度越低,规模越小,采集粒度越高。另外,监控的信息是Pull还是Push?所有的监测结果都需要人工处理吗?日志可以作为系统间交互的数据吗?这些问题需要大家根据自己的业务场景继续探索。你的运维计划是否完善?每个公司的运维团队都在思考这个问题。您的目的是降低成本并提高效率。请合理计算你的成本和效率,就是你要数人,而不是机器。可以通过以下几个维度进行评估:资源利用率是多少?对于大多数团队来说,研发的人力成本远高于机器成本。你首先要考虑的是你的人都是并发的,而不是你的CPU被吃光了。解决方案简单吗?这对应人才招聘的门槛。对于一个新人来说,总是需要快速上手一个项目来验证自己的能力,所以解决方案一定是比较简单的。如何扩容和缩容应该有一套完整的解决方案。开发、测试和发布过程是否需要人工干预?对小流量测试的支持如何?回滚、限流、断流等方案是否统一提供?滴滴出行的分布式结构设计思想让Linux强大,是因为每个模块只负责最简单的事情,面对输入输出,输入输出的格式是确定的。分布式架构设计思路应该也是一样的。相同的规则和相同的用法结合起来可以发挥巨大的作用。滴滴出行的分布式架构设计要解决的问题不仅仅是简单的机器运维,而是如何规避研发过程中人在复杂环境中可能面临的风险,解决架构设计粗糙带来的低效问题,不可控的、不稳定的状态。这样的架构设计带来的一个巨大的好处就是,当信息流进来的时候,进入信息分发,信息分发把它分发到合适的pipeline,pipeline经过处理后才发送到下一个pipeline。每个管道只做输入和输出,以实现高可用性和高吞吐量。许多云服务提供商都提供这种解决方案。这样做的好处是我们只需要管理消息队列,我们??可以在任何节点复制流量。你可以在任何一个链接中获取它的所有数据,不再依赖日志,只依赖输入输出。输入输出都保存在硬盘上,数据不会丢失。另一个优点是进程是异步传输的。同步模型的一个明显缺点是,在所有层中,如果一个进程在执行某个请求时需要一段时间才能返回信息,那么该进程将等待直到收到返回信息,然后再继续执行。当流量很大时,重试可能会导致某个链接挂掉,某个链接的连接数满了。本方案中只有两三个连接,不需要等待数据返回,只需要确认收货即可,不需要一一核对。低成本和高性能。但是这种架构设计显然不能解决所有问题。比如在使用MySQL作为存储和其他必须同步的服务时,需要为有状态服务提供一个抽象层Service,上面的服务都可以请求它。你可以理解为在Linux中输入一个命令来读取一个文件,那个文件是有状态的并且存在于那里,而这些模块是无状态的。滴滴选择了Docker+Kubernetes作为分布式集群管理方案。它的优点是可以直接提供资源管理、资源隔离、部署、升级、路由等需求。但是,只有Kubernetes是不够的,Kubernetes只能管理那些无状态的事务。并不是所有的东西都可以完全抽象成无状态状态。有状态的部分如何扩展,要看具体的业务场景,很难设计。我想说的是,没有完美的解决方案。如果你想自己开发这个东西,建议你只使用一种解决方案,而不是每一种。但没办法,面对不同的研发人员、不同的场景等现实,目前还没有定论。也希望借这篇文章与业内同仁共同探讨。【演讲视频】分布式时代的架构设计(上)分布式时代的架构设计(下)
