文档目录
- Spring Cloud Alibaba七天训练营(一)基础知识篇
- Spring Cloud Alibaba七天训练营(二)分布式配置
- Spring Cloud Alibaba七天训练营(三)服务注册与发现
- Spring Cloud Alibaba七天训练营(四)分布式服务调用
- Spring Cloud Alibaba七天训练营(五)服务熔断和限流
- Spring Cloud Alibaba七天训练营(六)分布式消息(事件)驱动
- Spring Cloud Alibaba 七天训练营(七)分布式事务
前言
近些年随着云技术的发展,越来越多的用户选择使用云技术来代替将传统的 IT 基础设施。在云技术发展的早期,业界的关注点集中在虚拟化、分布式、存储等 Iaas 方面的技术。但是随着“云原生”概念的提出,大家的注意力开始转移到如何构建更加适合云环境运行的应用上来。
“什么样的架构才是适合在云环境中运行”是一个非常大的问题,在此先不展开讨论,而是到 CNCF 对云原生的定义中寻找答案:
云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式API。这些技术能够构建容错性好、易于管理和便于观察的松耦合系统。结合可靠的自动化手段,云原生技术使工程师能够轻松地对系统作出频繁和可预测的重大变更。
从上文的定义中可以发现“微服务”在云原生技术中占有这非常重要的位置。在 jakarta.ee 2019 年的调研报告中也印证了这一点,超过40%公司选择采用微服务架构来构建云上系统:
让我们继续把视角聚焦到 Java 语言下。Pivotal 依托于 Spring 这个 Java 语言下编程模型的事实标准,结合大量业界经验,为广大 Java 开发者带来了 Spring Cloud 框架。该框架是对云环境下微服务开发中需要解决的各种问题的标准化,以帮助开发者快速实现分布式系统中的某些常见模式(例如,配置管理,服务发现,断路器等)。
同时,基于 Pivotal 强大的标准制定能力与影响力,Spring Cloud 拥有一个强大的国际化社区,阿里巴巴作为设个社区里重要的成员,也贡献出了 Spring Cloud Alibaba 这套优秀的实现,这也是目前整个 Spring Cloud 体系下最完善并且在持续更新的实现方案。
学习目标
通过本次课的学习,你应该了解或掌握如下知识点:
- 微服务的发展历程
- 微服务的基本形式
- Spring 、Spring Boot 、Spring Cloud 的职责与关系
- Spring Cloud Alibaba 的功能与定位
- Java 工程脚手架的使用方法
- Sandbox 沙箱环境的使用发方法
理论篇
俗话说,没有最好的架构,只有最合适的架构。微服务架构也是随着信息产业的发展而出现的最有普遍适用性的一套架构模式。通常来说,我们认为架构发展历史经历了这样一个过程:单体架构 -> SOA 面向服务架构 -> 微服务架构。
单体架构
在我们还是学生的年代,我们创建的绝大部分应用都属于单体应用。那个时候,我们几乎都是一个人在开发导师布置下来的各种实验。我们会把数据库连接、业务逻辑处理、展示逻辑等放在一起,甚至会在处理用户请求的地方直接连接数据库(多么美好的回忆啊 ^_^ )。
后来,我们会学习到MVC架构以及由此衍生出来各种多层架构,由此便开启了应用的拆分之旅。多层架构的本质,是按照技术职责将应用做水平拆分,每一层解决的技术问题相对集中,层与层之间做单向依赖。这样做可以帮助我们更好的管理我们的代码,大大提升了后期的维护效率。但是,此时应用还是一个应用,部署时也是按照一个整体运行。我们看到的应用架构应该类似下面的样子:
在程序规模不大,开发人员很少的时候,下面的有点是非常显著的:
- 开发简单。单体应用的结构,天然决定了所有代码都集中在一起,开发者不需要在多个应用之间来回跳转来寻找其中的调用逻辑。
- 测试简单。所有代码都在一个应用里,测试人员可以很方便的做到端到端的测试(当然,很多时候测试人员就是开发者自己)。
- 部署简单。因为一个应用就是产品功能的全集,所以在部署的时候,只需要不是一款应用即可。即使是集群部署,也不会增加多少复杂度:只需要将应用部署多份即可。
- 开发迅速。上面的各种简单,带来的就是软件功能可以快速实现。很多时候,实现需求的速度是项目成功与否的决定性因素。
所以,在开发简单&独立的产品时,单体架构依然是第一优先选择。
如果故事可以一直这么简单就好了。
随着功能的持续增加、团队规模的不断扩大,我们很快就会发现单体应用的弊端:
- 应用膨胀。所有代码都在一个应用里,导致应用的代码量迅速上升,对于开发者来说,经常需要在海量的代码里找到自己需要维护的哪一行,这种体验往往是令人崩溃的。同时,对于IDE来说,一个应用内大量代码也会严重拖慢其运行效率。
- 团队合作冲突。这种冲突会体现在多个方面:开发阶段,很容易由于修改相同的代码导致代码冲突。部署阶段,又会因为“运行环境里跑的是谁的分支”而造成新的冲突。所有的这些冲突将会严重影响到团队的合作效率。
- 运行效率&稳定性。单体应用,由于逻辑都集中在一起,启动时需要完成所有的初始化工作;同时单一功能的问题也会因为运行在一个进程内,从而导致整个应用宕机。
单体架构原有的迅速、简单的优点,随着规模的扩大(功能、团队),会变得荡然无存。
为了能解决这些问题,我们自然而然就会想到分而治之的办法,即将原来的单体应用拆分开来。但是应用该怎么拆分?拆分后又会有哪些新的问题产生?如何解决这些新的问题?就留给下面的 SOA 架构来解答。
SOA 架构
SOA 是 Service-Oriented Architecture 的简写,直译为“面向服务的架构”,从命名上就可以看出“服务”是 SOA 架构里是非常重要的概念。SOA 的核心思想是“将系统的功能解构为一系列服务”:
面向服务的架构(SOA)是一个组件模型,它将应用程序的不同功能单元(称为服务)进行拆分,并通过这些服务之间定义良好的接口和协议联系起来。接口是采用中立的方式进行定义的,它应该独立于实现服务的硬件平台、操作系统和编程语言。这使得构件在各种各样的系统中的服务可以以一种统一和通用的方式进行交互。
与单体架构按照技术职责进行水平拆分不同,SOA 会按照业务领域对应用进行粗粒度的垂直拆分,至于拆分到什么程度,哪些领域可以放在一起等类似问题,可以参考一下康威定理。
应用从单体应用做了垂直拆分以后,就会变成一些相对独立的应用。此时,应用间的依赖、调用等相关问题自然而然的就会浮现出来。此时就需要下面这些技术方案来解决这些问题:
- XML - 一种标记语言,用于以文档格式描述消息中的数据。
- SOAP(Simple Object Access Protocol) - 在计算机网络上交换基于XML的消息的协议,通常是用HTTP。
- WSDL(Web Services Description Language,Web服务描述语言) - 基于XML的描述语言,用于描述与服务交互所需的服务的公共接口,协议绑定,消息格式。
- UDDI(Universal Description, Discovery, and Integration,是统一描述、发现和集成) - 基于XML的注册协议,用于发布WSDL并允许第三方发现这些服务。
- ESB(Enterprise Service Bus, 企业服务总线)- 支持异构环境中的服务、消息,以及基于事件的交互,并且具有适当的服务级别和可管理性。
一个典型的 SOA 架构模式如下图:
SOA 看似解决了单体架构的所有问题,世界似乎都变得更加美好了 ^_^
但是….
SOA 并不完美,他也有很多问题的或者说是场景下的不适应。首先就是对 SOA 的解释缺乏统一标准,上文的引用的定义也只是众多解释中使用的较为通用的一种。甚至可以这么说:一千个人眼中,有一千种 SOA 。基于此,很多厂商便借用 SOA 的大旗来推广自己的产品和标准,这又进一步加剧了问题的严重性。
除此之外,SOA 还有很多其他的问题或不足:
- 高门槛。ESB 本身就是一套非常复杂的系统,通过 ESB 落地 SOA ,对开发人员的要求很高。甚至还会需要厂商参与;
- 厂商绑定。由于缺乏统一保准,不同厂商的解决方案之间很难做切换。
- 不适应云环境。在如今的互联网时代,速度就是一切。由此诞生了敏捷开发、持续集成等在不同节点提升业务上线速度的办法。但是方向是不一致的。
- 中心化。虽然应用本身实现了分布式与水平扩展,但是 ESB 却成了系统的中枢神经。
微服务架构
对于微服务架构,一直有一种说法,认为它是 SOA 架构的一种变体,或者是 SOA 的子集。关于这个问题,我们不去讨论他的对错(其实也没有对错之分),我们直接从这两者的区别入手来理解到底什么是微服务:
传统SOA | 微服务 | |
---|---|---|
通信方式 | 基于ESB,SOAP、WSDL等重协议 | 点对点通信,开放式协议,如 RESTful、gRPC、或者是轻量级的二进制协议。 |
数据管理 | 全局数据模型以及共享存储 | 每个服务独立模型和存储 |
服务粒度 | 较粗 | 较细 |
诞生的背景 | 企业级应用 | 互联网 |
解决的问题 | 面向企业内,系统集成 | 面向最终产品,解决扩展,维护的问题 |
通信手段、数据等的不同只是表象,其本质区别还是由于两者诞生于不同历史时期,需要解决的问题域不同。SOA 解决的核心问题是复用,而微服务解决的核心问题是扩展。
关于什么是微服务,Martin Fowler 有如下的定义(更多 MartinFowler 关于微服务的内容,可以参考链接):
The microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.?
这里提到几个重要的概念:
- 一套小服务
- 独立进程
- 轻量级通信协议
- 可独立部署
- 多语言&不同储技术
这个定义对微服务做了一个比较具象化较为易于理解的描述,通常来说我们看到的为服务架构如下图所示:
但是事实上,在实际生产环境中,微服务的架构要考虑的问题远比上面的示意图复杂的多,主要包括但不限于如下问题:
- 通过服务实现组件化
- 根据业务组织系统
- 做产品而不是做项目
- 简单高效的通信协议
- 自动化基础设施
- 面向失败的设计
- 具备进化能力的设计
纵然有 Martin Fowler 这样的大神在前面引路,但是我们依然认为“微服务”不是一个被设计出来的架构,而是在不断是尝试中总结出的一套适合在互联网行业使用的架构模式。以下的是微服务较为完整的架构图(出自微服务架构模式)
今天我们所说的“微服务”是一个庞大且复杂的概念集合,它既是一种架构模式,也是实现这种架构模式时所使用的技术方案的集合。
“微服务”不是银弹
微服务并不是一劳永逸的解决了所有的问题,相反的,如果不能正确的使用微服务,则有可能被微服务自身的限制拖入另一个泥潭:
- 分布式的代价。原本在单体应用中,很多简单的问题都会在分布式环境下被几何级的放大。例如分布式事务、分布式锁、远程调用等,不光要考虑如何实现他们,相关场景的异常处理也是必须要考虑到的问题。
- 协同代价。如果你经历过一个项目上线需要发布十几个应用,而这些应用又分别由多个团队在维护。你就能深刻的体会到协同是一件多么痛苦的事情了。
- 服务拆分需要很强的设计功力。微服务的各种优势,其中一个重要的基础是对服务领域的正确切分。如果使用了不合适的切分粒度,或者是错误的切分方法,都会让服务不能很好的实现高内聚低耦合的要求。
框架篇
从 Spring 到 Spring Cloud
Spring
熟悉 java 语言的同学,对 Spring 框架应该都不陌生。从 2004 年 1.0 版本发布开始,便由于其灵活易用的特性受到了整个 Java 行业的广泛关注。经过十多年的发展,Spring 框架早已经成为 Java 语言下编程模型的事实标准。其所倡导的 IOC/AOP 概念也早已深入人心。
在 Spring 框架的早期,大家都喜欢称其为“轻量化”框架(现在好像早就没人提这个词了^_^),“轻量”是相对于 EJB 等企业级开发框架而言的。其“轻”的特性体现在:框架本身的大小很小,早期版本的jar包不超过1MB;同时不依赖于运行容器,也是说任何容器里都可以运行Spring框架;更加重要的是 Spring 是非侵入的,使用Spring开发的应用可以不完全依赖Spring的类;
Spring Boot
但是事情总会发生变化,随着 Spring 的不断发展,越来越多的组件被集成到了框架中。Spring 框架也从一个小巧精简的 IOC 容器框架变成了一套大而全的框架集合。开发者为了实现组件的整合工作,往往需要在大量的 xml 文件、java 注解 中完成各种 bean 的配置。曾经屠龙的少年,如今也变成了恶龙。
那个时候,很多比 Spring 更加简单小巧的 IOC 容器如雨后春笋般的出现。业界开始出现一种声音:Spring 是不是已经不行了,或者是在走下坡路了。就在这个时候 Pivotal 推出了 Spring Boot 来彻底的解决这些问题。
使用 Spring Boot 可以大大简化 Spring 应用的开发工作。在 Spring Boot 中无论是官方组件还是第三方框架都会提供各种“starter”来方便开发者进行依赖和集成。由于采用了“约定大于配置”的思想,开发者在引入“stater”以后只需要做少量的配置工作就可以完成框架集成工作。往往开发者只需要很少量的代码就可以实现以前大量配置文件才能做到的功能。
同时 Spring Boot 还是一套面向生产环境设计的框架。配置外化、运行情况检查功能,可以很方便的在系统外部实现对系统的管理。同时 Spring Boot 还是一个运行时容器。通过内嵌 Tomcat 、Jetty 等使得程序的运行不在依赖传统的应用服务器。这一点在云原生时代意义尤其重大。
Spring 官方对 Spring Boot 特色定义如下:
- 创建独立的Spring应用程序
- 直接嵌入Tomcat,Jetty或Undertow(无需部署WAR文件)
- 提供自以为是的“starter”依赖项,以简化构建配置
- 尽可能自动配置Spring和三方类库
- 提供可用于生产的功能,例如指标,运行状况检查和外部化配置
- 完全没有代码生成,也不需要XML配置
Spring Cloud
Spring Cloud 是什么,没有比官方的定义更能说明问题了:
Spring Cloud provides tools for developers to quickly build some of the common patterns in distributed systems (e.g. configuration management, service discovery, circuit breakers, intelligent routing, micro-proxy, control bus, one-time tokens, global locks, leadership election, distributed sessions, cluster state). Coordination of distributed systems leads to boiler plate patterns, and using Spring Cloud developers can quickly stand up services and applications that implement those patterns. They will work well in any distributed environment, including the developer’s own laptop, bare metal data centres, and managed platforms such as Cloud Foundry.
这里面提到几个关键词:
- 分布式系统中的常见模式
- 任何分布式环境
“分布式系统中的常见模式”给了 Spring Cloud 一个清晰的定位,即“模式”。也就是说 Spring Cloud 是针对分布式系统开发所做的通用抽象,是标准模式的实现。
这个定义非常抽象,看完之后并不能知道 Spring Cloud 具体包含什么功能。再来看一下 Spring 官方给出的一个 High Light 的架构图,就可以对这套模式有更清晰的认识:
可以看到这个图中间就是各个Microservice,也就是我们的这个微服务的实现,周边周围的话就是去围绕这个微服务来去做各种辅助的信息事情。例如分布式追踪、服务注册、配置服务等,都绕微服务运行时所依赖的必不可少的的支持性功能。我们可以得出这样一个结论:Spring Cloud 是以微服务为核心的分布式系统的一个构建标准。
Spring Cloud Alibaba
既然说 Spring Cloud 是标准,那么自然少不了针对标准的实现。参与这个标准实现的公司有很多,例如:Google 的 Spring Cloud GCP,Netflix 的 Spring Cloud Netflix,Microsoft 的 Spring Cloud Azure 等等。当然还有我们阿里巴巴的 Spring Cloud Alibaba。
Spring Cloud Alibaba 从 19 年初开始提交代码就获得了业界的广泛关注,从下面这张图中可以看到,在很短的时间之内,Spring Cloud Alibaba 就成为了 Spring Cloud 家族中最受关注的框架:
下面这张图很好的说明了 Spring Cloud Alibaba 的组成以及与 Spring Cloud 的关系:
图中深色的部分,其实它就是 Spring Cloud 标准,一共有3层。中间颜色最深的部分就是及整个微服务最核心的内容,包括了“ RPC 调用”以及“服务注册与发现”。第二层,也就是围绕着核心的这一圈,是一些辅助微服务更好的工作功能,包括了负载均衡、路由、网关、断路器,还有分就是追踪等等这些内容。再外层的话,主要是些分布式云环境里通用能力。
最外面这一圈,是 Spring Cloud Alibaba 对 Spring Cloud 的实现。右上部分是对于 Spring Cloud 标准的实现。例如,我们通过 Dubbo 实现了 RPC 调用功能,通过 Nacos 实现了“服务注册与发现”、“分布式配置”,通过 Sentinel 实现了断路器等等,这里就不一一列举了。左下部分是我们 Spring Cloud Alibaba 对阿里云各种服务的集成。可能很多同学会有这样的一个问题:为什么要加上这一部分呢?此时回头审视一下 Spring Cloud ,它仅仅是一个微服务的一个框架。但是在实际生产过程中,单独使用微服务框架其实并不足以支撑我们去构建一个完整的系统。所以这部分是用阿里帮助开发者完成微服务以外的云产品集成的功能。
为什么要分成两个部分呢,这也是为了打消大家对于使用了 Spring Cloud Alibaba 以后就会被平台绑定的担忧。虽然在品牌商都叫做SpringCloudAlibaba,但是在代码上,我们采用了两个独立的项目维护。分别是 Spring Cloud Alibaba 和 Aliyun Spring Boot
目前,Spring Cloud Alibaba 包含如下组件:
开源部分
- Sentinel:把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
- Nacos:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
- RocketMQ:一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。
- Dubbo:Apache Dubbo? 是一款高性能 Java RPC 框架。
- Seata:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。
平台服务部分
- Alibaba Cloud OSS: 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。
- Alibaba Cloud SchedulerX: 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。
- Alibaba Cloud SMS: 覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。
工具篇
Java 工程脚手架
Java 工程脚手架,用于帮助开发者快速生成工程骨架。解决开发者在创建工程时的组件引入、解决版本依赖、基础配置、查询样例代码等繁琐问题。只需要简单的点点鼠标,就可以生成一套标准工程骨架。
脚手架的访问地址是 https://start.aliyun.com/bootstrap.html, 打开后页面见下图:
编译框架、坐标&名称、其他基础信息等,根据实际情况按需填写。当然,很多参数默认值就可以满足大部分需求。开发者重点关注的是下面3个部分:
组件依赖
很少有开发者会使用语言最原始的sdk来实现所有功能。通常来说,大家都会使用各种技术产品的高级封装来实现相关的技术特性。这里就需要做2件事情:引入对应组件的sdk、在应用中配置组件。而通过Java 工程脚手架就可以很轻易的完成这些工作。
Java 工程脚手架中提供了 2 种寻找组件的方式:根据分类浏览&关键字搜索
这里根据组件分类寻找需要使用的组件:
也可以根据组件的关键字直接使用搜索功能寻找需要使用的组件:
无论通过哪种方式,都可以通过组件右侧的加好实现组件的选择。
应用架构
在生成的工程里,代码需要根据其逻辑职责进行分层,从而获得更好的代码组织与管理效果。在这里提供了3种应用架构供开发者选用。
- None:不做任何代码分层。
- 分层架构:标准的4层架构。分为 WEB层、控制器层、服务层、持久化层。本架构参考了《Java 编码规约》的应用分层章节。
- COLA:领域驱动设计(DDD)的实现框架之一。采用了标准的六边形架构设计,并且辅之以一套灵活的扩展体系,可以有效提升复杂业务系统开发的效率。具体参考COLA 的 GIthub工程
示例代码
我们为组件准备了很多使用方法的参考样例,这样开发者就不需要选择外组件以后,再去别的搜索引擎寻找相关组件的使用方法了。
未选择任何组件时,是不会给出任何示例代码的。示例代码是在选择了组件依赖以后,才会出现于用户选择的组件相关的示例,如下图:
由于很多案例自身也依赖其他组件,所以在选择了某个案例以后,会多出一些案例,同时依赖的组件也会增多。
本次课程使用到的案例,都可以在这里寻找到。
生成代码
仅仅完成项目配置是不够的,最终开发者需要的是项目的代码。so, show me the code
无论是出于查阅组件用法的目的,还是出于需要工程完整代码的目的,脚手架都可以很好的支持:
如果仅仅需要查阅代码,而不是下载完整工程,可以直接通过点击“浏览代码”来实现。点击该按钮以后,会打开一个包含了完整代码树以及允许查看每个文件的内容窗口:
如果需要获取所有代码内容,则可以通过点击“获取代码”来实现:
这里提供了2种获取代码的途径:直接下载代码包 & 通过 git 命令 clone 工程。如果选择使用Git命令来Clone工程,需要注意一下,这个仓库地址只能下载不能上传哦。
Sandbox 沙箱环境
Sandbox 沙箱环境,为开发者带来一套快速上手、免除任何环境依赖、免费、便捷的开发&运行环境。允许开发者在上面查看、修改、部署示例代码,并且由平台提供相关运行资源。
下面来看一下产品的界面:
左边是产品的手册&说明部分。这里会包含说当前项目的功能说明、应用架构,以及如何部署和访问这些应用的操作步骤等。一些项目中使用到的技术点以及这些相关知识,也都会在这里呈现给用户。这部分文档的目的,就是方便用户去学习和理解当前的案例。
右边的部分是应用列表。一个完整的产品,可能需要多个应用协同才能工作,这里就是用来陈列相关的应用列表,同时也是针对这些应用的操作入口。
图片中的案例是一个任务管理器产品,功能相对简单。但是麻雀虽小五脏俱全。这个产品包含两个应用:
- 服务端,的包含了这个任务管理器的所有业务逻辑,以及下层的持久化能力等。
- WEB客户端,包含了所有前端页面逻辑、与前端通信的控制器层。
这两个应用通过一个注册中心来实现服务的注册&发现。最终实现一个完整的任务管理器产品。
这些东西都会放到这里面。这就是一个非常典型的一个一个应用拆分的一个方式,对不对?这里的话,其实业务应用上它有两个行动点,一个是开发和访问点,开发之后就会打开一个 IDE。
这里面就会有整个工程的代码。这些其实是我们预计好的,大家打开就能直接看到。如果它完全部署以後点了部署按钮,我也会直接访问到这个应用。
其暴露出来的这个访问接口,我们点开发之后会看到这样一个情况。对,这个就是我们的外包 id 。
开发者可以点击“开发”按钮,打开一个 WEB-IDE 来查看和修改对应应用的代码:
这个WEB-IDE 和开发者日常使用的 IDE 是一样的,都是左侧代码树,右侧代码编辑器的标准布局。即使是不熟悉这个产品的用户,也可以非常快的上手,甚至不需要学习过程。
如果需要部署这个应用,只需要在“运维”功能下,点击“部署”按钮,此时只需要等待部署完成即可。在部署过程会有很多的日志输出,都可以通过“输出”窗体浏览:
部署完成以后,会向 WEB-IDE 返回一个访问地址,开发者只需要点击这和地址就可以访问这个应用。下图是实际的访问效果。可以看到,两个应用,一个是任务管理器的web操作页面、一个是后台数据库管理页面:
通过上面的步骤,开发者可以将案例快速部署起来。先部署试用,然后去学习和修改代码,最后再部署验证。通过这样的循环,可以让开发者很快学习和理解案例的功能和相关技术点。
对文档有任何问题,请在评论区留言!