左耳听风_023_22_从亚马逊的实践谈分布式系统的难点
你好,我是陈浩网名左耳朵house.从目前已经公开的资料来看呢,分布式服务化的架构思想呢实现最早的公司啊应该是亚马逊。
因为早在二零零二年的时候呢,亚马逊的CEO杰夫贝佐斯啊就向全公司颁布了这么几条架构规定。
第一呢就是所有团队的程序模块都要通过service interface的方式将数据和功能开放出来。
第二呢就是团队间程序模块的消息,通信啊都要通过这些接口啊。
第三呢就是除此之外啊,没有其他的通信方式,其他形式呢一概也不允许,也就是不能直接链接别的程序,不能直接读取其他团队的数据库,不能使用共享内存模式,不能使用别人的模块的后门等等。
那唯一允许的通信方式呢就是调用service interface.那第四呢,任何技术都可以使用,比如HTTPCORBA、 pop、 sub和自定义的网络协议等等。
第五呢就是所有的service interface毫无例外,都必须从骨子里到表面上设计成能对外界开放的。
也就是说呢团队必须做好规划与设计,以便未来啊把接口开放给全世界的程序员没有任何例外。
那最后第六条呢就是不这么做的人啊会被炒鱿鱼。
那这个呢应该就是AWS出现的基因吧。
那AWS全称呢是amazon well service啊,当然前面也说过,采用分布式系统架构之后呢,会出现很多的架题。
首先呢就就一个线上上障障工单单会在不同的服务和不同的团队中啊转过来转过去。
那其次呢就是每个团队啊都可能成为一个潜在的DD dos攻击。
那除非每个服务都要做好配额和限流。
那还有呢就是监控和查错变得更加复杂杂,除,除非非非常强大的监控手段。
另外,服务发现和服务治理理会会变变得常复杂杂。
那为了克服这些问题,那亚马逊这么多年的实践让他可以运维和管理,极其杂杂分分式式务架构。
那那觉觉得主要有这么几点。
第一点呢就是分布式服务的架构啊,需要有分布式的团队架构。
那在亚马逊呢,一个服务由一个小团队负责,从前端到数据,从需求分析到上线运维。
那这个呢是良性的分工策略,就是按职责分工,而不是按技能分工。
那第二点呢就是分布式服务查错不容易。
那一旦出现比较严重的故障,就需要整体查错。
那出现一个s二的故障就可以看到每个团队的人啊都会上线。
在工单系统里呢就能看到在故障发生的。
一开始啊大家都在签到,并且自查自己的系统。
那如果没问题呢,也要在线待命,等待问题的解决,我在故障处理的最佳实践应对故障。
这一讲中啊详细的讲过这个事儿。
那第三点呢,就是没有专职的测试人员,也没有专职的运维人员。
那由开发人员啊来做所有的事情。
那开发人员做所有事情的好处呢,就是吃自己的狗粮,自己写的代码,自己维护,自己养,会让开发人员明白,写代码容易自护,代码复杂。
那这样一来呢,开发人员在接需求做设计、写代码做工具的时候呢,都会考虑软件的长期维护性。
那第四点呢就是运维优先,崇尚简化和自动化。
那为了能够运维这么复杂的系统呢,亚马逊内啊在运维上下了非常大的功夫自在。
人们所说说的deo OS这个事儿呢,亚马逊在十多年前啊就做到了亚马逊最为强大的就是运维,拼命的对系统进行简化和自动化。
那亚马逊呢做到了可以轻松运维,拥有上千万台虚拟机的AWS云平台。
那最后呢就是内部服务和外部服务啊是一致的。
不管是从安全方面还是接口设计方面,不管是从运维方面还是故障处理的流程方面,亚马逊的内部系统啊都和外部系统一样对待。
那这样做的好处呢,就是内部系统的服务啊,随时都可以开放出来。
而且从第一天开始呢,服务提供方就有对外服务的能力。
那可以想象以这样的标准运作的团队啊,他的能力会是什么样的。
在进化的过程中呢,亚马逊遇到的问题很多,甚至还有很多几乎没有人会想到的非常生僻的东西,他都一一学习和总结了,而且啊都解决的很好。
这构建分布式系统啊非常难,这其中充满了各种各样的能力,但亚马逊呢还是毫不犹豫的走了下去。
那这也是因为啊亚马逊想做平台,而且呢不是像淘宝这样的中介式流量平台,而是那种可以对外输出能力的平台。
亚马逊觉得呢自己没有像史蒂出乔布斯这样的牛人啊,不可能做出像iphone这样的爆产品品。
而呢呢用户天生就是众口难调,与其做一个大家都不满意的软件,还不如把一些基础能力啊对外输出引入外部的力量呢,来一起完成一个用户满意的产品。
那这其实呢就是在建立自己的生态圈。
啊,虽然在今天看来啊,这个事已经不不齐了,但是贝索斯斯啊早在十五年前误误导了,实在是个天才。
所以分布式服务架构呢是需要从组织到软件工程,再到技术上的一个大的改造,需要比较长的时间来磨合和改进,并且啊不断的总结教训和成功的经验。
我们再来看一下分布式系统在技术上需要满意的问题。
那第一呢就是异构系统的不标准问题。
那这个问题呢主要表现在软件和应用不标准,但要协议不标准,数据协议不标准,而有呢开发和运维的过程和方法不标准。
那不同的软件,不同的语言啊会出现不同的兼容性和不同的开发测试和运维标准。
那不同的标准呢会让我们用不同的方式来开发和运维,引起架构复杂度的提升。
比如有的软件修改配置,要改它的点cof文件。
而有的呢则是调用管理的API接口。
那在通讯方面呢,不同的软件用不同的协议,就算是相同的网络协议里呢,也会出现不同的数据格式。
还有呢不同的团队啊,因为使用不同的技术也会有不同的开发和运维方式。
那这些不同的东西呢会让我们的整个分布式系统架构啊变得异常复杂。
所以分布式系统架构呢需要有相应的规范。
比如我看到很多服务的API出错,不返回HTP的错误状态码,而是返回一个正常的状态码两百。
然后呢,在RTP body里面的jason字符串中啊,写一个error拉blaba error message.而这简直就是一种反人类的做法。
那实在不明白啊,为什么会有很多这样的设计啊,这样监控怎么做?那现在呢你应该使用swagger的规范了。
那再比如呢我看到很多公司啊,他们的软件配置里呢就是一个key value的东西。
那这样的东西呢灵活到可以很容易的被滥用,还有不规范的配置命名,不规范的值,甚至呢在配置中直接嵌入前端展示的内容。
那一个好的配置管理呢应该分为三层,底层呢和操作系统相关,中间层呢和中间件相关。
那最上面呢和业务应用相关。
于是呢底层和中间层啊是不能让用户灵活修改的,而是只让用户选择,比如操作系统的相关配置啊,应该形成模板来让人选择,而不是让人乱配置的那只配配系统形成的规范啊,我们才能hold得住众多的系统。
再比如数据通讯协议。
那通常来说呢,作为一个协议,一定要有协议头和协议体。
那协议头呢定义了最基本的协议数据,而协议体啊才是真正的业务数据。
那对于协议头呢,我们需要非常规范的让每一个使用这个协议的团队啊都使用一套标准的方式来定义。
那这样呢我们才容易对请求进行监控调度和管理。
那这样的规范还有很多,我在这儿呢就不一一列举了。
那下面呢我们再来谈谈分布式系统在技术上需要注意的第二个问题啊,也就是系统架构中的服务依赖性问题。
对于传统的单体应用来说呢,一台机器挂了整个软件啊就挂掉了。
但是你千万不要以为啊在分布式的架构下不会发生这样的事儿。
在分布式架构下呢,服务是会有依赖的那一个服务依赖链上的某个服务挂掉了,就可能会导致多米诺骨牌效应的出现。
所以在分布式系统中呢,服务的依赖啊也会带来一些问题。
比如非关键业务被关键业务所依依赖,它就会导致非关键业务啊变成了一个关键业务。
那还有呢就是在服务依赖链中会出现木桶短板效应,就是整个SLA呢由最差的那个服务决定。
那这个呢就是服务治理的内容了。
服务治理不单需要我们定义出服务的关键程度,还需要我们定义或者描述出关键服务或服务调用的主要路径。
那没有这个事情呢,我们将无法运维或者管理整个系统。
这里需要注意的是,很多分布式架构啊在应用层上做到了业务隔离啊,但是在数据库节点上并没有。
那如果一个非关键业务把数据库拖死了,那么会导致全站不可用。
所以数据库方面啊也需要做相应的隔离。
也就是说呢最好一个业务线啊,用一套自己的数据库啊,这就是亚马逊服务器的实践。
系统间呢不能读取对方的数据库,只通过服务接口耦合啊,这也是微服务的要求。
我们不但要拆分服务,还要为每个服务啊拆分相应的数据库。
除了异构系统的不标准问题,服务依赖性问题,分布式系统在技术上需要注意的。
第三个问题呢,就是故障发生的概率啊会更大。
在分布式系统中呢,因为使用的机器和服务会非常忙,所以故障发生的频率啊也会比传统的单体应用更大。
只不过呢单体应用它的故障影响面很大。
而分布式系统中呢,虽然故障的影响面可以被隔离啊,但是因为机器和服务多出故障的频率啊也会多。
那另一方面呢,因为管理复杂,而且没人知道整个架构中有什么,所以呢非常容易犯错误。
你会发现啊对分布式系统架构的运维啊简直就是一场噩梦。
我们会慢慢的明白,出现故障不可怕,而故障恢复时间过长才可怕,故障影响面过大才可怕。
那运维团队呢在分布式系统下会非常忙忙到,每时每刻都要处理大大小小的故障。
我看到很多大公司啊都在自己的系统里拼命的添加各种监控指标,有的能够添加出几万个监控指标。
而我觉得这完全是在使蛮里,那一方面呢,信息太多等于没有信息。
那另一方面呢,SRE要求我们定义出key matriss啊,也就是所谓的关键指标。
然而他们啊却没有,这其实啊是一种思维上的懒惰。
但是刚才所说的都是在救火阶段,而不是防火阶段。
所谓防火剩余救火,我们还要考虑怎样防火。
那这个呢就需要我们在设计或运维系统的时候呢,都要为这些故障做考虑。
就是所谓的design for failure,在设计的时候呢就要考虑如何减轻故障。
那如果无法避免呢,也要使用自动化的方式来恢复故障啊,减少故障的影响面。
因为啊当机器和服务的数量变得越来越多的时候,啊,你会发现人类的缺陷就成为了瓶颈。
那这个缺陷呢就是人类啊无法对复杂的事情做到事无巨细的管理。
只有机器自动化才能帮助人类。
也就是说人管代码代码才管机器人,不管机器。
最后呢分布式系统啊在技术上的第四个问题就是多层架构的运维复杂度啊更大。
那通常来说呢,我们可以把系统分成四层基础层平台层、应用层和接入层。
那所谓基础层呢就是我们的机器网络和存储设备等等。
那平台层呢就是我们的中间件层,tom cat、 mysq、 LREDIS、卡夫卡之类的软件。
那应用层呢就是我们的业务软件,比如各种功能的服务。
而接入层呢就是接入用户请求的网关负载均衡或者CDNDNS这样的东西。
那对于这四层呢,我们需要知道任何一层的问题啊都会导致整体的问题。
那其次呢,没有统一的视图和管理,导致运维被割裂开来,会造成更大的复杂度。
那很多公司呢都是按技能分工的,他们按照技能呢把技术团队分为产品开发、中间件开发、业务、运维和系统运维等等子团队。
那这样的分工呢导致的结果就是大家各管一摊,很多事情啊完全连不在一起。
那整个系统呢会像多米诺骨牌一样啊,一个环节出现问题就会倒下去一大片。
因为没有一个统一的运维视图啊,不知道一个服务调用是怎么经过每一个服务和资源的,就会导致出现故障的时候呢,要花上大量的时间啊在沟通和定位问题上。
那之前我在某个云平台的一次经历啊,就是这样的。
从接入层到负载均衡,再到服务层,再到操作系统底层设置的keep live参数啊完全不一致。
导致用户户发发现软件运行行为为和文当中定义的完全不一样。
而工程师查错的规程啊,简直就是一场噩梦,以为找到了一个结果,还有一个来来回回花了大量的时间啊,才把所有的keep live的参数啊设置成一致的浪浪费了太多的时间。
分工呢不是问题,问题在于分工后的协作是否统一和规范,而这一点呢一定要重视。
好了,我们来总结一下今天分享的主要内容。
首先呢我以亚马逊为例啊,讲了它是如何做分布式服务架构的,遇到了哪些问题,还有呢就是如何解决的。
我认为呢亚马逊在分布式服务系统方面的这些实践和经验积累是AWS出现的基因。
随后呢我分享了在分布式系统中啊需要注意的几个问题。
随后呢也给出了应对方案。
我认为呢构建分布式服务需要从组织到软件工程,再到技术上的一次大的改造啊,需要比较长的时间来做磨合和改进。
随后呢不断的总结教训和成功的经验。
那在下节课中呢,我们会讲一讲分布式系统的技术栈,希望能对你有帮助欢迎你啊,也来分享一下你在分布式架构中啊遇到的各种问题。
我在文末呢列出了分布式系统架构的本质系列文章的目录啊,方便你快速找到自己感兴趣的内容。
那如果你在分布式系统架构方面啊,有其他想了解的话题和内容啊,也欢迎留言给我。