学完微软技术总监整理的 44 个微服务架构设计模式,我涨薪了

用户头像
Java架构师迁哥
关注
发布于: 2020 年 09 月 10 日





前言

“微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间相互协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务和服务之间采用轻量级的通信机制相互沟通(通常是基于HTTP的Restful API).每个服务都围绕着具体的业务进行构建,并且能够被独立的部署到生产环境、类生产环境等。另外,应尽量避免统一的、集中的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构”



单体应用 vs 微服务架构



优点



  1. 提升开发交流,每个服务足够内聚,足够小,代码容易理解;

  2. 服务独立测试、部署、升级、发布;

  3. 按需定制的DFX,资源利用率,每个服务可以各自进行x扩展和z扩展,而且,每个服务可以根据自己的需要部署到合适的硬件服务器上;每个服务按

  4. 需要选择HA的模式,选择接受服务的实例个数;

  5. 容易扩大开发团队,可以针对每个服务(service)组件开发团队;

  6. 提高容错性(fault isolation),一个服务的内存泄露并不会让整个系统瘫痪;

  7. 新技术的应用,系统不会被长期限制在某个技术栈上;



缺点



  1. 没有银弹,微服务提高了系统的复杂度;

  2. 开发人员要处理分布式系统的复杂性;

  3. 服务之间的分布式通信问题;

  4. 服务的注册与发现问题;

  5. 服务之间的分布式事务问题;

  6. 数据隔离再来的报表处理问题;

  7. 服务之间的分布式一致性问题;

  8. 服务管理的复杂性,服务的编排;

  9. 不同服务实例的管理。



作者简介:

克里斯·理查森(Chris Richardson)



世界著名的软件大师,《POJOS in Action》等技术名著的作者,也是著名开源项目 Cloud Foundry 和 Eventuate 的创始人。他的研究领域包括微服务架构设计、分布式数据管理、事件驱动的应用架构 、领域驱动设计、持续交付、Spring 框架、Scala、NoSQL 数据库等。



喻勇



在技术圈驰骋多年,曾担任过微软技术布道师,VMware Cloud Foundry 生态建设负责人,并有幸引领了国内容器技术的创业浪潮。目前定居加拿大,关注微服务架构、云原生应用等领域。



本书适合的读者

本书的重点是架构和开发,适合负责开发和交付软件的任何人阅读。



侧重于解释微服务架构的设计模式和其他概念。无论读者使用何种技术栈,我的目标都是让你们可以轻松读懂这本书。你只需要熟悉企业应用程序架构和设计的基础知识即可。特别是,需要了解三层架构、Web应用程序设计、关系型数据库、使用消息和基于REST的进程间通信,以及应用程序安全性的基础知识等概念。本书的代码示例使用Java 和Spring框架。为了充分利用它们,读者应该对Spring框架有所了解。



对读者提醒的:

第一、要记住微服务不是解决所有问题的万能“银弹”。



第二、编写整洁的代码和使用自动化测试至关重要,因为这是现代软件开发的基础。



第三、关注微服务的本质,即服务的分解和定义,而不是技术,如容器和其他工具。



第四、确保你的服务松耦合,并且可以独立开发、测试和部署,不要搞成分布式单体(Distributed Monolith),那将会是巨大的灾难。



第五、也是最重要的,不能只是在技术上采用微服务架构。拥抱DevOps的原则和实践,在组织结构.上实现跨职能的自治团队,这必不可少。还必须记住:实现微服务架构并不是你的目标。你的目标是加速大型复杂应用程序的开发。



部分内容展示

1.1.1 FTGO应用程序的架构



FTGO应用程序是一个典型的分层模块化企业级Java应用。图1-1展示了它的架构。FTGO应用程序拥有一个六边形的架构,我们会在第2章中详细介绍这类架构风格。在这个六边形中,应用程序的核心是业务逻辑组件。在业务逻辑外围是各种用来实现用户界面和与外部服务集成的适配器。





业务逻辑由包含了服务和领域对象的模块组成,一些典型的模块包括Order Management、Delivery Management、Billing和Payments。若干适配器用来完成与外部系统的对接工作,一些是入站(inbound)适配器,它通过调用业务逻辑来处理各类请求,包括REST API和Web用户界面适配器。其他是出站(outbound)适配器,它使业务逻辑能够访问MySQL数据库并调用Twilio和Stripe等云服务。

尽管逻辑上FTGO是一个模块化的架构,这个应用还是被整体打包成一个单一的WAR文件,部署运行在Tomcat之上。这是一个非常典型并且被广泛应用的单体软件架构风格:一个系统被作为单一的单元打包和部署。如果FTGO应用是采用GoLang语言编写的,那它的交付形态就是一个单一的可执行文件;如果是用Ruby或者Node.js开发的,那它的交付形态就是一个目录和它之下的子目录中包含的各种源代码。单体架构本身并不存在问题, FTGO开发人员在选择单体架构时为他们的应用程序架构做出了一个很好的决定。



1.1.2 单体架构的好处:



在FTGO发展的早期,应用程序相对较小,单体架构具有以下好处。



  • 应用的开发很简单:IDE和其他开发工具只需要构建这一个单独的应用程序。

  • 易于对应用程序进行大规模的更改:可以更改代码和数据库模式,然后构建和部署。

  • 测试相对简单直观:开发者只需要写几个端到端的测试,启动应用程序,调用REST API,然后使用Selenium这样的工具测试用户界面。

  • 部署简单明了:开发者唯一需要做的,就是把WAR文件复制到安装了Tomcat的服务器上。

  • 横向扩展不费吹灰之力:FTGO可以运行多个实例,由一个负载均衡器进行调度。



但是,随着时间的推移,开发、测试、部署和扩展都会变得更加困难。我们来看看为什么。



1.1.3 什么是单体地狱:



不幸的是,正如FTGO的开发人员已经意识到的,单体架构存在着巨大的局限性。类似FTGO这样渴求成功的应用程序,往往都不断地在单体架构的基础之上扩展。每一次开发冲刺(Sprint),FTGO的开发团队就会实现更多的功能,显然这会导致代码库膨胀。而且,随着公司的成功,研发团队的规模不断壮大。代码库规模变大的同时,团队的管理成本也不断提高。

如图1-2所示,那个曾经小巧的、简单的、由一个小团队开发维护的FTGO应用程序,经过10年的成长,已经演变成一个由大团队开发的巨无霸单体应用程序。同样,小型开发团队现在已成为多个所谓Scrum敏捷团队,每个团队都在特定的功能领域工作。作为架构扩展的结果,FTGO已经陷入了单体地狱。开发变得缓慢和痛苦。敏捷开发和部署已经不可能。我们来看看这是为什么。





过度的复杂性会吓退开发者

FTGO应用程序的首要问题是它的过度复杂性。这个系统本身过于庞大和复杂,以至于任何一个开发者都很难理解它的全部。因此,修复软件中的问题和正确地实现新功能就变得困难且耗时。各种交付截止时间都可能被错过。

更糟糕的是,这种极度的复杂性正在形成一个恶性循环:由于代码库太难于理解,因此开发人员在更改时更容易出错,每一次更改都会让代码库变得更复杂、更难懂。之前图1-1所示的干净、模块化架构并不能反映现实世界的真实情况。真实情况是FTGO应用正在一步一步地成为一个巨大的、令人费解的“脏泥球”。

玛丽记得她曾经在某个技术会议上遇到一个极客,他开发了一个分析数以千计JAR文件和数百万行代码之间依赖关系的工具,那时候玛丽觉得这个工具也许能帮助FTGO厘清头绪。现在她并不这么想。玛丽认为更好的方法是迁移到更适合复杂应用程序的架构风格:微服务架构。

开发速度缓慢

因为要跟这些极度复杂的系统打交道,FTGO的开发人员发现他们日常的开发工作变慢了。这个巨大的项目把开发人员的IDE工具搞得很慢,构建一次FTGO应用需要很长时间,更要命的是,因为应用太大,每启动一次都需要很长的时间。因此,从编辑到构建、运行再到测试这个周期花费的时间越来越长,这严重地影响了团队的工作效率。

从代码提交到实际部署的周期很长,而且容易出问题

另一个困扰FTGO应用团队的问题是:把程序更改部署到生产环境的时间变得更长,整个流程几乎令人抓狂。目前团队每月对生产环境进行一次更新部署,通常都是在周五或者周六的晚上。玛丽总是读到一些关于SaaS应用持续部署的“黑科技”:每天都可以在业务时间对应用进行多次修改并快速完成部署。显然,对于像Amazon.com这样的公司,2011年就已经能够做到每11.6秒完成一次变更到生产环境的部署。一个月完成几次更新,对FTGO开发人员来说简直就是神话。实现持续部署更是遥不可及的梦想。

FTGO的敏捷实践是不完整的。工程团队被分成各个小队(squad),以两周为一个冲刺周期。不幸的是,从代码完成到运行在生产环境是一个漫长且费力的过程。一个问题是,众多开发人员都向同一个代码库提交代码更改,这常常使得这个代码库的构建结果处于无法交付的状态。当FTGO尝试采用功能分支来解决这个问题时,带来的是漫长且痛苦的合并过程。紧接着,一旦团队完成一个冲刺任务,随后迎接他们的将是一个漫长的测试和代码稳定周期。

把更改推向生产环境的另一个挑战是运行测试需要很长时间。因为代码库如此复杂,以至于一个更改可能引起的影响是未知的,为了避免牵一发而动全身的后果,即使是一个微小的更改,开发人员也必须在持续集成服务器上运行所有的测试套件。系统的某些部分甚至还需要手工测试。如果测试失败,诊断和修复也需要更多的时间。因此,完成这样的测试往往需要数天甚至更长时间。

难以扩展

FTGO团队在对应用进行横向扩展时也遇到了挑战。因为在有些情况下,应用的不同模块对资源的需求是相互冲突的。例如,餐馆数据保存在一个大型的内存数据库中,理想情况下运行这个应用的服务器应该有较大容量的内存。另外,图片处理模块又需要比较快的CPU来完成图形运算,这需要应用部署在具有多个高性能CPU的服务器之上。因为这些模块都是在一个应用程序内,因此FTGO在选用服务器时必须满足所有模块的需要。

交付可靠的单体应用是一项挑战

FTGO应用的另一个问题是缺乏可靠性,这个问题导致了频繁的系统故障和宕机。系统不可靠的一个原因是应用程序体积庞大而无法进行全面和彻底的测试。缺乏可靠的测试意味着代码中的错误会进入生产环境。更糟糕的是,该应用程序缺乏故障隔离,因为所有模块都在同一个进程中运行。每隔一段时间,在一个模块中的代码错误,例如内存泄漏,将会导致应用程序的所有实例都崩溃。 FTGO开发人员不喜欢在半夜因为生产环境的故障而被叫醒。业务人员也对由此造成的收入损失和丧失客户信任而头疼不已。

需要长期依赖某个可能已经过时的技术栈

FTGO所经历的单体地狱的最终表现,也体现在团队必须长期使用一套相同的技术栈方面。单体架构使得采用新的框架和编程语言变得极其困难。在单体应用上采用新技术或者尝试新技术都是极其昂贵和高风险的,因为这个应用必须被彻底重写。结果就是,开发者被困在了他们一开始选择的这个技术之内。有时候这也就意味着,团队必须维护一个正在被废弃或过时的技术所开发的应用程序。

Spring框架本身保持着持续的演进和更新,同时维持着向后的兼容性。所以理论上来说FTGO可以随着升级。不幸的是,FTGO的应用程序使用了与Spring新版本不兼容的框架,开发团队也挤不出时间来更新这些旧框架。久而久之,这个应用的绝大部分都被卷入了这个已经过时的框架。更不幸的是,FTGO的开发人员一直想尝试类似GoLang和Node.js这样的非JVM类编程语言,然而在单体架构之下,这是做不到的。



1.2 为什么本书与你有关:



如果你正在翻看这本书,那么你很可能是软件开发人员、架构师、CTO或工程研发的副总裁。你负责的应用程序已超出其单体架构所能够支撑的范围,就像FTGO的玛丽一样,你正在努力应对软件交付,并想知道如何逃避单体地狱。或许你担心你的组织正在走向单体地狱之路,你想知道如何在为时已晚之前改变方向。如果你需要让手中的软件项目避免陷入单体地狱,那么这本书就是为你所写。

本书花了很多时间来解释微服务架构的概念。无论你现在使用何种技术栈,我的目标都是让你可以轻松地读懂这本书。你所需要的只是熟悉企业应用程序架构设计的基础知识。特别是,你需要了解以下内容:



  • 三层架构。

  • Web应用程序设计。

  • 使用面向对象设计来开发业务逻辑。

  • 关系型数据库:SQL和ACID事务的概念。

  • 使用消息代理和REST API进行进程间通信。

  • 安全,包括身份验证和访问授权。



本书中的代码示例是使用Java和Spring框架编写的。这意味着为了充分利用这些示例,你还需要熟悉Spring框架。



1.3 你会在本书中学到什么:



读完这本书后,你会理解和掌握如下知识:



  • 微服务架构的基本特点,它的好处和弊端,以及应该在什么情况下使用微服务架构。

  • 分布式数据管理的架构模式。

  • 针对微服务架构应用程序的有效测试策略。

  • 微服务架构应用程序的部署方式。

  • 把单体应用重构为微服务架构的策略。



你也会掌握如下技术:



  • 使用微服务的架构模式来设计应用程序的架构。

  • 为服务开发业务逻辑。

  • 使用Saga在进程间维护数据的一致性。

  • 实现跨服务的数据查询。

  • 更高效地测试微服务架构应用程序。

  • 开发生产环境就绪的应用程序,实现安全性、可配置性和可观测性。

  • 把现有的单体应用重构为服务。



1.4 拯救之道:微服务架构



玛丽意识到,FTGO应用程序必须迁移为微服务架构。

有趣的是,软件架构其实对功能性需求影响并不大。事实上,在任何架构甚至是一团糟的架构之上,你都可以实现一组用例(应用的功能性需求)。因此,即使是成功的应用程序(例如FTGO),其内部架构也往往是一个大泥球。

架构的重要性在于它影响了应用的非功能性需求,也称为质量属性或者其他的能力(-ilities)。随着FTGO应用的增长,各种质量属性和问题都浮出水面,最显著的就是影响软件交付速度的可维护性、可扩展性和可测试性。

一方面,训练有素的团队可以减缓项目陷入单体地狱的速度。团队成员可以努力维护他们的模块化应用。他们也可以编写全面的自动化测试。但是另一方面,他们无法避免大型团队在单体应用程序上协同工作的问题,也不能解决日益过时的技术栈问题。团队所能做的就是延缓项目陷入单体地狱的速度,但这是不可避免的。为了逃避单体地狱,他们必须迁移到新架构:微服务架构。

今天,针对大型复杂应用的开发,越来越多的共识趋向于考虑使用微服务架构。但微服务到底是什么?不幸的是,微服务这个叫法本身暗示和强调了尺寸。针对微服务架构有多种定义。有些仅仅是在字面意义上做了定义:服务应该是微小的不超过100行代码,等等。另外有些定义要求服务的开发周期必须被限制在两周之内。曾在Netflix工作的著名架构师Adrian Cockcroft把微服务架构定义为面向服务的架构,它们由松耦合和具有边界上下文的元素组成。这个定义不错,但仍旧有些复杂难懂。我们来尝试一个更好的定义。



本书完整目录

由于字数原因接下来把目录截取给大家观看,需要完整PDF版的朋友转发+关注后添加助手vx:bjmsb10;免费获取;



第1章 逃离单体地狱







第2章 服务的拆分策略





第3章 微服务架构中的进程间通信







第4章 使用Saga管理事务 







第5章 微服务架构中的业务逻辑设计





第6章 使用事件溯源开发业务逻辑







第7章 在微服务架构中实现查询







第8章 外部API模式





第9章 微服务架构中的测试策略(上)





第10章 微服务架构中的测试策略(下)





第11章 开发面向生产环境的微服务应用







第12章 部署微服务应用





第13章 微服务架构的重构策略





总结

设计模式类的书籍大多非常抽象,但是这本书竟然能把微服务构建和实施过程中的的细节(或坑点)讲的如此清楚,真的很难得。国内这两年也出过不少微服务的书,但大多是讲“术”而不是“道”,而我认为,对于微服务方案来讲,“术”是最容易搞定的,比如你来个SpringCloud全家桶,“术”的问题就基本解决,更何况,SpringCloud/SpringBoot本身非常容易上手使用,让大家有一种我学会它就会做微服务一样的错觉,有时候这种错觉真的会害死人,大家不妨看看身边有多少工程是为了微服务而微服务...而这本书,以“道”为主,清晰讲解实施微服务的过程中,我们需要关注哪些问题,解决方案有哪些,然后辅以“术”,让人读起来非常爽。另外,这本书不太适合初级工程师,比较适合有一定工程实践经验的中高级工程师或架构师们看看!



写在最后

这份PDF领取方式也简单,作为电子版全网首发,需要领取的朋友麻烦帮忙转发转发这篇文章+关注小编,然后添加助手vx:bjmsb10;免费获取



用户头像

还未添加个人签名 2020.09.07 加入

还未添加个人简介

评论

发布
暂无评论
学完微软技术总监整理的44 个微服务架构设计模式,我涨薪了