微服务与分布式简介
- 分布式系统是建立在web之上的 软件系统
- 分布式的目的是解决普通的,单一的计算机无法独自处理一个任务
- 单一应用架构,即一个后端服务承载全部功能,这种模式orm是关键,主要是orm占用资源最多
- 协同开发问题(多个功能模块互相影响,一次部署打包需要所有功能都没问题才行,不利于升级维护,不利于扩展。一个功能出问题影响所有功能)
- 垂直应用架构:单一应用不足以承载越来越大的访问量,将后端服务进行拆分为更多的服务,通过一个统一的入口进行转发(如nginx),以提高效率。此时虽然多服务但是仍旧为一个物理机,这种mvc是关键,nginx也可以看成是mvc架构的一个部分
- 公用模块无法重复利用,开发性的浪费
- 分布式应用架构:垂直应用越来越多,每次增加服务模块都要重复性的写一些公用性的代码。此时应该将不同服务的公用代码提取出来 这种架构里提高业务复用及整合的分布式服务框架(RPC)是关键。
- 还有种流动计算架构:
RPC HTTP RMI
- rpc即远程调用,是一种进程间的通信,同一个服务里通常是线程间的调用。他是一种技术的思想,而不是规范。它允许程序直接调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数(不是一个内存地址通常不允许进行调用,现在通过网络来让服务自己调用自己,将结果传给另外一个服务,就相当于远程调用了),而不用程序员显式编码这个远程调用的细节。即程序员无论是调用本地的还是远程的函数,本质上编写的调用代码基本相同。
- http可以看成rpc的一种实现。他们底层都是
Socket
- http可以看成rpc的一种实现。他们底层都是
- http即超文本传输协议。与rpc一样跨语言,但是http协议数据量比rpc大得多(请求体里有很多各种头,cookie等) 而rpc更加简单高效
- rpc一般用于内部请求(指的不是一个计算机内部,指的是公司内部),而对外接口一般是http
RMI:可以看成是只用于java之间的rpc。而rpc是跨语言的(但是要求互相之间是同一种rpc框架)
CAP理论
这个定理的内容是指的是在一个分布式系统中、Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。
- 一致性(C):在分布式系统中,如果服务器集群,每个节点在同时刻访问必须要保持数据的一致性。
- 这里的一致性是指强一致性。一般关系型数据库就具有强一致性特性。
- 可用性(A):服务一直可用
- 分区容错性(P):某个节点出错后仍旧对外提供一致性和可用性服务
- 这是最基本的要求,我们在剩下2个中做取舍
- 一致性(C):在分布式系统中,如果服务器集群,每个节点在同时刻访问必须要保持数据的一致性。
- 三个不能都得,三选二得情况下一般都是
CPAP进行组合(为什么没有ca不清楚)- CP情况下:虽然我们服务可用性不高(可能一个挂了影响其他),但是必须要保证数据强一致性,如金融等业务这种偏多
- AP情况下:可以短暂数据不一致,但是最终可以一致性,不管怎么样,要能够保证我们的服务可用
- 一般除非要保证强一致性时使用CP,绝大多数情况我们都可以使用AP即可
Zookeeper是CP型得Eureka是AP型的,Nacos是AP与CP可以切换使用某个,默认是APBASE理论
BASE 是 Basically Available( 基本可用 )、Soft State( 软状态 )和 Eventually Consistency ( 最终一致性 )
- BASE 理论是对 CAP 中的一致性及可用性进行权衡的结果,其核心思想是:无法做到强一致性,那么可以通过牺牲强一致性来获得可靠性。
- 基本可用:在分布式系统出现不可预知故障时,允许损失部分可用性(如服务降级)
- 软状态:允许系统在多个不同节点的数据副本上存在数据延时。
- 通过牺牲强一致性来获得可用性,并允许一定时间内的不一致,但最终达到一致。
我们可以借助消息队列实现分布式最终一致性事务链接
微服务的组成简介
服务提供者(Provider):暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务。
- 服务消费者(Consumer):调用远程服务的服务消费方,服务消费者在启动时,向注册中心订阅自己所需的服务,服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
- 注册中心(Registry):注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者
监控中心(Monitor):服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
微服务组成之间的调用关系
l 服务容器负责启动,加载,运行服务提供者。
- l 服务提供者在启动时,向注册中心注册自己提供的服务。
- l 服务消费者在启动时,向注册中心订阅自己所需的服务。
- l 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
- l 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
l 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
Spring Cloud简介
早期的 Spring Cloud 五大组件包括:
Eureka、Ribbon、Hystrix、Zuul、Config。- Spring Cloud 基于 Spring Boot 框架,它不重复造轮子,而是将第三方实现的微服务应用的一些模块集成进去。准确的说,Spring Cloud 是一个概念上容器,它包含了一整套组件。
服务之间通信本质还是
HTTP通信,而服务之间一般采用Rest风格的API进行远程调用注册中心
因为微服务各个模块可以动态扩展,所以固定的通信地址不可靠,因此需要一个中心化的组件各个微服务实例信息进行登记和管理,同时让各个微服务实例之间能够相互发现,从而互相调用。
注册中心主要负责如下功能,eureka是微服务注册中心思想的实现:
Eureka 由两部分组成:
- 一个是 Eureka Server,提供服务注册和发现功能,即,我们上述的服务器端;
- 另一个是 Eureka Client,它简化了客户端与服务端之间的交互
Eureka Client 会定时将自己的注册信息登记到 Eureka Server 中,并从 Server 中下载包括了其它 Eurek Client 信息的注册表
Zookeeper
Zookeeper 是一个分布式协调服务。这样我们就可以利 用 Zookeeper 来协调多个分布式进程之间的活动。比如在一个分布式环境中,为了提高可靠 性,我们的集群的每台服务器上都部署着同样的服务。但是,一件事情如果集群中的每个服 务器都进行的话,那相互之间就要协调,编程起来将非常复杂。而如果我们只让一个服务进 行操作,那又存在单点。
- 通常还有一种做法就是使用分布式锁,在某个时刻只让一个服务去干活,当这台服务出问题的时候锁释放,立即 fail over 到另外的服务。
-
Nacos(A)
Nacos是Alibaba 开源的一个使用 Java 语言开发的服务发现、配置管理中心服务
- 早期eureka是springcloud实现注册中心的唯一选择。现在如
Nacos,Consul比eureka还强大。它们的区别在于:- Eureka 是一个 jar 包,它不能独立运行,而无论是 Consul 还是 Nacos 它们都是独立的产品,可以独立运行。
- Eureka 只能提供服务注册与发现功能,而无论是 Consul 还是 Nacos 它们都整合了配置中心性能的功能。
- 早期eureka是springcloud实现注册中心的唯一选择。现在如
-
负载均衡
负载均衡就算将用户访问请求,通过某种算法,尽可能平均的分发到集群中的节点。如
nginx也算是负载均衡的一个应用- 负载均衡一般在配置远程调用时会自动集成进去。所以没有意识到时,其实Ribbon已经在起作用了
-
Ribbon
-
Spring Cloud Loadbalancer
目前ribbon已经逐渐停止维护,新版本的cloud已经移除了对
ribbon的支持。Spring Cloud Loadbalancer是ribbon的官方推荐替代熔断器
不同服务通过网络互相访问会容易碰到
网络请求超时``微服务不可用等问题,一个服务有问题会引起依赖它的服务也出错。这就是**雪崩效应**- 针对上述错误有如下手段:
- 对于超时有超时重试机制,超时时超过一定时间后我们(主调方)就会断开连接(不再等待被调方的响应)。同时超时后会设置重试,重试一定次数才彻底关闭
- 对于微服务不可用有熔断器机制,如果请求出现异常,所有请求都会直接返回(不会再执行controller和service),而不会等待或阻塞,这样可以减少资源的浪费。(也称为快速失败)
- 熔断器还有一种半开的状态,当熔断器发现异常后会进入半开状态,此时它会『放行一个请求』来检测被调系统是否已经恢复,如果请求调用成功,则代表被调系统已经恢复正常,那么就会关掉熔断器,否则继续打开。
- 限流/流量限制:限流跟熔断类似,熔断是发生错误时自动触发直接返回。限流是主动强行直接返回。
- 限流和熔断并非只有直接拒绝请求的操作,还有服务降级,特权优先,延时处理等处理方式
快速失败的HTTP状态码为
429 too many requestHystrix
Hystrix 封装了微服务调用过程中的每一个依赖,使每个依赖彼此隔离,当延迟情况发生时,它会被限制在资源中,并包含回退(fallback)逻辑,该逻辑决定在依赖发生任何类型故障时应做出何种响应。
- Hystrix 的目标是阻止级联故障(级联故障就是一个错引起关联部分也错),对通过第三方客户端访问的依赖的延迟和故障进行保护和访问。Hystrix 实现这一目标的大致思路如下:
- 将外部依赖的访问请求封装在独立的线程中,进行资源隔离。
- 对于超出设定阈值的服务调用,直接进行超时处理,不允许其消耗过长时间而导致线程阻塞。
- 每个依赖服务维护一个独立的线程池,一旦线程池满了,直接拒绝服务调用。
- 统计依赖服务调用的成功次数、失败次数、拒绝次数、超时次数等结果。
- 在一段时间内,如果服务调用的异常次数超过一定的阈值,就会触发熔断器,停止对特定服务的所有请求。在一定时间内对服务降级,一段时间之后自动尝试恢复。
- 如果某个服务出现调用失败、被拒绝、超时等异常情况,就会自动调用 fallback 降级机制。
-
Resilience4j
Hystrix 官方已经停止开发了,所以 Spring Cloud 社区又推出了一款新的熔断器:Resilience4j 。
Resilience4j 是spring和netflix官方共同推荐的替代Hystrix的产品。不过市场占有率提升缓慢就是
Sentinel (A)
阿里的,相较于Hystrix添加了限流功能
- Sentinel的限流算法为滑动窗口算法
Sentinel以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
网关
API网关封装了系统内部架构,类似于外观模式,对客户端友好,屏蔽不同服务的复杂性和差异性
Zuul
Zuul 作为第一代网关,它相较于第二代网关 Gateway 而言,它最大的优势在于:它是基于 Servlet 的,因此学习曲线几乎为零。在并发量不高的情况下(仅在乎功能,而不在乎性能), Zuul 仍然是可选方案。
Spring Cloud Gateway
Gateway(网关) 是 Java 微服务体系中的第二代服务网关,是Zuul的替代品。Gateway基于
Springboot2.0Gateway 旨在提供一种简单而有效的途径来转发请求,并为它们提供横切关注点。主要功能如下
- 路由Route:路由就是一套『转发』规则。路由是网关最基础的部分,路由信息由一个 ID 、一个目的 URL 、一组断言工厂和一组 Filter 组成。如果路由断言为真,则说明请求的 URL 和配置的路由匹配。
- 断言 Predicate:通过断言函数和请求信息可以自由的定义转发规则。路由的转发规则都是断言定义
- Path 断言不会改变请求的 URI ,即,Gateway 收到的 URI 是什么样的,那么它将请求转给目标服务的时候,URI 仍然是什么。整个过程中只有 IP、端口部分会被『替换』掉 。
- 过滤器 Filter:Spring Cloud Gateway 中的 Filter 分为两种类型:Gateway Filter 和 Global Filter 。过滤器 Filter 将会对请求和响应进行修改处理,ru修改url
配置中心
一个服务可能存在多个实例(即多个部署),如果服务需要修改配置,那么每个实例都要修改,不方便。因此需要一个中心的配置中心。
- 个人理解就是配置中心就是统一进行配置,并把配置存到数据库里
现在的趋势是将配置中心的功能和注册中心的功能合二为一,如
nacos和Consul都提供了配置中心的功能。因此spring Cloud Config用的比较少Spring Cloud Config
消息总线
方便服务被动接收其他服务的消息。如服务a往总线上发消息,订阅了消息总线的b也能收到消息。可以使用消息队列或者第三方消息总线实现作消息总线
分布式事务
-
Spring Cloud Alibaba
springCloud的大部分常用组件都是
netflix开发的,netflix可以看成是springcloud的一个子框架。而alibaba依照springcloud的思想提供了一套对应netflix的组件。- Alibaba对于springcloud没有的功能也提供了组件,如分布式事务
Seata,分布式消息RocketMQ - SpringCloud Alibaba 优于 SpringCloud Netflix,SpringCloud Netflix 核心组件停止维护。
- 阿里巴巴的这些也可以跟netflix的组件自由组合搭配使用。阿里的新组件并非完全替代netflix,如nacos内部也引入了ribbon。
- spring cloud alibaba也遵循spring cloud的标准,所以能够与netflix自由组合 | | SpringCloud | SpringCloudAlibaba | | —- | —- | —- | | 注册中心 | Eureka | Nacos | | 负载均衡 | Ribbon | Dubbo LB | | 熔断器 | Hystrix | Sentinel | | 配置中心 | SpringCloudConfig | nacos | | 网关 | Zuul | - | | 配置中心 | Config | Nacos | | 服务调用 | Feign | Dubbo |
Cloud ,Cloud Alibb与Boot版本对应关系
- lombok版本最好大于
1.14因为lombok需要配合idea的lombok插件才能起作用。idea的lombok插件一般是最新版本的,不一定兼容低版本的lombok依赖
cloud项目实战
- ruoyi
- 登录模块单独作为一个服务
- 当前登录信息获取得实现:在所有请求得token拦截器那里登录成功就往ThreadLocal里面存入map。map里存有该请求得用户名,用户id等(这些东西一般存于请求头里面)。ThreadLocal
- 这个项目里redis,功能是否启用,路由规则等配置都配置到了nacos的配置文件里,这些可能容易变动或者一对多的组件(如redis) 就配置到配置中心方便管理
- 服务发现注册等不容易变动的就配置到项目里的配置文件里.
- 网关:单独作为单独一个项目,请求都到网关进行一系列过滤再转发给路由的相关服务。
- 各种通用的配置可以提取为一个公共的模块。其中公共模块里每一个功能相关的配置再作为一个子模块。如redis相关的配置作为一个模块
- 使用时直接像普通依赖一样引用其中具体的某个模块即可,父级common就是个普通的继承型pom,子项目都采用jar打包方式(无需配置,packing默认就是jar)
- 会自动将引入模块的需要依赖一同传递过来,能直接使用引入模块定义的功能

- 登录模块单独作为一个服务
