【架构】评分较高的三本微服务书籍的阅读笔记
1. 前言
最近看了三本有关微服务的书:
- 《凤凰架构》
- 《微服务设计模式》
- 《微服务实战(第二版)》
同时回顾了一本通用知识的书:
- 《数据密集型应用系统设计》
从宏观上看,微服务都是重构出来的,所有作者都不建议一上来就把项目搭建成微服务。这种基于重构来搭建微服务的指导思想是:要明确知道微服务解决单体的缺点时,同时也引入了风险和挑战,当微服务的风险和挑战大于单体架构时请谨慎。当微服务的收益大于单体架构时,需要遵循一些设计原则甚至是必备的组件。除了比较抽象的原则外,作者都给出了具体的例子,其中国外的《微服务设计模式》给出了个很完整的重构方案,其中“服务的拆分策略”尤为经典,并且受到《凤凰架构》的认同。但是使用的技术都是国外且是最新的,对工程师有较高的要求;《凤凰架构》则是结合国内流行的技术,以架构师的视角对分布式技术娓娓道来,其中很多流程图很接地气;《微服务实战(第二版)》顾名思义,是一本实战书,开箱即用的代码(基于Docker)十分直观的介绍了微服务中流行技术的应用层代码实现,包括之前从未听过但是功能很强的Resilience4j
。
2. 合并目录
三本书讲的东西是有交集的,现在做一个目录合并,旨在突出:
- 重复即重要的知识点
- 对同一事物不同角度论述的知识点
- 可以交叉验证的知识点
2.1 目录全景
具体目录的顺序分别对应如下
- 凤凰架构
- 微服务设计模式
- 微服务实战
合并后的目录 | 具体目录 |
---|---|
服务架构介绍 | |
服务架构的演进 | |
逃离单体地狱 | |
欢迎迈入云世界,Spring / 使用 Spring Cloud 探索微服务世界 | |
服务拆分 | |
向微服务迈进 | |
服务的拆分策略 / 微服务架构中的业务逻辑设计 / 微服务架构的重构策略 | |
使用 Spring Boot 构建微服务 | |
服务间通信 | |
远程访问服务 | |
微服务架构中的进程间通信 | |
- | |
事务 | |
事务处理 | |
使用 Saga 管理事务 | |
- | |
事件驱动 | |
- | |
使用事件溯源开发业务逻辑 | |
使用 Spring Cloud Stream 的事件驱动架构 | |
安全 | |
架构安全性 / 可靠通信 | |
开发面向生产环境的微服务应用 | |
保护微服务 | |
共识算法 | |
分布式共识 | |
- | |
- | |
服务发现 | |
从类库到服务-服务发现 | |
- | |
关于服务发现 | |
网关 | |
从类库到服务-网关路由 | |
外部API模式 | |
使用 Spring Cloud Gateway 进行服务路由 | |
外部化配置 | |
服务网格 | |
开发面向生产环境的微服务应用 | |
使用 Spring Cloud Config 服务端控制配置 | |
高可用 | |
从类库到服务-客户端负载均衡 / 流量治理 | |
开发面向生产环境的微服务应用 | |
当糟糕的事情发生时:使用 Spring Cloud 和 Resilience4j 弹性模式 | |
查询优化 | |
透明多级分流系统 | |
在微服务中实现查询 | |
- | |
服务监控 | |
可观测性 | |
开发面向生产环境的微服务应用 | |
使用 Spring Cloud Sleuth 和 Zipkin 进行分布式追踪 / 监控微服务 | |
测试 | |
- | |
微服务中的测试策略 | |
- | |
容器与运维 | |
虚拟化容器 / 资源与调度 | |
部署微服务应用 | |
欢迎来到 Docker | |
部署 | |
服务网格 / 部署 Kubernetes 集群 | |
部署微服务应用 | |
部署微服务 |
2.2.《数据密集型应用系统设计》进行补充
合并后的目录 | 具体目录 |
---|---|
服务架构介绍 | |
服务架构的演进 | |
逃离单体地狱 | |
欢迎迈入云世界,Spring / 使用 Spring Cloud 探索微服务世界 | |
分布式系统的挑战 | |
事务 | |
事务处理 | |
使用 Saga 管理事务 | |
- | |
事务 | |
共识算法 | |
分布式共识 | |
- | |
- | |
一致性与共识 | |
查询优化 | |
透明多级分流系统 | |
在微服务中实现查询 | |
- | |
数据模型与查询语句 |
3. 提炼骨架
3.1. 什么场景下需要使用微服务
单体架构发展到一定程度后,无法支持对市场机会作出快速反应时,需要重构成微服务。快速反应指:
- 尽量缩短开发周期
- 系统失效或者维护时间越长,损失越大,甚至大到无法承受。
3.2 微服务解决了什么问题
《微服务设计模式》提到了两种拓展模式
- N个相同实例的扩展
EG: 同一个应用,创建同样的N个实例,请求进来后可以根据N个实例负载均衡。 - N个相同实例,但是每个实例只处理一部分用户。
EG: 同一个应用,创建同样的N个实例,请求先经过路由器,判断是来自于哪个用户,路由到处理该用户的实例上。
以上两种拓展模式很好的提升了应用的吞吐量和可用性,然而这两种方法都没有解决日益增长的开发问题和应用复杂性,而基于功能性分解,把应用拆分成服务,以服务为粒度拓展即可解决这个问题。
3.2. 微服务引入了什么问题
- 决策者需要考虑什么情况需要使用微服务
- 服务的拆分和定义是一项挑战
- 分布式系统本身的复杂度
3.1. 维护服务之间的数据一致性 —— 分布式事务
3.2. 引入显著的运维复杂性 - 当部署多个服务是,需要更谨慎得协调开发团队
3.3. 微服务需要的技术栈
这一部分注意是在 《微服务实战(第二版)》中整理
-
服务发现
Eureka
Consul
Nacos
-
服务间通信
2.1. 负载均衡
选用Eureka
作为注册中心后,可以将集群注册到Eureka
,集群用起来后就伴随着负载均衡技术的引入,Netflix Ribbon
是一个稳定的负载均衡解决方案,但是Spring Cloud Loadbalancer
活跃度比较高,所以选用这个实现。那么就需要在配置文件中禁用掉Netflix
的实现:spring: loadbalancer: ribbon: enabled: false
2.2. 集成了负载均衡的客户端
将服务注册到注册中心后,每个服务都能拿到注册信息,可以使用注册信息访问对方。基于Eureka
的服务间通信可以使用三种客户端进行通信:Spring Discovery Client
启用了 Discovery Client 的Rest 客户端
Netflix Feign 客户端选用
Netflix Feign
,主要是使用方式比较简洁。 -
外部化配置
Spring Cloud Config
-
网关
Spring Cloud Gateway
-
安全
Spring Security
Keycloak
jwt
-
事件驱动
Spring Cloud Stream
-
分布式链路追踪
Spring Cloud Sleuth
Zipkin
-
高可用组件
8.1. 负载均衡组件
已经提到过的开箱即用的Spring Cloud Loadbalancer
8.2. 断路器模式 (熔断器)
Resilience4j
使用@CircuitBreaker(name = "licenseService")
8.3. 后背模式 (服务降级)
Resilience4j
使用@CircuitBreaker(name = "licenseService", fallbackMethod = "buildFallbackLicenseList")
, 其中buildFallbackLicenseList
放入降级逻辑。8.4. 舱壁模式
# 信号量隔离 resilience4j.bulkhead: instance: bulkheadLicenseService: maxConcurrentCalls: 20 # 省略其他参数 # 线程池隔离 resilience4j.thread-pool-bulkhead: instance: bulkheadLicenseService: maxThreadPoolSize: 1 # 省略其他参数
Resilience4j
使用@Bulkhead(name = "licenseService", fallbackMethod = "buildFallbackLicenseList")
, 其中buildFallbackLicenseList
放入降级逻辑。值得注意的是:舱壁模式也支持服务降级8.5 重试模式
Resilience4j
使用@Retry(name = "licenseService", fallbackMethod = "buildFallbackLicenseList")
值得注意的是:重试模式也支持服务降级8.6 限流模式
Resilience4j
使用@RateLimiter(name = "licenseService", fallbackMethod = "buildFallbackLicenseList")
值得注意的是:限流模式也支持服务降级8.7 兼容ThreadLocal
使用Resilience4j
注解的方法,父线程的ThreadLocal可以被子线程继承。
4. 容易搞混的高可用组件的解释
组件(模式)名 | 作用 |
---|---|
客户端负载均衡 | 对一个集群中的多个实例进行轮询或者随机调用。 |
断路器模式 | 调用方的能力,当远程服务被调用时,调用方会监控这个调用的质量,如果时间太长或者失败次数过多,则进行快速失败。防止一个低效的远程调用拖垮整个应用。熔断器有自适应能力,意思是当远程调用的服务质量恢复时,熔断器则关闭。具体算法暂不提。 |
后备模式 | 可以跟其他模式组合用。后被模式也就常说的服务降级,“快速失败”是否还有优化空间呢?最简单的就是失败后返回200的响应,提示客户请求正在排队,请不要频繁请求。稍微复杂一定的降级:淘宝千人千面的商品推荐页,如果推荐系统出错,那么降级成千人一面的首页。 |
舱壁模式 | 将每个远程调用的线程资源隔离开,可以是每个调用都预设一个线程池(线程池隔离),可以是每个调用都进行信号量管理(信号量隔离)。这样做的好处是防止一个响应缓慢的远程调用侵占整个应用的资源。 |
重试模式 | 微服务是运行服务失败的,同时也该允许调用方重试,可以幂等性调用的接口用重试可以提升整体业务成功率。 |
限流模式 | 舱壁模式是控制某个调用的并发度,限流模式关注的是时间区间的总调用数。 |