微服务
微服务是一种架构模式,它提倡将单一应用程序划分成一组小的服务。 每个服务运行在其独立的进程中,服务之间通过轻量级通信进行通信。
单个轻量级服务一般为一个单独微服务,微服务讲究的是专注某个功能的实现, 比如登录系统只专注于用户登录方面功能的实现,讲究的是职责单一,开箱即用,可以独立运行。 微服务架构系统是一个分布式的系统,按照业务进行划分服务单元模块,解决单个系统的不足,满足越来越复杂的业务需求。
就目前而言,对于微服务业界并没有一个统一的、标准的定义。
但通常而言,微服务架构是一种架构模式或者说是架构风格,它提倡将单一应用程序划分成一组小的服务。
每个服务运行在其独立的自己的进程中服务之间相互配合、相互协调,为用户提供最终价值。
服务之间采用轻量级通信。
每个服务都围绕具体业务进行构建,并能够独立部署到生产环境等。另外应尽量避免统一的、集中的服务管理机制。
简单来讲:
微服务就是一个独立的职责单一的服务应用程序。在intellij idea
工具里面就是用maven
开发的一个个独立的module
,
具体就是使用springboot
开发的一个小的模块,处理单一专业的业务逻辑,一个模块只做一个事情。
微服务强调的是服务大小,关注的是某一个点,具体解决某一个问题、落地对应的一个服务应用,可以看
做是idea
里面一个module
,一个功能就是一个服务。
例如:一个公司有很多部门,但是每个部门负责的职责都是单一的, 比如:财务部门、人事部门、开发部门,都有对应的工作内容,这每个部门就是一个独立的微服务。
分布式
微服务都大体认知了,也同时认知下分布式,因为目前的微服务架构,基本都要满足分布式需求。
在《分布式系统原理与范型》一书中有如下定义:
分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统
分布式系统是指将一个大型系统分解成多个独立的子系统,并将这些子系统分布在不同的计算机节点上, 由一组通过网络进行通信、为了完成共同的任务而协调工作的计算机节点组成的系统。
分布式系统的出现是为了用廉价的、普通的机器完成单个计算机无法完成的计算、存储任务。
其目的是利用更多的机器,处理更多的数据。
分布式系统(distributed system
)是建立在网络之上的软件系统。
分布式系统要解决的问题本身就是和单机系统一样的,而由于分布式系统多节点、通过网络通信的拓扑结构,会引入很多单机系统没有的问题, 为了解决这些问题又会引入更多的机制、协议,带来更多的问题。
分布式共识算法
分布式共识算法是在分布式系统中确保所有参与节点就单一数据值达成一致的算法。 这些算法对于构建可靠和容错的分布式系统至关重要,尤其是在那些需要在没有中央控制的情况下维护一致性状态的应用场景中,例如区块链技术和分布式数据库。
常见的分布式共识算法和特点:
- Paxos
- 分布式共识算法的基础。
- 提供了在异步网络环境中达成一致性的方法。
- 实现复杂,尤其是 Multi-Paxos,它解决了多个提案的问题。
- Raft
- 是为了解决 Paxos 难以理解的问题而设计的。
- 提供了更易于理解和实现的机制来实现一致性。
- 强调了领导者选举和日志复制。
- ZAB (Zookeeper Atomic Broadcast)
- 构成了 ZooKeeper 分布式协调服务的基石。
- 支持两种模式:崩溃恢复和正常操作。
- 在 ZooKeeper 中用于确保数据的一致性。
- Two-Phase Commit (2PC) 和 Three-Phase Commit (3PC)
- 主要用于事务处理系统中的分布式事务管理。
- 2PC 包括准备阶段和提交阶段;3PC 增加了一个预准备阶段以减少锁定资源的时间。
- 其他共识算法
- PBFT (Practical Byzantine Fault Tolerance): 这是一种实用的拜占庭容错算法。
- HotStuff: 一种基于 PBFT 的改进版本,通过引入新的优化机制提高了效率。
- Proof of Work (PoW), Proof of Stake (PoS), and other blockchain consensus mechanisms: 用于区块链技术中的共识。
每种算法都有其特定的优势和适用场景。 选择合适的共识算法取决于系统的具体需求,包括对延迟、吞吐量、容错性和安全性的要求。 例如,在区块链中,通常会使用 PoW 或 PoS 这样的算法来达成共识,而在传统的分布式数据库中,则可能采用 Raft 或 Paxos。
微服务架构
微服务架构就是对微服务进行管理整合应用的。
微服务架构依赖于微服务,是在微服务基础之上的。
例如:在公司里,每一个部门都是一个独立的微服务,那么公司是一个大型的微服务架构, 就类似董事长可以对下面的部门进行管理。微服务架构主要就是这种功能。
微服务的优缺点
- 优点
- 松耦合,聚焦单一业务功能,无关开发语言,团队规模降低。
- 小而精,开发中,不需要了解多有业务,只专注于当前功能,便利集中,功能小而精。
- 高容错,微服务一个功能受损,对其他功能影响并不是太大,可以快速定位问题。
- 高灵活,可以灵活搭配技术,独立性比较舒服。
- 缺点
- 高复杂,随着服务数量增加,管理复杂,部署复杂,服务器需要增多,服务通信和调用压力增大,运维工程师压力增大
- 运维成本高,需要运维工程师,运维成本高。
- 依赖增强,系统依赖增强,数据一致性,性能监控。
总结:变小变灵活了,数量也变多了,协同性和管理性同步增多。
微服务的技术栈
微服务组件 | 技术方案 |
---|---|
服务开发 | SpringBoot、Spring、SpringMVC |
服务注册与发现 | Nacos、Eurka、Consul、Zookeeper等 |
服务配置与管理 | Nacos、阿里的Dlamond、SpringCloudConfig、Apollo、Netfix公司的Archaius等 |
服务路由(API网关) | Gateway、Zuul、Apache APISIX等 |
服务调用 | Rest(OpenFeign)、RPC(Dubbo)、GRpc等 |
服务熔断器 | Sentinel、Hystrix、Resilience4j等 |
负载均衡 | Nginx、LoadBalancer、Ribbon等 |
消息队列 | RocketMQ、Kafka、RabbitMQ、ActiveMQ等 |
服务监控 | Prometheus、Zabbix、Nagios、Metrics、Spectator等 |
全链路追踪 | Zipkin,Brave,Dapper等 |
服务部署 | Docker,OpenStack,Kubernetes等 |
数据流操作开发包 | SpringCloud Stream(封装与Redis,Rabbit,kafka等发送接收消息) |
事件消息总线 | Nacos、Spring Cloud Bus |
目前主流的微服务开发整体框架方案主要分为2种,Spring Cloud
和Spring Cloud Alibaba
。
微服务组件 | Spring Cloud |
Spring Cloud Alibaba |
---|---|---|
注册与发现 | Eurka、Zookeeper | Nacos |
配置与管理 | SpringCloudConfig | Nacos |
API网关 | Gateway | Gateway |
服务调用 | OpenFeign | Dubbo、OpenFeign、GRpc |
熔断器 | Hystrix、Resilience4j | Sentinel |
事件消息总线 | Spring Cloud Bus | Nacos |
消息队列 | 随意搭配 | RocketMQ |
分布式事务 | TCC、Seata、等等 | Seata |
两大主流框架的一些区别,其他的基本都是按照各自使用搭配,并无太大区别。
目前使用多的还是Spring Cloud Alibaba
体系的。
服务注册与发现
服务注册
服务注册就是管理一个记名册,它管理系统内所有的服务地址。</br>
当新的服务启动后,它会向记名册记录自己的地址信息(此信息可以配置的,是由客户端控制告诉服务端的)。</br>
服务的依赖方直接向记名册要Service Provider
地址就行了。</br>
当下用于服务注册的有很多如:
Eureka
ZooKeeper
Nacos
- 等等
服务注册主要有两种形式:
- 客户端注册
- 第三方注册
客户端注册
客户端注册是服务自身要负责注册与注销的工作。当服务启动后向注册中心注册自身,当服务下线时注销自己。</br> 期间还需要和注册中心保持心跳。</br> 心跳不一定要客户端来做,也可以由注册中心负责(这个过程叫探活)。</br> 这种方式的缺点是注册工作与服务耦合在一起,不同语言都要实现一套注册逻辑。</br>
现在大部分的框架都是此类模式。
第三方注册(独立的服务Registrar
)
第三方注册由一个独立的服务Registrar
负责注册与注销。</br>
当服务启动后以某种方式通知Registrar
,然后Registrar
负责向注册中心发起注册工作。</br>
同时注册中心要维护与服务之间的心跳,当服务不可用时,向注册中心注销服务。</br>
这种方式的缺点是Registrar
必须是一个高可用的系统,否则注册工作没法进展。
服务发现
服务发现是指服务自身要负责发现可用服务地址。 根据当前项目使用的服务,查找到对应的服务地址,保证服务可以正常访问。
服务发现主要有两种形式:
- 客户端发现
- 服务端发现
客户端发现
客户端发现是指客户端负责查询可用服务地址,以及负载均衡的工作。这种方式最方便直接,而且也方便做负载均衡。</br> 再者一旦发现某个服务不可用立即换另外一个,非常直接。</br> 缺点也在于多语言时的重复工作,每个语言实现相同的逻辑。</br>
服务端发现
服务端发现需要额外的Router
(路由)服务,请求先打到Router
,然后Router
负责查询服务与负载均衡。</br>
这种方式虽然没有客户端发现的缺点,但是它的缺点是保证Router
的高可用。</br>
服务配置与管理
随着业务的发展、微服务架构的升级,服务的数量、程序的配置日益增多(各种微服务、各种服务器地址、各种参数)
会出现以下一些问题:
- 安全性:配置跟随源代码保存在代码库中,容易造成配置泄漏。
- 分散性:配置文件过于分散,难以管理。
- 回溯性:而且静态配置文件方式修改无法追溯,所以当配置进行修改之后,不容易形成记录,更无法追溯是谁修改的、修改时间是什么、修改前是什么内容。
- 时效性:修改配置,需要重启服务才能生效。
- 繁琐性:一项配置更改,需要人工修改每一个服务的配置文件。
- 局限性:无法支持动态调整:例如日志开关、功能开关;无法动态切换不同环境。
传统的配置方式已无法满足配置管理的要求,为了更加高效和快捷的获取配置, 因此,我们需要配置中心来统一管理配置,把业务开发者从复杂以及繁琐的配置中解脱出来, 只需专注于业务代码本身,从而能够显著提升开发以及运维效率。 同时将配置和发布包解藕也进一步提升发布的成功率,并为运维的细力度管控、应急处理等提供强有力的支持。
配置中心应该满足的特点
- 配置集中管理:解决传统的“配置文件过于分散”的问题。所有的配置都集中在配置中心这一个地方管理,不需要每一个项目都自带一个,这样极大的减轻了开发成本。
- 统一标准
- 配置与应用分离:解决传统的
配置文件无法区分环境
的问题,配置并不跟着环境走,当不同环境有不同需求的时候,就到配置中心获取即可,极大的减轻了运维部署成本。 - 实时更新:解决传统的“静态化配置”的问题。线上系统需要调整参数的时候,只需要在配置中心动态修改即可。
- 高性能、高可用性、高并发、分布式
- 可以基于不同环境配置,做到隔离(开发、测试、预发布、灰度/线上);
变更推送如何实现
配置信息存储之后,我们需要考虑如何将配置的变更推送给服务端,这样就可以实现配置的动态变更
,不需要重启服务器就能让配置生效了。
而一般会有两种思路来实现变更推送:一种是轮询查询
的方式;一种是长连推送
的方式。
轮询查询很简单,就是应用程序向配置中心客户端注册一个监听器,配置中心的客户端,定期地(比如1
分钟)查询所需要的配置是否有变化,如果有变化则通知触发监听器,让应用程序得到变更通知。
这里有一个需要注意的点,如果有很多应用服务器都去轮询拉取配置,由于返回的配置项可能会很大,那么配置中心服务的带宽就会成为瓶颈。
为了解决这个问题,会给配置中心的每一个配置项,多存储一个根据配置项计算出来的MD5
值。
配置项一旦变化,这个MD5
值也会随之改变。
配置中心客户端在获取到配置的同时,也会获取到配置的MD5
值,并且存储起来。
那么在轮询查询的时候,需要先确认存储的MD5
值,和配置中心的MD5
是不是一致的。
如果不一致,这就说明配置中心中,存储的配置项有变化,然后才会从配置中心拉取最新的配置。
由于配置中心里存储的配置项变化的几率不大,所以使用这种方式后,每次轮询请求就只是返回一个MD5
值,可以大大地减少配置中心服务器的带宽。
另一种长连推送,则是在配置中心服务端保存每个连接关注的配置项列表。 这样,当配置中心感知到配置变化后,就可以通过这个连接,把变更的配置推送给客户端。 这种方式需要保持长连,也需要保存连接和配置的对应关系,实现上要比轮询的方式复杂一些,但是相比轮询方式来说,能够更加实时地获取配置变更的消息。
服务调用
在微服务架构中,需要调用很多服务才能完成一项功能。服务之间如何互相调用就变成微服务架构中的一个关键问题。
服务调用一般有两种方式,一种是HTTP
方式,另一种是RPC
方式。
HTTP
(Hypertext Transfer Protocol)是一种应用层协议,主要强调的是网络通信;RPC
(Remote Procedure Call,远程过程调用)是一种用于分布式系统之间通信的协议,强调的是服务之间的远程调用。 一些RPC
框架比如gRPC
,底层传输协议其实也是用的HTTP2
,包括Dubbo3
,也兼容了gRPC
,使用了HTTP2
作为传输层的一层协议。
目前主流的OpenFeign
就是HTTP
方式,Dubbo
是RPC
方式。
API网关
API
网关是系统对外的访问入口。例如常见的Nginx
就是API
网关,它更多是服务器对外的网关。
微服务中的API
网关,功能更多的是:
- 动态路由
- API管理
- 服务治理
- 身份认证
- 安全管理
- 监控
- 等等基于服务更细微的管控。
负载均衡
在微服务架构中,负载均衡(Load Balancing)是一个关键组件,它负责将客户端的请求均匀地分布到多个服务实例上, 从而优化资源使用、提高系统吞吐量、增强容错能力和可伸缩性。
负载均衡的几个核心功能和概念:
- 请求分发
- 将来自客户端的请求分发到多个后端服务实例上,确保没有单一服务过载。
- 高可用性
- 当某个服务实例不可用时,负载均衡器能够检测并重新路由请求到其他健康的服务实例,提供故障转移。
- 可伸缩性
- 随着需求的增长,可以增加更多的服务实例,负载均衡器自动调整流量分配,支持水平扩展。
- 性能优化
- 通过算法选择最优的服务实例处理请求,如基于响应时间、权重等策略。
- 监控与健康检查
- 负载均衡器通常具备监控服务实例健康状态的能力,并根据健康检查结果动态调整流量分配。
- 智能路由
- 根据特定条件或策略进行智能路由,例如基于地理位置、用户类型或服务版本的路由。
- 负载均衡策略
- 不同的负载均衡策略可以应用于不同的场景,常见的有:
- 轮询(Round Robin):按顺序将请求分发给服务实例。
- 最少连接(Least Connections):将请求发送给当前连接数最少的实例。
- 随机(Random):随机选择服务实例。
- 加权轮询(Weighted Round Robin):根据服务实例的处理能力分配不同权重。
- 一致性哈希(Consistent Hashing):保持相同请求总是路由到同一实例,适用于缓存场景。
- 不同的负载均衡策略可以应用于不同的场景,常见的有:
- 实现方式
- Nginx
- Ribbon
- 等
在微服务架构中,负载均衡是确保服务高可用性和可扩展性的基石,它使得系统能够处理大量并发请求,同时保持稳定和高效
熔断器
在微服务架构中,熔断器(Circuit Breaker)是一种设计模式,用于提高系统的弹性和可靠性。
在微服务架构中通常会有多个服务层调用,基础服务的故障可能会导致级联故障,进而造成整个 系统不可用的情况,这种现象被称为服务雪崩效应。
服务雪崩效应是一种因服务提供者
的不可用导致服务消费者
的不可用,并将不可用逐渐放大的过程。
熔断器的原理很简单,它借鉴了电力系统中的熔断器概念,当电路过载时,熔断器会断开电路以防止进一步的损坏。
它可以实现快速失败,如果它在一段时间内侦测到许多类似的错误,会强迫其以后的多个调用快速失败,
不再访问远程服务器,从而防止应用程序不断地尝试执行可能会失败的操作,
使得应用程序继续执行而不用等待修正错误,或者浪费CPU
时间去等到长时间的超时产生。
熔断器也可以使应用程序能够诊断错误是否已经修正,如果已经修正,应用程序会再次尝试调用操作。
主要功能
- 故障隔离
- 当一个服务频繁失败时,熔断器会打开,阻止对该服务的进一步调用,直到服务恢复。
- 降级处理
- 在熔断器打开的情况下,可以返回预定义的错误信息或者默认结果,而不是等待超时或抛出异常。
- 恢复机制
- 熔断器在一段时间后会尝试半开状态,允许少量请求通过,以检查服务是否已恢复。
- 重试机制
- 在服务恢复或初始故障后,熔断器可以配置重试机制,自动重试失败的调用。
实现原理
- 闭合状态:服务正常运行,所有请求被转发。
- 打开状态:服务调用失败达到阈值,熔断器打开,后续请求直接失败,不进行调用。
- 半开状态:经过一定时间后,熔断器进入半开状态,允许有限的请求通过,如果这些请求成功,则熔断器回到闭合状态。
技术实现
在微服务中,熔断器可以由多种框架和技术实现,如:
- Hystrix:Netflix开源的熔断器库,常用于Spring Cloud生态系统。
- Resilience4j:轻量级的Java库,提供熔断器、重试和限流等功能。
- Sentinel:阿里巴巴开源的流量控制组件,提供熔断、限流和降级功能。
- Envoy Proxy:服务网格中的代理,内置了熔断器和其他服务治理功能。
熔断器是微服务架构中不可或缺的一部分,它有助于构建健壮、可扩展和自我修复的系统。