当前位置: 首页 > 科技观察

15年资深架构师详解:某大型互联网公司微服务转型实践

时间:2023-03-13 04:45:56 科技观察

【.com原稿】微服务是一个比较大的话题。根据我以往的经验,本文将以Netflix为例,分享一家大型互联网公司如何从单体APP成功转型为微服务。文章主要涉及微服务的历史、应用场景、与单体服务的区别、微服务在技术和企业组织结构上带来的挑战,以及如何合理选择单体服务架构和微服务架构。微服务的产生历史如下图所示,是谷歌搜索微服务的结果:从2014年开始关注微服务,搜索微服务的人越来越多,2016年左右达到顶峰。从地域上看,很多国家都在关注,比如印度、欧洲等,很多公司都在使用微服务架构。下面以Netflix为例,分享微服务的演进及其带来的挑战。Netflix微服务的演进我是2012年加入Netflix的,从中了解到:Netflix从2008年到2009年开始在自己的数据中心做单体web应用,那时候是一个巨大的Java包,里面写了无数程序它,导致许多问题。2010年,重量级部分开始转出。2013年到2014年,其他模块陆续调出,发布了很多开源微服务工具,引起了硅谷乃至全球很多人的关注。直到2015年左右,Netflix基本完成了向微服务的过渡,从自己的数据中心完全转移到了亚马逊的云平台上。下面是微服务的示意图:微服务看起来很复杂,但实际上是由相互连接的服务器组成的。下图展示了Netflix在微服务方面的使用情况:从时间上看,Netflix是硅谷较早采用微服务的公司,在采用过程中也受到了很多质疑,尤其是对于从数据中心迁移到云端的传统企业,需要时间慢慢接受。微服务和单体服务的概念和区别如下,是一个很常见的单体APP的示意图:从powser到各个公司的Apache,形成一个包含各种功能的WAR包,最后是MySQL存储层。这样测试起来比较容易,部署也很简单。MonolithicAPP的优点如下:易于开发。许多IDE和框架都支持它,例如SprintMVC、RubyRails、PythonDjango等。易于测试。只需启动应用程序并使用Selenium测试UI即可实现端到端测试。易于部署。只需将打包的应用程序复制到服务器即可。易于扩展。通过在负载均衡器后面运行多个副本,轻松水平扩展。DevOps相对简单。专门的DevOps团队会做。MonolithicAPP的缺点如下:应用过于庞大和复杂,难以完全理解并快速正确地进行更改。应用程序将变得越来越大,可能会减慢启动时间。每次更新都必须重新部署整个应用程序。如果代码库有新的变化,变化的影响往往没有被很好地理解,这会导致大量的手动测试。持续部署是困难的。当不同的模块具有冲突的资源需求时,单体应用程序也可能难以扩展。可靠性差。任何模块中的错误(例如内存泄漏)都可能导致整个网站瘫痪。此外,由于应用程序的所有实例都是相同的,因此该错误将影响整个应用程序的可用性。采用新技术或框架很困难。框架或语言的更改在时间和成本上可能非常昂贵,因为它会影响整个应用程序。随着代码库、组件和团队规模的增长,会出现各种问题。要点总结如下:原代码太大,IDE打不开。单机内存不够编译运行代码。部署一次需要很长时间。开发的速度跟不上产品的需求,一个小小的改动就需要重新编译整个源码。某个模块中的一个小错误可能会导致整个网站瘫痪。随着组织的发展、功能的增加和技术堆栈瓶颈的出现,需要进行新的更改。但是面对如此庞大的视频网站,有些程序使用了Java包,并且有自己的数据中心。那时候还没有微服务的概念,但是他们已经有了拆分内容的意识。什么是微服务?“微”是指团队规模、代码行数还是API端口数?不,不同的人对微服务有不同的定义。我个人同意这个描述:Looselycoupledserviceorientedarchitecturewithboundedcontexts。关键是LOOSELYCOUPLED和BOUNDEDTEXT。LOOSELYCOUPLED是指每个服务可以独立更新,而BOUNDEDTEXT是指一个服务只需要做自己的事情,外界使用API??等接口。也就是说,微服务必须做到独立部署,拥有独立的技术栈,定义上下文,拥有清晰的归属。微服务和单体服务的对比如下,这是一个非常形象的微服务和单体服务的对比图:单体服务把所有东西都放在一个大盒子里,这个大盒子什么都有。微服务更像是汽车箱。每个盒子都包含特定的功能模块和物品,一切都可以灵活拆分。也就是说,在MonolithicAPP中,所有的部分都在一个巨大的包中。在微服务的构建下,有很多独立的小服务,通过API接口连接成一个大系统。下图是MonolithicAPP的架构:Netflix会支持很多设备。一开始,所有的设备都会通过一个负载均衡器,变成一个包含一切的巨大程序,最后变成一个巨大的Oracle数据中心。这样一来,问题就大了,大家都很反感。下图是微服务的架构:从上图可以看出,每个服务是可以拆分的,有自己的数据源,不一定是Oracle。可以根据业务场景使用不同的数据库,完全由各个团队决定。综上所述,我们从技术角度分析Netflix为什么选择微服务。从业务的角度来看,Netflix选择微服务的原因有以下几点。原因有以下三个:可用性。24x7全天候保护,防止单点故障。在庞大的CODEBASE的情况下,往往一个小小的错误,比如在代码中多加一个冒号,就会导致整个程序无法编译,甚至导致整个网站崩溃。对于大型互联网公司来说,需要避免单体服务导致的宕机。可扩展性。Netflix当时流量占全美三分之一,付费用户超过9000W,增长非常快。为了能够在组件遇到瓶颈时快速扩展,通常需要添加新机器以使其正常工作。但是在传统的单体服务上,整个部分是绑定在一起的,很难扩展。速度。对于互联网公司,尤其是ToC需要快速上线,速度很重要。速度是互联网时代成功的关键。大型互联网公司实施微服务。一旦需要新的功能,可以立即开启一个新的微服务,也可以在有限的几个微服务中进行更改,而不是基于庞大的数据库。微服务带来的技术挑战软件架构从单体服务向微服务的转变带来了巨大的技术挑战。在下方选择您认为比较重要的内容进行分享。它主要涉及以下几个方面的挑战:服务发现(Servicediscovery)。传统的单体服务相对简单,但微服务有成百上千台服务器。对于用户来说,服务器的选择是一个问题。操作复杂性增加–DevOps。分布式系统固有的复杂性。网络延迟,容错。服务接口版本控制,存在不匹配。测试(需要整个生态系统来测试)。FANOUT->网络流量增加。面对这些挑战,分享一些关键技术,如服务发现、服务注册、服务注册模式、瓶颈/热点、断路器和测试等。对于服务发现,用户最难决定的是选择哪个服务器从中获取数据。有两种解决方案:客户端发现和服务器端发现。如下图,就是clientdiscovery:clientdiscovery是指客户端部署一个ServiceInstance来存储所有的地址和各种信息。客户端收到数据后,可以自行决定从哪个服务器获取信息。如下图,是服务器端发现:客户端不需要写很多程序,而是通过LoadBalancer把信息传递给某个服务器。服务注册中心服务注册中心是服务发现的关键部分。它是一个包含服务实例网络位置的数据库,需要具有高可用性和最新性。服务注册一定不能宕机,一旦出现问题,恢复非常困难。对于服务注册和发现,Netflix使用自研的Eureka组件。服务注册模式服务注册模式分为自注册和第三方注册两种:自注册模式。这种方法的一个很好的例子是NetflixOSSEureka客户端。Eureka客户端处理服务实例注册和注销的所有方面。SpringCloud项目实现了各种模式,包括服务发现,以便轻松地使用Eureka自动注册服务实例,只需使用@EnableEurekaClient注释注释您的Java配置类。服务注册模式比较简单,不需要任何其他系统组件。但它将服务实例耦合到服务注册表。您必须在您的服务使用的每种编程语言和框架中实施注册代码。如下图,是第三方注册模式:开源注册器项目——通过Registrator,部署为Docker容器的服务实例会自动注册和注销,支持多种服务注册中心,包括etcd和Consul。NetflixOSSPrana主要用于以非JVM语言编写的服务,是一个与服务实例并行运行的辅助应用程序。Prana向NetflixEureka注册和注销服务实例。Registrator的优点是服务与服务注册表断开连接,无需为开发人员使用的每种编程语言和框架实现服务注册逻辑。相反,服务实例注册在专用服务中集中处理。不利之处在于,除非将其内置到部署环境中,否则它是另一个需要设置和管理的高度可用的系统组件。如何处理FANOUT如下图,在单体服务中只有一个请求,但在微服务中很多情况下,客户端必须通过不同的微服务器来收集所有的数据,并且有很多请求。如下图,解决办法是缓存:尽量缓存自己已有的数据,访问时优先于缓存,不选择其他部分。瓶颈/问题如下图所示。当整个服务中的某个情况成为瓶颈时,就会调用X,X会从用户账号中获取数据。X调用Y,Y也从用户帐户中获取数据。这样一来,用户服务就会成为一大瓶颈。一旦宕机,前端APP肯定拿不到数据。处理方式如下图所示:Netflix对于一些共享数据使用了更多的方法不重复调用,可以使用HTTPHEADER来传输数据。如何提高可用性(Availability)?微服务不一定能保证可用性,有的时候即使微服务做得不好也更容易宕机,所以必须采用一些好的容错机制。所谓容错,原则上就是当发生错误时,尽量让一个服务器停止。常见的解决方案包括Timeout、Circuitpeaker(熔断器)和Bulkheads(隔板)——拒绝新请求。Fuse在Netflix中被广泛使用,如下两图所示,就是熔断过程:Fuse主要是在一个服务去它的下游服务获取数据的时候用到的,不应该直接拿,而是要经过一次熔断程序。当下游服务出现错误,或者有较长的延迟时,熔断器会停止,然后去下游服务获取数据,直接返回。熔断器也会继续判断服务是否恢复,恢复后继续取数据。这样一来,问题就堵在了某个地方,不会出现服务连接问题,导致微服务大规模崩溃。微服务测试测试是一件令人头疼的事情,尤其是端到端的微服务架构变得尤为困难,主要是因为数百个服务属于不同的团队。我个人推荐单元测试和服务测试。端到端测试(EndtoEndTest)应该尽量避免,可以通过一些监控工具来完成。Netflix使用ChaosMonkey工具来测试延迟和服务可靠性。这里值得注意的是,每个微服务至少要有三个实时备份,以免宕机后无法恢复。微服务带来的企业组织架构挑战我们之所以分享微服务带来的挑战,归根结底还是人在做事。微服务是去中心化的,让每一个服务拥有独立的权利,这将导致组织结构的巨大变化。企业的组织架构往往体现在技术架构上。微服务能否在企业内部取得成功,很大程度上取决于企业的组织架构和技术架构能否匹配。以Netflix为例,分享在向微服务架构转型过程中对团队和企业架构的挑战。优化速度,而不是效率Netflix正在考虑将速度或效率作为优化的核心,最终选择了速度。因为速度是赢得市场最重要的因素,速度意味着比竞争对手更快地了解客户需求并给他们想要的东西。当竞争对手准备好效仿时,它已经开始进行下一组改进。速度和效率之间有什么关系?强调效率通常意味着试图控制开发过程的整体流程,以消除重复工作并避免错误,同时降低成本。共同的结果是专注于节流,而不是开源。如果你说“我这样做是因为它更有效率”,那么意想不到的结果就会拖慢你的速度。这并不是鼓励浪费和重复开发,而是应该首先优化速度,其次才是效率。提高效率并不是企业的最终目的。提高效率应该会带来更快的业务增长。以结果为导向,减少不必要的流程,尽可能的增加每个微服务团队的自由度,比如开发工具,开发流程等,再以结果为导向。Netflix有3个框架,其中Java是主流。每个团队可以根据自己的情况选择技术框架,甚至数据库可以选择MySQL或者NoSQL。尽量减少进程,为什么会有进程?流程往往是对过去的总结,比如一些错误,经验总结,然后以此来控制流程。但是过多的流程会减慢对新事物和突发事件的反应速度。还需要明确每个团队的目标,减少相互依赖。下图展示了传统公司的产品开发流程:大部分软件开发团队都是孤岛,相互之间没有交集。软件开发项目的标准流程始于与用户体验和开发团队的产品经理开会,讨论新功能的想法。在代码中实现这个想法后,代码被传递给质量保证(QA)和数据库管理团队,通常需要进行大量沟通。与系统、网络和SAN管理员的通信通常是通过内部TICKET系统进行的,导致过程非常缓慢。一些公司尝试以初创公司的形式开发产品,但初创公司的开发团队不一定是微服务开发团队。虽然公司有很多小型创业公司形式的小团队,但每个团队的内部结构仍然和传统公司一样。如下图,就是微服务产品开发团队:微服务产品开发团队没有不同的产品经理、UX经理、开发经理等,在它的孤岛里向下管理。每个产品功能(作为微服务实现)都有一个经理负责监督一个团队,该团队处理微服务软件开发的各个方面,从构思到部署。平台团队提供产品团队通过API访问的基础架构支持。在整个过程中,产品以Devop的形式发布和维护。如何合理选择单体服务架构和微服务架构并不是所有的场景都适合微服务。应根据实际情况选择微服务或单体服务:微服务适用于大流量,系统具有一定的复杂性,需要快速开发新产品的互联网公司,用户数量增长迅速,大多数的目录。单体服务的应用场景一般是流量比较小,功能单一或者很简单,没有快速迭代,内部工具,POC工具或者网站。曾任乐视美国视频平台技术总监、Netflix视频内容平台技术总监。超过15年互联网公司(LinkedIn、LeTV、Netflix和PayPal)的技术开发、架构和团队管理经验。主要职责范围为高并发后端服务架构、微服务架构、大数据平台架构等,以及端到端的整个产品开发。感兴趣的领域是视频、支付、互联网金融和电子商务。以上内容根据罗益民先生在WOTA2017“微服务架构”专场的演讲整理而成。【原创稿件,合作网站转载请注明原作者和出处为.com】