俗话说乱花渐欲迷人眼,学习微服务应该从哪开始学呢
从这张表去学微服务
微服务全家桶:走进 Spring Cloud 的世界
了解 Spring Cloud 框架的功能定位,以及它和 Spring Boot 之
间的关系。除此之外,我还会详细讲解 Spring Cloud 的发展历史,并介绍 Netflix 和
Alibaba 两大核心组件库,以及 Spring Cloud 的版本更新策略
大话 Spring Cloud
Spring Cloud 可谓出身名门,它由 Spring 开源社区主导孵化的,专门为了解决微服务架
构难题而诞生的一款微“微服务全家桶”框架。难能可贵的是,Spring Cloud 走了一条博
采众家之长的道路,除了 Spring 开源社区的研发力量以外,它还吸纳了很多业界一线互联
网大厂的开源组件为己用,将这些经过大厂真实业务锤炼的组件孵化成为了 Spring Cloud
组件的一部分。
通过 Spring 社区发布的一张简化的架构图来看一下 Spring Cloud 的技能加点
上面这幅图中,我们可以看到有几个 Spring Boot Apps 的应用集群,这就是经过拆分
后的微服务。Spring Cloud 和 Spring Boot 达成了一种默契的配合:Spring Boot 主内,
通过自动装配和各种开箱即用的特性,搞定了数据层访问、RESTful 接口、日志组件、内
置容器等等基础功能,让开发人员不费吹灰之力就可以搭建起一个应用;Spring Cloud 主
外,在应用集群之外提供了各种分布式系统的支持特性,帮助你轻松实现负载均衡、熔断
降级、配置管理等诸多微服务领域的功能(理解这句话)
从 Spring Boot 和 Spring Cloud 的分工中我们可以看出,Spring Boot 忙活的是底层的
柴米油盐酱醋茶,Spring Boot 后勤保障做得好,才能让 Spring Cloud 毫无顾虑地投身于
微服务的星辰大海,两者合二为一完整构建了微服务领域的全家桶解决方案
到这里,相信你已经可以理解 Spring Boot 和 Spring Cloud 的侧重点,以及 Spring
Cloud 的功能定位。那么接下来,让我带你去了解一下 Spring Cloud 内部都有哪些重要
组件。
Spring Cloud 组件库的朝代更替(可以不看)
在我们开始了解 Spring Cloud 组件库之前,我得先介绍在 Spring Cloud 历史上举足轻重
的两家公司 Netflix 和 Alibaba,以及它们的恩怨情仇。这两家公司分别为开源社区贡献了
Spring Cloud Netflix 组件库和 Spring Cloud Alibaba 组件库。
说起 Netflix 可能你并不知道,但提起《纸牌屋》你一定看过或者听过,这部高分美剧就是
由这家我们俗称“奈飞”的公司出品的。Netflix 是一家美国的流媒体巨头,它靠着自己强
大的技术实力,开发沉淀了一系列优秀的组件,这些组件经历了 Netflix 线上庞大业务规模
的考验,功能特性和稳定性过硬。如 Eureka 服务注册中心、Ribbon 负载均衡器、
Hystrix 服务容错组件等。后来发生的故事可能你已经猜到了,Netflix 将这些组件贡献给
了 Spring 开源社区,构成了 Netflix 组件库。可以这么说,在 Spring Cloud 的早期阶
段,是 Netflix 打下了的半壁江山。
Netflix 和 Spring Cloud 度过了蜜月期之后,矛盾就逐渐发生了。先是 Eureka 2.0 开源计
划的搁浅,而后 Netflix 宣布 Hystrix 进入维护状态,Eureka 和 Hystrix 这两款 Netflix 组
件库的明星项目停止了新功能的研发,Spring 社区不得不开始思考替代方案,在后续的新
版本中走向了“去 Netflix 化”。以至于 Netflix 的网关组件 Zuul 2.0 历经几次跳票千呼
万唤始出来后,Spring Cloud 社区已经不打算集成 Zuul 2.0,而是掏出了自己的
Gateway 网关。在最新版本的 Spring Cloud 中,Netflix 的踪迹已经逐渐消散,只有
Eureka 组件形单影只待在 Netflix 组件库中,回忆着昔日的辉煌。
Spring Cloud Alibaba 是由 Alibaba 贡献的组件库,随着阿里在开源路线上的持续投入,
近几年阿里系在开源领域的声音非常响亮。Spring Cloud Alibaba 凝聚了阿里系在电商
领域超高并发经验的重量级组件,保持了旺盛的更新活力,成为了 Spring Cloud 社区的
一股新生代力量,逐渐取代了旧王 Netflix 的江湖地位。Spring Cloud Alibaba 组件秉承
了“大而全”的特点,就像一个大中台应用一般包罗万象,在功能特性的丰富程度上做到
了应有尽有,待我们学到 Spring Cloud 章节后你就能体会到了。这也是本课程选择
Spring Cloud Alibaba 组件的一个重要原因。
Spring Cloud 全家桶组件库
其中红色加粗的,是我们在实战环节将要集成的组件
Spring Cloud 版本更新策略
大部分开源项目以数字版本进行更新迭代,Spring Cloud 在诞生之初就别出心裁使用了字
母序列,以字母 A 开头,按顺序使用字母表中的字母标识重大迭代发布的大版本号
小版本
SNAPSHOT 版本:正在开发中的快照版本,例如 2021.0.0-SNAPSHOT,快照版代表
当前分支最新的代码进度,也是更新最为频繁的小版本类型,不推荐在线上正式环境使
用;
Milestone 版本:在大版本正式发布前的里程碑版本,例如 2021.0.0-M1,M1 代表当
前大版本的第一个里程碑版本,M2 代表第二个迭代里程碑,以此类推。在正式版本发
布之前要经历多个里程碑的迭代,像 Spring Cloud Finchley 版足足经历了 9 个 M 版
本之后,才过渡到了 RC 版。同样地,我也不推荐你在正式项目中使用 Milestone 版
本;
Release Candidate 版本:这就是我们俗称的 RC 版,例如 2021.0.0-RC1。当一个版
本迭代到 RC 版的时候,意味着离正式发布已经不远了。但是你要注意,RC 版是发布前
的候选版本,走到这一步通常已经没有新的功能开发,RC 主要目的是开放出来让大家试
用并尽量修复严重 Bug、
Release 版:稳定的正式发布版,比如 2020.0.1。你可以在自己的线上业务中放心使用
Release 稳定版。
初窥门径:我们要搭建一个怎样的微服务实战项目?
这次不敲代码,而是画出蓝图。俗话说的好君子谋定而后动
要聊的是这个 优惠券平台项目的整体功能和模块
宏观的角度来了解一下我们整个项目的概貌和大致的走向
优惠券平台项目介绍
相信你一定参与过双 11 或者 618 之类的电商大促活动,体验过各种眼花缭乱的优惠券和
营销规则计算。而我们的实战项目,就是要搭建一个简化版的营销优惠计算系统,实现优
惠券模板的创建、用户领取优惠券、下单核销优惠券和订单价格试计算等功能。
如果我要实现一个“领取优惠券”的功能,那么我首先是要创建一个营销规则模板。这个模板就像是一个模具一样,每张优惠券都通过这个模具来铸造,并最终发放到用户手中
使用模板的好处是可以对优惠券消费规则做一层抽象,比如满减类、打折类这些优惠券只
是具体的优惠金额不同,但是玩法类似,我们把相类似的玩法功能抽象成一个模板,就可
以简化具体优惠券的创建和核销流程
在这个实战项目中,把整个项目划分为了优惠券模板服务、
计算服务、用户服务和平台类组件这四大模块。它们的功能是这样的:
优惠券模板服务:模板规则是创建具体优惠券的前置条件,每种类型的模板都是一个计
算公式,这个公式约定了优惠计算的方式。在这个项目中,模板服务实现了模板规则的
创建、克隆、分页查找等功能。另外,我将在项目里定义满减、随机立减、满折、晚间
双倍优惠等多种券模板类型。
优惠计算服务:这个模块是根据用户购物车中的商品信息(单价、数量、所属门店)和
优惠券信息,来计算当前订单优惠后的价格。另外,如果用户有多张优惠券,我还提供
了“优惠金额试算”服务,帮助用户挑选最省钱的优惠券。
用户服务:这是暴露给外部用户使用的接口,它依赖于模板服务和优惠计算服务完成底
层逻辑,主要业务场景是用户领券、订单价格试算、下单核销和订单金额试算等功能。
平台类组件:主要包括一些业务无关的中心化组件,比如 Gateway 网关等等,你将在
Spring Cloud 课程中逐渐接触到平台类组件的搭建。
从整体来看,优惠券模板服务和优惠计算服务是基础服务,用户服务是对用户开放的接
口,它依赖于这两个基础服务来完成业务逻辑。而平台类组件则提供了横向的微服务特性
支持,比如微服务网关、链路追踪功能等等,你可以把它们理解为“微服务中间件”。我
们通过下面这幅图来看一下这四个模块之间的关联关系:
为了帮你顺利过渡到 Spring Cloud 实战,我会先用 Spring
Boot 搭建出这个优惠券平台的单体应用,然后在这个基础上做 Spring Cloud 改造。
Spring Boot 实战项目规划(过渡)单体项目
在搭建项目的过程中,重点掌握以下这三个技术点:
1项目搭建:分层构建项目结构,并借助 Maven 实现依赖项管理;1.
2数据操作:我会带你快速入门 spring-data-jpa 实战,分别通过接口声明、自定义 SQL
和 JpaRepository 三种方式实现数据库 CRUD 操作;
3开放对外 API:快速入门 spring-web 实战,通过注解对外暴露 RESTful 风格的 API。
此外,以后的文章会不断跟你分享一些我平时工作中积累的小技巧,比如防御型编程、如何借助
插件自动生成代码和数据校验、JPA 级联关系的误区、计算密集型服务的特点、模板设计
模式的应用等等
在 Spring Boot 阶段我们搭建好优惠券平台的单体应用后,接下来就可以进行 Spring
Cloud 微服务化改造了
Spring Cloud 实战项目全景规划
这张图点乱,我们后期学了再来看
下面我们来看下每个阶段主要做些什么以及对应的技术选型。
第一阶段
我们主要实现微服务之间的通信,将用户微服务、优惠券模板服务和订单优
惠计算服务拆分为独立部署的业务系统,通过注册中心来实现服务注册和服务发现,让各
个微服务之间可以互相调用。这个阶段涉及的关键技术是 Nacos 注册中心、
Loadbalancer 客户端负载均衡组件和 OpenFeign 服务间调用组件。
Nacos我专门写了一篇文章记录,(跟小破马学的(这是爱称,我觉的讲的不赖))
我们知道微服务之间的服务通信有一个前提条件,就是你要知道将要调用的服务器地址是什么。这个寻址的任务是交由 Nacos 注册中心和 Loadbalancer 负载均衡器共同来完成
的
Nacos 是 Alibaba 出品的服务治理组件,它作为一个注册中心组件,负责收集所有服务节
点的地址信息并维护服务注册表,所有服务上线之后都会向它汇报状态。Loadbalancer 则
承担了负载均衡的任务,在客户端发起服务调用的时候,它会负责从 Nacos 的注册表中挑
选一台目标服务器。而 OpenFeign 组件是一个“锦上添花”的组件,它能够简化基于
HTTP 的远程服务调用,让我们就像使用本地接口一样方便地发起远程服务调用
我也不太明白(调用远程服务是怎么想使用本地接口一样方便的 哈哈哈哈哈,喃真是学艺不精啊)
为什么我会选择 Nacos+Loadbalancer 作为选型方案呢?
Eureka + Ribbon 是一个使用最为广泛的组合 太low了 写优雅的牛逼的项目就得用牛逼的技术
在第一阶段,我会分为三个部分来搭建起微服务之间的通信:
1服务治理:服务治理的重点是搭建基础的跨服务调用功能。我会把用户服务、优惠计算
服务和订单服务改造成可以独立启动的微服务,并借助 Nacos 的服务发现功能,通过
Webflux 组件中的 WebClient 实现基于 HTTP 的跨服务间的调用;
2负载均衡:在这部分,我们将在服务治理的基础上,引入 Loadbalancer 组件为跨服务
调用添加负载均衡的能力。除此之外,我会对 Loadbalancer 组件的扩展接口做自定义
开发,实现一个金丝雀测试的负载均衡场景;
3简化服务调用:我将使用 OpenFeign 组件对用户服务进行改造,将原先复杂的
WebClient 调用替换为简洁的 OpenFeign 调用
第二阶段
在第二阶段,我们的实战重点有三个:
利用服务容错提高微服务架构的可用性;
搭建全链路的分布式链路追踪能力;
实现统一的配置管理和动态属性推送
这个阶段涉及的技术组件是 Nacos Config、Sentinel、Sleuth+Zipkin+ELK。
在微服务架构中,服务容错是保障服务高可用的一个重要手段。在这个项目中,我们选择
用 Sentinel (翻译:“哨兵”)作为服务容错组件,它也是 Alibaba 贡献给 Spring Cloud 的。Sentinel 秉承了阿里系“大而全”的传统,只这一款组件就可以实现降级、熔断、流量整形等多种服务
容错途径
链路追踪也是微服务架构中一个很重要的功能,线上异常排查全靠它提供线索。我使用了
Spring Cloud 官方开源的 Sleuth 实现了日志打标功能,使用全局唯一标记将一次跨微服
务调用链上的各个环节全部串联起来
光打标还没用,我还结合了 Zipkin 组件实现调用链的可视化检索,将调用链上各个阶段的
请求按顺序显示在页面上,这样,我们就可以一目了然定位到线上异常发生在哪个环节。
另外,使用了目前业界主流的 ELK 组合(Elastic Search + Logstash + Kibana)作为
日志检索系统
配置项管理的技术选型方面,我使用了 Nacos Config 作为最终方案。借助 Nacos
Config 我们可以轻松实现配置项的远程获取和动态推送,在配置项的应用隔离和环境隔离
方面 Nacos 也是一把好手。Nacos 的搭建更
加容易且更易于上手,而且可以更好地支持“配置项”回滚的功能
第三阶段
三个重点
搭建微服务网关作为统一流量入口;
使用消息驱动组件对接 RabbitMQ;
通过分布式事务保证数据一致性
这个阶段涉及的技术组件是 Gateway、Stream 和 Seata
微服务网关是架设在外部网关(如 Ngnix)和内部微服务之间的一座桥梁,我选用 Spring
Cloud Gateway 作为网关组件。Gateway 不光担任了路由转发的重任,同时它提供了丰
富的谓词组合实现复杂的路由判断逻辑。除此以外,你还可以在网关层定义拦截器,对来
访请求执行一段特殊的业务逻辑。(在这里咋说呢 是不是就不需要aop了呢?不对的当只有单独的那么几个需要功能增强,我们就不用网关了,这时候还得用aop)
曾经微服务网关的头把交椅是 Netflix 贡献的 Zuul 组件,但 Zuul 2.0 的开源发布一拖再
拖,且性能并未达到预期效果。Spring Cloud 官方迫不得已,还没等到 Zuul 2.0 发布,
就自己发布了一款开源网关组件 Spring Cloud Gateway。基于这些原因,Gateway 当之
无愧成为了网关层的不二选择
消息队列和消息驱动是老牌技术了,它并不是微服务特有的功能。了解 Spring Cloud 开源的消息驱动组件“Stream”,它可以大幅降低应用系统和消息组件之间的对接流程。二是消息组件
在如今有非常丰富的使用场景,我希望将“消息组件的应用场景”作为一个知识拓展点,
帮助你开阔眼界
分布式事务是微服务环境下保证事务一致性的终极手段。在课程中我将主要介绍两种比较
有代表性的 Seata 分布式事务解决方案,一种是没有代码侵入的 Seata AT 方案,另一种
是蚂蚁金服贡献的资源锁定 + 补偿型的 Seata TCC 方案
总结
在整个项目中,我们先通过 Spring Boot 快速落地了优惠券平台的三个业务模块,然后,
在 Spring Cloud 实战阶段,我们分为三个阶段对 Spring Boot 项目进行微服务化改造:
第一个阶段使用 Nacos、Loadbalancer 和 OpenFeign 实现了跨服务的调用;
第二阶段使用 Sentinel、Nacos Config 和 Sleuth 实现了服务容错、配置管理和分布式
链路追踪;
第三阶段使用 Gateway、Stream 和 Seata 实现了微服务网关、消息事件驱动和分布式
事务