迁移到微服务与DevOps,改变软件开发效能! 这本书就够了!

一如既往,技术行业正处于巨大的转变之中,物联网、软件定义网络以及软件即服务(SaaS)仅为其中几例。由于这些创新,对能够改进应用开发和部署过程的平台和架构的需求很大。各种规模的公司现在都需要能够简化应用更新过程的框架和架构,以便让最新版本更频繁地推向市场而不会给开发和部署团队增加过多负担。

像许多类似的转变一样,这个转变仍在早期,这个领域的许多技术和框架来了又走。然而,屹立不倒的赢家仍在持续不断地改善整个世界的软件,让软件的开发者——我们——能够比以往更敏捷地创建新应用和更新现有应用。在我看来,微服务和容器就是赢家,这两个热门话题都具有持久性。与单体方法这种最常用的开发与部署应用的方式相比,微服务简化了这些流程,特别是那些需要多个团队而且代码持续增加的大型项目,在这种情况下,即便是代码中的小改动也可能造成严重的延期。微服务通过将敏捷性和伸缩性整合到应用开发和部署中来处理当今的大型代码,所有这些都在一个已证明的范型中。

这正是本书的用武之地。我最初开始学习微服务时,网上有几个有价值的资源(特别是,我推荐Chris Richardson的网站和James Lewis与Martin Fowler的个人网站),但通过系统性地构建案例来阐述为什么CTO或工程团队的主管应该(或不应该)迁移到微服务的书却不多。市场上有明显的空白。我对这个主题掌握得越多,就越忍不住想:“为什么我不能成为填补这个空白的人呢?”很快,我就开始为自己的书集思广益。

目标读者

我写这本书时主要考虑两类读者。第一类是富有软件及系统工程经验的学生、设计师和架构师。尽管你可能很熟悉微服务或容器,但本书可能是一本完全致力于微服务或容器的书。本书不但提供了这两个主题的全面概述,而且提供了充足的信息和分析来帮助你决定何时利用以及何时不利用这些技术。在微服务或容器上有实战经验的读者也许想一带而过前两部分而直接投入第三部分,第三部分提供了功能完整的Helpdesk服务的示例,它是遵循标准的面向服务架构(SOA)方法编写的。这个案例研究会讨论这样的一个应用架构如何转换为基于微服务的架构以及Docker如何用于这个场景。我认为这个表面之下的深入探索是真正的享受,它将激发读者的兴趣,使其投身微服务和容器世界。

本书的其他目标读者是从业务角度关注这两个主题的非程序员——对了解基础知识感兴趣的管理者或项目经理。也许你阅读过一篇关于微服务的有趣博客,它可能是团队一直在寻找的解决方案,但似乎不能找到好的后续书籍。也许你偶尔听到工程师谈及Docker容器并想加深了解以便融入讨论中。无论何种原因,本书对任何考虑更有效的更新应用或开发新应用的方法的管理者而言都应该是理想读物。特别是,本书充满了易于理解的示例而且没有什么专业术语。

本书适合任何试图实现以下目标的人阅读:

  • 使组织更有效地创建工业级强度的软件;
  • 转换至微服务和Docker容器并了解它们与SOA有何区别;
  • 作为学校课程的一部分学习微服务和Docker,以获取高度市场化的新技能。

简言之,本书适合所有想更多了解微服务和Docker容器的人。我希望你也是其中一员!让我们开始吧。

 内容简介

本书作者长期担任系统架构和工程团队的领导者,他在本书中分析了两个最热的新技术趋势——微服务和容器。正如作者所展示的,微服务和Docker容器能够为应用开发和部署带来前所未有的敏捷性和伸缩性,特别是在速度是关键而小错误可能带来灾难性后果的复杂的大型项目中。 

为了便于读者学习如何利用微服务和Docker 来驱动模块化架构设计、按需扩展、应用性能和可靠性、上市时间、代码复用以及DevOps 效能的指数级提升,作者不但提供了从单体架构迁移的详细指导和完整路线图,而且提供了一个带领读者了解企业级SOA 系统迁移的深入的案例研究。 

本书对软件架构师/开发者、希望继续坚持使用旧方法的系统专业人员以及尝试最大化这些技术的业务价值的管理者,都是很宝贵的参考资料。 

本书特色:

  • 理解微服务如何能够让使用者将应用组织到易于管理、更新和扩展的独立组件中。 
  • 决定微服务和容器是否值得投入并管理与它们相关的组织学习曲线。 
  • 应用微服务之间进程间通信的最佳实践。 
  • 以有序的方式迁移单体系统。 
  • 理解Docker 容器,了解Docker的安装和Docker接口。 
  • 网络、编排和有效地管理Docker容器。 
  • 使用Docker最大化基于微服务的应用的扩展性。 
  • 通过深入、动手的案例研究来应用所学。 

简要目录

第一部分 微服务

  • 第1章 微服务概览免费
  • 第2章 转换到微服务
  • 第3章 进程间通信
  • 第4章 微服务的迁移与实现

第二部分 容器

  • 第5章 Docker容器
  • 第6章 Docker安装
  • 第7章 Docker接口
  • 第8章 容器连网
  • 第9章 容器编排
  • 第10章 容器管理

第三部分 项目实战—学以致用

  • 第11章 案例研究:单体Helpdesk应用
  • 第12章 案例研究:迁移到微服务
  • 第13章 案例研究:容器化Helpdesk应用

结语

附录A Helpdesk应用流

附录B 安装Solr搜索引擎

样章试读:微服务概览

 技术已经改变并将继续改变世界的运转方式。反过来,这些改变又对支持这一切的技术提出新的、具有挑战性的要求。在不到20年的时间里,我们从56 KB的拨号调制解调器时代发展到100 GB的以太网时代。随着网络速度提升,企业承载了更大的压力来开发更快的软件,鉴于此,先进的高级软件语言被开发出来以适应应用的需要。相似地,在系统方面,我们从大型机演化到高速服务器,再将服务器制作成一种虚拟化和云的商品。现在,随着利用容器来更高效地使用资源,“容器化”成了一个动词。

一路走来,诸如模型-视图-控制器(MVC)、企业集成模式(EIP)和面向服务的架构(SOA)等新范式层出不穷。基于微服务的架构是时下技术世界的话题。让我们一探究竟。

1.1 什么是微服务

微服务是一种独立的能力,其被设计为可执行程序或进程,并通过超文本传输协议(HTTP)、RESTful Web服务(构建在表述性状态转移[REST]架构之上)、消息队列等标准但轻量级的进程间通信机制来与其他微服务进行通信。使微服务与标准应用相区别的是,每个微服务各自进行开发、测试、部署和按需伸缩,并独立于其他微服务。

微服务概念继承了软件开发的所有最佳原则,包括松耦合、按需扩展和面向服务,仅举数例。

独立的能力是什么意思?这意味着每个微服务仅完成一个功能,对于所有使用者而言其行为是相同的。以订单管理服务为例,它只处理订单,不做其他事情;它甚至不发送通知。它会调用其他负责发送通知的微服务进行处理。功能分离提供了极大的灵活性,因为每个微服务可以独立于其他微服务进行管理、维护、伸缩、扩展、复用和替换。

鉴于此定义,基于微服务的应用只是组织在一起的几个独立自主的微服务,其中每个服务提供具体明确的功能并通过定义良好的协议进行通信,以提供全部应用功能。可以将这种范式描述为基于微服务的架构,其中每个微服务作为单独的进程运行。

读者也许想了解这与基于SOA的单体应用有何不同。其不同之处在于:单体应用中,所有功能被打包成一个大的可执行文件或WAR文件,这也称为单体实现(monolithic implementation)。

让我们用一个简单的例子来探讨这个问题:一个可以从网上访问的计算器应用。对于单体应用,所有计算器操作(加、减等)可能是作为单独的程序功能来实现的,一个功能会直接调用另一个功能来完成其操作。只有一个进程在运行,而通信则通过标准的程序功能调用。整个设计看起来应该如图1-1所示。

图1-1 一个简单计算器应用的单体架构

微服务对于这个异常简单的例子可能小题大做了,但这仅仅是为了方便我们理解。假定一个开发人员遵从微服务范式构建了这个计算器应用,其将计算器提供的每个操作构造成独立的服务,如图1-2所示。这个例子中,一个微服务通过HTTP协议或其他协议的进程间调用来访问另一个微服务。在之前的例子中,如果任何函数遇到一个讨厌的bug(如越界),它会让整个应用挂掉。然而,使用微服务,只有受影响的服务无法使用,其他服务仍然可供用户使用。

图1-2 一个简单计算器应用的基于微服务的架构

这个简单的例子意在强调遵从微服务范式的最大好处:它通过将应用分割成可管理的独立组件来简化复杂应用的实现。这种简化在诸多方面都有很大的帮助,比如能够在不影响其他服务的情况下增加许多能力。

此外,每个微服务可以独立升级或按需伸缩。例如,假设我们需要用现有功能创建一个新操作:找到给定数字的平方数。这个操作很直观并且几乎不触碰现有代码。我们新建了一个微服务,这个微服务调用了“乘法”微服务的已发布标准API(见图1-3)。结果,相较于单体应用需要重新编译、重新部署等工作,以及可能导致的停机,我们只需要编写、编译和部署一个微服务。

图1-3 使用新微服务轻易地增加“平方数”功能

我们也可以创建不直接被客户端应用调用而只被其他微服务调用的微服务,如图1-4所示。图中客户端可能只调用第一层的3个微服务,然而第一层的第一个微服务也许会调用它后面第2层和第3层的两个微服务,如图中箭头所示。这两个微服务被称为辅助性微服务。

图1-4 一个微服务调用其他微服务

微服务并非新概念,但由于单体应用带来的挑战,它最近正日趋普及。

让我们通过另一个例子来探讨这些挑战。考虑一个电子商务系统以及它可能牵涉的高层组件,如图1-5所示。

对于中小型企业,这个系统最初可能运行良好。运维团队构建一个软件包并将其部署到生产环境中,而且通过部署多个应用副本并在它们前面放置一个负载均衡器就可以很容易地提供水平伸缩。随着业务的增长,所需的能力也随之增加,这进一步扩大了代码和团队的规模,相应地,部署、发布和支持应用的复杂性也随之增加。随着时间流逝,应用会变得更复杂,这使其更难为应用的开发者界定清晰的代码和功能归属。此刻,事情趋向于分崩离析,组织开始面对如下挑战:

图1-5 单体电商系统的基本组件

  • 性能问题;
  • 伸缩性;
  • 更长的回归测试周期;
  • 更长的升级和重新部署周期,导致无法部署小修补和改进;
  • 计划外停机;
  • 升级期间可能停机;
  • 困在现有技术和编程语言上;
  • 无法仅伸缩所需的组件或功能。

这些挑战带来的诸多影响中,通常未被关注的一点是工程团队所经受的挫败和随之而来的离职率的增加。

对于这些情况,微服务范式可能非常有用,但该范式只适用于大型单体应用,因为如果应用很小或者只是支撑着很小的业务,那么伴随着微服务的一些成本可能使其不值得那样去做。当企业达到这样的成熟度时,需要花费大量投入来分解单体应用;组织通常开始用微服务开发新功能,而后,基于投资回报,会慢慢开始分解旧应用。

设想一下,如果我们要升级之前例子中的购物车组件。取决于软件的架构和遗留系统,这也许不仅要添加或更新代码,也许还要对涉及购物车组件的所有代码或功能进行回归测试。它还要重新编译、测试和重新部署整个应用,这可能导致停机或拖慢应用。另外,假如一个开发人员觉得用某种新语言(例如Scala)编写这个功能会容易和高效,这个期望可能要一直等到容许用这种新语言重写整个应用时才能满足。基本上,应用开发者受困于前人所做的选择,这样的选择也许在当时是正确的但已然不是最好的了。

让我们看看微服务对这种情况有何帮助。正如我们所讨论的,我们会把所有主要的单体组件分解成独立的微服务,如图1-6所示。

图1-6分解为独立微服务的电子商务系统组件

这些微服务被单独部署,并且每个微服务执行一个单独的功能。如果我们想修改购物车微服务,我们要处理更少的代码,也就是说,仅处理这个具体的微服务,而且这会更容易测试和部署。微服务不仅解决了单体服务带来的挑战,它还具有推动组织走向持续交付的若干优点。

1.2 模块化架构

如果检视整个行业的软件项目历史,我们会发现只有29%的大型项目在指定的成本、时间和质量范围内获得了成功——依据Standish Group的“CHAOS Report 2016”。这意味着2015年的项目有71%失败了或遇到了麻烦。失败可能是由于质量问题、没有完成、预算超支等。因此,许多意在让软件组织遵从的新实践和软件管理标准被设立起来(如IEEE的软件工程标准、软件测试标准)。这些标准意在通过应用最佳实践来控制复杂性。这在两个方面给予了帮助:首先,增加项目完成的机会;其次,增加了应用的使用期限或寿命。

软件应用或平台的平均寿命是4~6年,之后它们会由于种种原因而渐渐废弃。原因可能包括随时间变化的需求、由于遗留架构而无法伸缩、过时的技术(考虑到技术世界的变化速度)等。业界倾向于追赶下一个潮流,这意味着使用最新的技术、新架构和最佳实践来重写软件或平台。但在某些时候,必须要问一句:真的需要更改每一个组件,也就是整个软件包吗?不见得。某些组件或其部分采用新技术也许会做得更好,但那通常行不通,因为架构并没有提供模块化——能让我们用重写的代码来替换单独的软件组件或其部分。

由于我们一直在开发单体应用,因此需要遵循标准来应对复杂性。如果使用微服务范式来分解这种复杂性,我们最终会得到一个显著增加使用期限的模块化架构。此外,我们可以立即减少对诸多标准和庞大的软件开发过程的依赖,从而节省时间,进而加快整个软件开发的生命周期。

除了流程效率,在我们想要升级平台时模块化架构也会节省大量开销。不同于一切从头开始的方式,我们可以如外科手术般精准地移除过时的微服务并用正确的技术和设计实现新的微服务来替换它们。这是使用微服务范式的关键长期效益之一,并且是其区别于其他范式的显著优势之一。然而,大多数情况下,仅从模块性增加所获得的收益就使基于微服务的方法值得投资。

1.3 微服务的其他优点

除了我们目前讨论的内容,微服务还为组织及其工程师带来了如下好处。

  • 简单性。由于每个微服务仅完成一个清晰明确的功能,因此需要处理的代码更少,代码内部的内聚和依赖更低,产生bug的可能性也更小。
  • 伸缩性。要扩展单体应用,我们需要在负载均衡器后面的几台服务器上部署重资源的应用。不可能只对应用的一部分进行扩展,要么不做要么都做。使用微服务,我们可以只扩展那些预期有很高负载的组件,如图1-7所示。提供不同级别的伸缩性非常容易并且是微服务的显著特征。

图1-7 伸缩性对比

  • 持续交付。由于代码库中更少的相互依赖以及更快的开发周期,微服务范式支持持续交付和DevOps文化并对其有实质帮助。
  • 更大的自由和更少的依赖。微服务需要独立自主。一个开发团队能够专注于自己的微服务并自由地增强功能而无须担心破坏其他微服务,只要他们遵守接口契约或实现向后兼容的新契约。
  • 故障隔离。故障隔离是指系统的一部分发生故障不会导致整个系统崩溃。也就是说,这个故障与整个系统是隔离开的。对于单体应用,系统任何部分的故障都会搞垮整个系统,因为系统是一个可执行程序或进程。对于微服务,一个微服务中的故障可能会导致受影响的微服务崩溃,但它未必会搞垮整个应用,因为受影响的微服务运行在自己的进程空间中。例如,在一个基于微服务架构的电子商务系统中,如果产品评论的微服务崩溃了,用户仍旧可以查看库存、挑选物品、检查购物车以及下订单。然而,他们在评论微服务的问题得到解决前无法查看评论。如果这个应用是单体的,评论服务的问题可能会让整个应用停机。
  • 数据隔离和去中心化。单体应用通常使用一个中央数据库来存储和共享所有数据,与此不同,微服务提供了隔离这些数据的机会。通常,每个微服务拥有自己的数据并且不与其他微服务直接共享自己的数据。
  • 选择。单体应用中所有应用组件必须使用单一的数据库、平台和编程语言,与此不同,基于微服务的应用提供了为具体工作选择最好工具的机会。一个微服务可能使用Linux操作系统上的Oracle,另一个微服务则可能使用Microsoft平台上的NoSQL数据库。没必要再长期委身于技术栈。

1.4 微服务的缺点

没有什么是免费的。要想获得微服务提供的所有好处,必须付出一些代价。如果迈向微服务,我们需要关注这种架构带来的挑战。不过,不必担心。接下来,我们要学习如何使用某些系统和应用来应对这些挑战。现在,让我们列出微服务带来的一些挑战。

  • 故障排查的复杂性。微服务通过微服务间的通信来提供所有能力,这增加了潜在的故障点。因此,这让回答下面这类问题变得更加困难:

◇ 系统在给定的任何实例上是否健康?

◇ 如果最终用户报告了性能缓慢或超时这样的问题,该从何处着手开始排查?

在单体应用中,端到端地追踪请求更为容易。然而,在基于微服务的应用中,每个最终用户的请求可能被分解成多个请求并触及多个微服务来获得响应。故障排查可能会变得有点棘手。

  • 增加的延迟。进程内通信(就像在单体应用中使用的那种)要比微服务使用的进程间通信快得多。
  • 运维的复杂性。面对实际应用中成百上千的微服务,运维团队需要应对复杂的基础设施、部署、监控、可用性、备份和管理问题。某种程度上,我们正将单体架构的复杂性迁移至微服务的系统层面。尽管如此,这种复杂性可以通过高层自动化来处理。
  • 版本控制。由于基于微服务的应用也许有数以千计的微服务,版本控制和管理变得有点复杂。这需要更好的版本控制和管理系统。
发布了556 篇原创文章 · 获赞 298 · 访问量 90万+

猜你喜欢

转载自blog.csdn.net/epubit17/article/details/104905622