文章目录
一、什么是微服务?
微服务,顾名思义是微小的服务,它是将一个单体的应用开发为一组微小的服务,每个服务独立,是一个独立的业务模块,运行在自己的进程中,服务间通信采用轻量级的通信机制(通常采用HTTP资源API),这些服务共用一个最小型的集中式管理,服务可用不同的语言开发,使用不同的数据存储技术。
1.为什么使用微服务?微服务的优点:
在传统的互联网项目来说,都是各种大大小小的独立系统耦合在一起,对于系统的扩展来说,是比较差的,维护成本也比较高。而且将所有功能都写在一个项目里,各种功能和业务耦合在一起,维护特别麻烦,各个功能模块之间很难分清界限,出现问题很难定位问题的范围,甚至可能一部分错误,导致系统的崩溃。
优点:
- 将复杂的业务拆分为多个小的业务,每个业务拆分成一个服务,将复杂的问题简单化。利于分工,降低新人学习成本。
- 微服务系统是分布式系统,业务与业务之间完全解耦,随着业务的增加可以根据业务再拆分,具有极强的横向扩展能力。面对高并发的场景可以将服务集群化部署,加强系统的负载能力。
- 服务间采用HTTP协议通信,服务与服务之间完全独立,每个服务可以根据业务场景选取合适的编程语言和数据库。
- 微服务每个服务都是可以独立部署,每个服务的修改和部署对其他服务没有影响。
简单总结就是:服务拆分、扩展性好、完全解耦、独立部署。
2.微服务的缺点:
- 开发人员要处理分布式系统带来的复杂性,如:
- 怎么多服务,客户端如何去访问?
- 怎么多服务,服务之间如何进行通信?
- 怎么多服务,如何进行治理?
- 怎么多服务,服务挂了怎么办?
- 多服务运维难度和成本高,运维压力大。
- 多服务管理复杂
- 系统部署依赖
- 系统集成测试
- 数据一致性
二、微服务技术栈
三、SpringCloud是什么?
SpringCloud是分布式微服务架构下的一站式解决方案,是各个微服务架构落地技术的集合体,俗称微服务全家桶。
SpringCloud是基于SpringBoot提供的一套微服务解决方案,包括服务注册、配置中心、全链路监控、服务网关、负载均衡、熔断器等组件,除了NetFix的开源组件做高度封装之外,还有一些选型中立的开源组件。
SpringCloud利用SpringBoot的开发便利性,巧妙地简化了分布式系统基础设施的开发,SpringCloud为开发人员提供了快速构建分布式系统的一些工具,包括配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选,分布式会话等等,他们都可以用SpringBoot的开发风格做到一键启动和部署。
SpringCloud并没有重复造轮子,它只是将目前各家公司开发的比较成熟,经得起实际考验的服务框架组合起来,通过SpringBoot风格进行再封装,屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂,易部署和维护的分布式系统开发工具包。
四、SpringCloud和SpringBoot的关系
- SpringbBoot专注于快速、方便的开发单个个体微服务,就是.jar。
- SpringCloud是关注全局的微服务协调治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来,为各个微服务之间提供:配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等集成服务。
- SpringBoot可以离开SpringCloud独立使用,开发项目,但是SpringCloud离不开SpringBoot,属于依赖关系。
- SpringBoot专注于快速、方便的开发单个个体微服务,SpringCloud关注全局的服务治理框架。
五、什么是Eureka?
NetFlix在设计Eureka时,遵循的就是API原则。Eureka是Netfix的一个子模块,也是核心模块之一。Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移,服务在注册与发现对于微服务来说是非常重要的,有了服务注册与发现,只需要使用服务的标识符,就可以访问到服务,而不需要修改服务调用的配置文件,功能类似于Dubbo注册中心,比如Zookeeper。
1.原理
参考:https://blog.csdn.net/qwe86314/article/details/94552801
Eureka的基本架构
- SpringCloud封装了NetFlix公司开发的Eureka模块来实现服务的注册与发现(对比Zookeeper)。
- Eureka采用C-S的架构设计,EurekaServer作为服务注册功能的服务器,它是服务注册中心。
- 而系统中的其他微服务,使用Eureka的客户端连接到EurekaServer并维持心跳连接,这样系统的维护人员就可以通过EurekaServer来监控系统中各个微服务是否正常运行,SpringCloud的一些其他模块(比如:Zuul)就可以通过EurekaServer来发现系统中的其他微服务,并执行相关的逻辑。
服务提供者和服务的消费者,本质上也是 Eureka Client 角色。整体上可以分为两个主体:Eureka Server 和 Eureka Client。这也是Eureka包含的两个组件。
Eureka Server:注册中心服务端
Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样Eureka Server中的服务注册表中将会列出所有可用的服务节点信息,服务节点的信息可以在界面中直观的看到。
主要对外提供了三个功能:
- 服务注册
服务提供者启动时,会通过 Eureka Client 向 Eureka Server 注册信息,Eureka Server会存储该服务的信息,Eureka Server 内部有二层缓存机制来维护整个注册表 。 - 提供注册表
服务消费者在调用服务时,如果 Eureka Client 没有缓存注册表的话,会从 Eureka Server 获取最新的注册表。 - 同步状态
Eureka Client 通过注册、心跳机制和 Eureka Server 同步当前客户端的状态。
Eureka Client:注册中心客户端
Eureka Client 是一个 Java 客户端,用于简化与 Eureka Server 的交互。Eureka Client 会拉取、更新和缓存 Eureka Server 中的信息。因此当所有的 Eureka Server 节点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者,但是当服务有更改的时候会出现信息不一致。
- Register: 服务注册
服务的提供者,将自身注册到注册中心,服务提供者也是一个 Eureka Client。当 Eureka Client 向 Eureka Server 注册时,它提供自身的元数据,比如 IP 地址、端口,运行状况指示符 URL,主页等。 - Renew: 服务续约
Eureka Client 会每隔 30 秒发送一次心跳来续约。 通过续约来告知 Eureka Server 该 Eureka Client 运行正常,没有出现问题。 默认情况下,如果 Eureka Server 在 90 秒内没有收到 Eureka Client 的续约,Server 端会将实例从其注册表中删除,此时间可配置,一般情况不建议更改。
服务续约的两个重要属性:
服务续约任务的调用间隔时间,默认为30秒
eureka.instance.lease-renewal-interval-in-seconds=30
服务失效的时间,默认为90秒。
eureka.instance.lease-expiration-duration-in-seconds=90\
- Eviction 服务剔除
当 Eureka Client 和 Eureka Server 不再有心跳时,Eureka Server 会将该服务实例从服务注册列表中删除,即服务剔除。 - Cancel: 服务下线
Eureka Client 在程序关闭时向 Eureka Server 发送取消请求。 发送请求后,该客户端实例信息将从 Eureka Server 的实例注册表中删除。该下线请求不会自动完成,它需要调用以下内容:
DiscoveryManager.getInstance().shutdownComponent();
- GetRegisty: 获取注册列表信息
Eureka Client 从服务器获取注册表信息,并将其缓存在本地。客户端会使用该信息查找其他服务,从而进行远程调用。该注册列表信息定期(每30秒钟)更新一次。每次返回注册列表信息可能与 Eureka Client 的缓存信息不同,Eureka Client 自动处理。
如果由于某种原因导致注册列表信息不能及时匹配,Eureka Client 则会重新获取整个注册表信息。 Eureka Server 缓存注册列表信息,整个注册表以及每个应用程序的信息进行了压缩,压缩内容和没有压缩的内容完全相同。Eureka Client 和 Eureka Server 可以使用 JSON/XML 格式进行通讯。在默认情况下 Eureka Client 使用压缩 JSON 格式来获取注册列表的信息。
获取服务是服务消费者的基础,所以必有两个重要参数需要注意:
# 启用服务消费者从注册中心拉取服务列表的功能
eureka.client.fetch-registry=true
# 设置服务消费者从注册中心拉取服务列表的间隔
eureka.client.registry-fetch-interval-seconds=30
- Remote Call: 远程调用
当 Eureka Client 从注册中心获取到服务提供者信息后,就可以通过 Http 请求调用对应的服务;服务提供者有多个时,Eureka Client 客户端会通过 Ribbon 自动进行负载均衡。
2.自我保护机制
默认情况下,如果 Eureka Server 在一定的 90s 内没有接收到某个微服务实例的心跳,会注销该实例。但是在微服务架构下服务之间通常都是跨进程调用,网络通信往往会面临着各种问题,比如微服务状态正常,网络分区故障,导致此实例被注销。
固定时间内大量实例被注销,可能会严重威胁整个微服务架构的可用性。为了解决这个问题,Eureka 开发了自我保护机制,那么什么是自我保护机制呢?
Eureka Server 在运行期间会去统计心跳失败比例在 15 分钟之内是否低于 85%,如果低于 85%,Eureka Server 即会进入自我保护机制。
Eureka Server 触发自我保护机制后,页面会出现提示:
Eureka Server 进入自我保护机制,会出现以下几种情况:
- Eureka 不再从注册列表中移除因为长时间没收到心跳而应该过期的服务。
- Eureka 仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)。
- 当网络稳定时,当前实例新的注册信息会被同步到其它节点中。
Eureka 自我保护机制是为了防止误杀服务而提供的一个机制。当个别客户端出现心跳失联时,则认为是客户端的问题,剔除掉客户端;当 Eureka 捕获到大量的心跳失败时,则认为可能是网络问题,进入自我保护机制;当客户端心跳恢复时,Eureka 会自动退出自我保护机制。
如果在保护期内刚好这个服务提供者非正常下线了,此时服务消费者就会拿到一个无效的服务实例,即会调用失败。对于这个问题需要服务消费者端要有一些容错机制,如重试,断路器等。
通过在 Eureka Server 配置如下参数,开启或者关闭保护机制,生产环境建议打开:
eureka.server.enable-self-preservation=true
六、Eureka与Zookeeper对比:
1.ACID原则
解释:https://www.cnblogs.com/sweetorangezzz/p/13363236.html
- A(Atomicity)原子性
- C(Consistency)一致性
- I(Isolation)隔离性
- D(Durability)持久性
2.CAP原则
CAP原则又称CAP定理,指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。
RDBMS(关系数据库管理系统:Mysql、Oracle、sqlServer)遵循的是ACID原则。
NoSQL(非关系型的数据库:redis、mongdb)遵循的是CAP原则。
CAP理论的核心:
- 一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这个三个需求。
- 根据CAP原理,将NoSQL数据库分成了满足CA原则,满足CP原则和满足AP原则三大类:
- CA:单点集群,满足一致性,可用性的系统,通常扩展性较差。
- CP:满足一致性,分区容错性的系统,通常性能不是特别高。
- AP:满足可用性,分区容错性的系统,通常可能对一致性要求要低一些。
3.作为服务注册中心,Eureka比Zookeeper好在哪里?
-
Zookeeper保证的CP原则
加粗样式当向注册中心查询服务列表时,我么可以容忍注册中心返回的几分钟以前的注册信息,但不能接受服务直接down掉不可用,也就是说,服务注册功能对可用性的要求要高于一致性。但是Zookeeper会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩下节点会重新进行leader选举,问题在于,选举leader的时间太长,30~120s,且选举期整个Zookeeper集群都是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因为网络问题使得Zookeeper集群失去master节点是较大概率会发生的事件,虽然服务最终会恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。 -
Eureka保证的是AP原则
Eureka看明白了这一点,因此在设计时就优先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册时,如果连接失败,则会自动切换其他节点,只要有一台Eureka还在,就能保住注册服务的可用性,只不过查到的信息可能不是最新的,除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:- Eureka不再从注册中心列表中移除因为长时间没收到心跳而应该过期的服务。
- Eureka仍然能够接受新服务的注册和查询请求,但是不会同步到其他节点上(即保证当前节点依然可用)。
- 当网络不稳定时,当前实例新的注册信息会被同步到其他节点中。
因此,Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像Zookeeper那样使整个注册服务瘫痪。
七、Ribbon负载均衡
SpringCloud Ribbon是基于NetFlix Ribbon实现的一套客户端负载均衡的工具。
简单的说,Ribbon是NetFlix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将NetFlix的中间层服务连接在一起。Ribbon的客户端组件提供一系列完整的配置项,如:连接超时、重试等等,简单的说,就是在配置文件中列出LoaderBalancer(负载均衡)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询、随机连接等等)去连接这些机器。我们也很容易实现自定义的负载均衡算法(实现IRule接口)。
1.Ribbon能干嘛?
- Ribbon能进行负载均衡,负载均衡简单的说就是将用户的请求均匀的分配到服务上,从而达到系统的高可用。
- dubbo、SpringCloud中均给我们提供了负载均衡,SpringCloud的负载均衡算法可以自定义。
- 集中式负载均衡:即在服务消费方和提供方之间使用独立的负载均衡设施,如Nginx,由该设施负责把访问请求通过某种策略转发至服务的提供方。
- 进程式负载均衡:将负载均衡逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选出一个合适的服务器。Ribbon就属于进程内负载均衡,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。
八、Feign负载均衡
feign是一个声明式的web service客户端,它让微服务之间的调用变得更简单了,类似Controller调用service,SpringCloud对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡。
只需要创建一个接口,然后添加注解即可。
大家目前都习惯面向接口编程,比如WebService接口,比如我们的DAO接口,这个已经是大家的规范。那么调用微服务有两种方法:
- 通过微服务名字获得调用地址。
- 通过注解+接口,获得我们的调用服务。
适应社区其他程序员提出的,还是统一的面向接口编程的套路。
1.Feign能干什么?
- Feign旨在使编写Java Http客户端变得更容易。
- 前面在使用Ribbon+RestTemplate时,利用RestTemplate对Http请求的封装处理,形成了一套模板化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用,所以,Feign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义,在Feign的实现下,我们只需要创建一个接口并使用注解的方式来配置它(类似于以前的Dao接口上标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可)。即可完成对服务提供方的接口绑定,简化了使用springCloud Ribbon时,自动封装服务调用客户端的并发量。
2.Feign集成了Ribbon
- 利用Ribbon维护了MicroServiceCloud-Dept的服务列表信息,并通过轮询实现了客户端的负载均衡,而与Ribbon不同的是,通过Feign只需要定义服务绑定接口且以声明式的方法,优雅而且简单的实现了服务调用。
九、Hystrix服务熔断
1.分布式系统面临的问题
复杂的分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免的失败。
2.服务雪崩
多个微服务之间调用的时候,A,B服务同时依赖于基础服务C,基础服务C又调用了服务D,服务D是一个辅助类型服务,整个业务不依赖于D服务,某天D服务突然响应时间变长,导致了核心服务C响应时间变长,其上请求越积越来越多,C服务也出现了响应变慢的情况,由于A,B强依赖于服务C,故而一个无关紧要的服务却影响了整个系统的可用。这就是所谓的“雪崩效应”。
雪崩的根本原因来源于服务之间的强依赖,所以我们可以提前评估,做好熔断,隔离,限流。
对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒中内饱和,比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障,这些都需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。
3.Hystrix的作用:
Hystix是Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败。
使用Hystix解决雪崩问题的手段有两个:
- 线程隔离
- 服务熔断
4.服务熔断
熔断原理
熔断器,也叫断路器,其英文单词为:Circuit Breaker
熔断状态机3个状态:
- Closed:关闭状态,所有请求都正常访问。
- Open:打开状态,所有请求都会被降级。Hystix会对请求情况计数,当一定时间内失败请求百分比达到阈值,则触发熔断,断路器会完全打开。默认失败比例的阈值是50%,请求次数最少不低于20次。
- Half Open:半开状态,open状态不是永久的,打开后会进入休眠时间(默认是5S)。随后断路器会自动进入半开状态。此时会释放部分请求通过,若这些请求都是健康的,则会完全关闭断路器,否则继续保持打开,再次进行休眠计时
什么是服务降级?
服务降级:优先保证核心服务,而非核心服务不可用或弱可用
对比:
-
服务熔断: 服务端, 某个服务器超时或者异常,引起熔断 就像保险丝
-
服务降级:客户端,从整体网站请求负载考虑,当某个服务熔断或者关闭后,服务不在被调用,此时在客户端,我们可以准备一个FallbackFactory,返回一个默认的值(缺省值)整体的服务水平下降了。
十、Zuul网关
总结
待完善。。。