SpringMicroservices实战第二版 - 精要介绍
TL;DR
- 单体架构中,所有的流程都是紧密耦合的,并作为一个整体部署和扩展。
- 微服务架构是 一个个极小的,负责特定业务功能, 自治的服务,通过轻量级的通信机制组合在一起。
- 单片式架构往往是简单、轻量级应用的理想选择。 而微服务架构通常更适合于开发复杂的、不断变化更新的应用程序。选择那种软件架构完全取决于你的项目规模、时间和要求,以及其他因素
- SpringBoot可以帮我们快速构建上述两种架构。(书中自然是主要关注后者)
- 具体来说,只要通过一些简单的注解,就可以快速创建一个 基于REST/JSON 的微服务节点。
- 虽然编写微服务的代码很简单,但要将这些微服务完全投入到生产中去需要更多的深谋远虑.
- 微服务有几个类别的开发模式(套路): 包括核心开发、路由、客户端弹性、安全、监控度量、构建/部署等。这些模型会在本博文中进行精简的介绍。之后会为每一个模型单独开一篇博文进行详细介绍。
微服务概念101
感觉这方面的概念其实没必要再多阐述了,这里就简单的提一下.
因为全球化等原因,网路应用开发的复杂性与要求越来越高,古早的单体架构无法满足需求,所以微服务架构应运而生. 微服务架构将原先单体架构中的功能模块进行了拆分,每个模块都是一个独立的服务。然后使用轻量级的通信机制( 形式上往往是调用REST服务)将这些服务组合在一起。 此后,每个服务都可以独立部署、扩展、升级、替换,而不会影响到其他服务(这是最重要的特性) 。同时由于不同组件通过轻量级的通信机制进行交互,所以每个模组自身实现可以使用不同的编程语言、不同的数据存储技术、不同的操作系统等等。 以及,在管理层面上,微服务使得使组织可以更好的分工协作与责任划分。
微服务绝不仅仅是写代码
理解微服务的概念与构建一个微服务组件是较为容易的。但是,要将微服务投入到生产环境中并保持其稳定性则是另一回事了。我们要额外考虑的因素包括:
- 大小合适: 如何确保服务拆分的粒度合适,使其不至于过于复杂的同时专注于一个职责领域。
- 服务位置问题: 大量微服务的地址如何管理,如何让客户端找到它们。
- 有弹性: 微服务出现问题时,如何快速失败,而不会影响到其他服务。
- 可伸缩: 如何设计让微服务能够以最小的服务间依赖进行快速伸缩
- 可重复: 当对微服务进行拓展时,如何确保每一个新拓展的微服务都是一致的。
上述问题便是(大部分) 微服务架构在提供单体架构所无法提供的灵活性的同时,所带来的新的挑战。这些挑战需要我们在设计微服务架构时进行考虑。
所幸 尽管纵观网络应用发展史中,微服务架构算是一个年轻的架构,但其仍有近十年的发展历史了。 其中,很多优秀的企业都在微服务架构的实践中积累了大量的经验,并将其解决方案开源出来。 这让我们在设计微服务架构时 可以直接选择一些当下的最佳实践,也在一些问题了有了很多可借鉴的经验。
Spring在其中的角色
在基于Java的应用程序构建中,Spring已经成为了事实上的标准开发框架。具体关于Spring的特性不展开太多。重点是,Spring提供了一个公开的生态, 在其子项目SpringCloud中封装了多个流行的云管理微服务框架,并且让这些技术的使用和部署像为代码添加注解一样简便。
简而言之,Spring(SpringCloud)极大地简化了微服务开发的复杂性。
Cloud Computing 云计算的概念
云计算即通过互联网提供可扩展的虚拟化计算资源(数据库、网络、算力),这些资源可以按需使用,而且可以快速地配置和释放。 通过云计算服务,开发者可以更加自由地控制自己所提供软件服务规模。
具体来说,在云计算出现之前,若想要对程序进行拓展,则需要直接购买更多的硬件资源,并且自己进行配置和管理。 而在云计算之后,开发者可以通过云计算服务商提供的服务,来按需购买所需的计算资源。 云计算提供的服务往往以 XaaS (anything as a service) 的形式为开发者们所谈论, 其中 X 代表了不同的服务类型。 根据服务商提供的服务类型不同,可以分为以下几类:
- Infrastructure as a Service (IaaS)
- Container as a Service (CaaS)
- Platform as a Service (PaaS)
- Function as a Service (FaaS)
- Software as a Service (SaaS)
对于这些术语的解释在细节上可能会有一些争议,但是在大致区分上可以参考一下这张图来理解:
一个 自己做饭-买半成品-点外卖-去饭店 的例子很流行,其很好地类比了不同云计算服务的区别在于提供的服务的深度.所以这里不啰嗦了。
这里多展开一下FaaS, 排除SaaS来看(因为其不在我们开发者的谈论的范围内,其一般指的是订阅制的软件服务模式,例如不直接买整个软件,而是 提供不断迭代更新的软件服务) ,FaaS是最上层的服务类型,也就是说其提供的服务最为深度. 其是一种新兴的服务类型,也被称为Serverless Computing。 这里的Serverless并非指的是没有服务器,而是指的开发者不需要关心服务器,而只需要关心自己代码,将剩下的全部交给云计算服务商来处理。 换言之,在开发者视角看来,其没有接触Server的概念,而是直接面向服务商提供的接口来开发自己的应用程序。
之所以FaaS变得流行起来,是因为其可以让前端开发者以一个与 系统学习后端/后端开发者学习前端 相比难度低非常多的方式 来直接开发部署完整的全栈应用程序. 当然,这只是最典型的一个例子。其实换个角度看FaaS还可以是一个在线的集成编程环境,让我们可以直接在浏览器中编写代码,而不需要安装任何开发工具。( 例如一些在线运行jupyter notebook的网站)
FaaS的理念很好,但有得也有失。(抛开 理所应当得比其他XaaS服务更高的价格) FaaS在带来便利的同时也一定程度上限制了开发者的自由度。就像Apple的生态很出色,但是一旦你进入了Apple的生态,就很难再出来了。 FaaS也是这样,首先程序自然无法脱离FaaS运行,同时开发者很难将自己的程序一个服务商迁移到另一个服务商,因为其往往会使用一些特定的API,而这些API往往是不同服务商之间不兼容的。
这里仅做一个补充,书中并没有具体深入FaaS,其主要聚焦于CaaS.
以下仅为书中内容的精要介绍,其具体信息会在单独的博文中展开。
本书精要 - 微服务节点本身的核心开发模式
对于一个微服务节点的设计实现来说,其主要考虑以下几个方面
- 服务粒度: 一个微服务节点应该提供什么样的服务来满足 微服务划分的原则
- 接口设计: 一个微服务要暴露哪些接口,以及这些接口的设计
- 通信协议: 如何与其他微服务节点进行通信(或接受其他微服务节点的通信),同步的一般采用基于HTTP的REST接口,异步的一般采用消息队列
- 配置管理: 如何管理微服务节点的配置,以及可以运行在不同云环境下
- 在整个架构中的事件驱动设计: 如何利用事件驱动设计来让 微服务节点之间的硬编码耦合降低到最低
本书精要 - 微服务的路由模式
其需要解决的问题就是: 当客户端需要消费服务时,如何发现一个可用的微服务节点并路由到该节点上进行通信。 难点在于,微服务节点的数量往往是巨大且动态变化的,并且可能还在处在完全不同的云环境下. 同时,还需要考虑到安全与负载均衡的问题。
解决方案需要用到服务路由与发现技术( 两者虽然往往是一起使用的,但其是互相独立的,且可以单独使用,不过这自然会使得开发难度上升)。
- 服务发现:通过服务发现组件,微服务节点可以将自己的信息注册到服务发现组件中,从而使客户端无需硬编码就可以发现可用的微服务节点。 (需要注意的是,服务发现组件是面向微服务内部的组件,而非直接面向客户端的)
- 服务路由:即通常为API网关,在维护信息安全后,将一个单入口的请求映射到多个微服务节点上(选一个),从而实现负载均衡。 (服务路由的网关自然是直接面向客户端的)
本书精要 - Resiliency
Resiliency(弹性) 即系统在面对故障、异常或负载增加时能够保持稳定性和可用性的能力。它强调系统能够适应和恢复自身,以确保核心功能的正常运行. 由于微服务架构是高度分布式的,所以需要额外留意的是,如何保证系统的可靠性。即防止一个微服务节点的故障导致整个系统的故障( 阻塞)。
为做到这一点,以下是一些常用的开发模式
- 客户端负载均衡: 通过客户端负载均衡,可以将请求分发到多个微服务节点上,从而实现负载均衡。
- 服务熔断: 通过服务熔断,可以在某个微服务节点出现故障(或没能力处理请求)时,快速失败,从而避免故障扩散到整个系统(形成阻塞)。
- Fallback 机制: 通过Fallback机制,可以在某个微服务节点出现故障时,执行备用逻辑,从而保证系统的可用性。
- Bulkhead(隔板)机制 : 通过这种模式,来让不同的微服务节点使用不同的资源池,使得当一个微服务节点出现故障时,不会影响到其他微服务节点的正常运行。
本书精要 - 微服务的安全
为了确保微服务架构不向外部暴露,同时保证微服务节点之间的安全通信,需要考虑以下几个方面
- 鉴别: 如何确定请求是他们所声称的那个用户发出的
- 鉴权: 用户的身份是否可以访问该资源或执行该操作
- 凭证管理与传播: 如何管理用户凭证,并尽力减少其在网络中的传输。 一般来说,Oauth2规范 + JWT(JSON Web Token)是一个不错的选择。
本书精要 - 微服务的日志与链路追踪
微服务所带来的新问题是,现在的日志已经不再是单一的了,而是分散在多个微服务节点上的。因此,需要考虑如何将这些分散的日志收集起来,以便于分析与监控。 一个常用的解决模式如下
- 日志关联: 将多个节点中的日志,通过一个唯一的ID进行关联,这样就可以将离散的日志 关联到一个 用户请求的处理过程中。
- 日志聚合: 将多个微服务节点中的日志集中到一起(一个数据源中),从而方便进行查询与分析。
- 链路追踪: 对用户请求的处理过程(经由多个微服务节点的链路)进行可视化地展示与追踪,从而方便进行故障排查与性能优化。
本书精要 - 微服务的度量指标
度量指标是衡量系统性能的重要指标,这些指标可以用于系统的监控,并对应用程序中可能出现的故障进行预警。
- 度量指标: 如何判断一个系统的健康程度,并对这些信息进行暴露
- 度量指标服务: 请求与保存度量指标的服务
- 度量指标的收集与展示: 将程序与 基础设施 相关的度量指标进行收集与展示
本书精要 - 微服务的构建与部署
微服务的每个实例应该与所有其他实例相同。你不能允许配置漂移(服务器在部署后发生了一些变化),因为这可能导致在你的应用程序中引入不稳定性。
该模式的目标是整合基础设置的配置到 构建/部署 的环节中。 即不将应用程序打包后再放到一个已经准备好的设施中,而是将基础设置的配置流程也加入到构建/部署的流程中。 最终当进行构建/部署时,会得到一个完整的、可运行的应用程序+基础设施的组合。
一个符合上述思路build/deployment pipeline需要考虑的内容如下:
- pipeline本身如何做到可重复构建 与一键式部署到任意环境中
- 如何将基础设施的配置 当做代码一样也纳入到pipeline中
- 当构建好之后,如何确保镜像是不可变的(不再会改变)
- Phoenix servers: 如何让运行单个容器的服务器定期被拆毁,并从一个不可变的镜像中重新创建。因为一个服务器运行的时间越长,就越容易出现配置漂移。( 可能会有人在服务器上做了一些手动的配置,从而导致服务器的配置与其他服务器不一致)
宗旨就是,在配置漂移影响到上层环境之前,尽快就将其拆除并重新创建。