服务雪崩效应 {#%E6%9C%8D%E5%8A%A1%E9%9B%AA%E5%B4%A9%E6%95%88%E5%BA%94}
-
在微服务架构中,由于存在多个服务之间的调用,基础服务的故障可能会引发连锁反应,导致一系列服务相继出现故障,最终可能导致整个系统无法正常运行。这种现象被称为服务雪崩效应。
-
服务雪崩效应是指由于服务提供者的不可用,导致服务消费者也无法正常使用,并且这种不可用状态会逐渐扩大,影响更多的服务。
服务雪崩效应的形成原因 {#%E6%9C%8D%E5%8A%A1%E9%9B%AA%E5%B4%A9%E6%95%88%E5%BA%94%E7%9A%84%E5%BD%A2%E6%88%90%E5%8E%9F%E5%9B%A0}
-
服务提供者不可用
-
服务中断或性能下降
-
服务资源分配不足或过载
-
-
硬件故障
-
服务器硬件故障
-
网络设备故障
-
存储设备故障等硬件问题导致的服务中断或性能下降。
-
-
程序Bug
-
代码逻辑错误导致的服务异常终止或性能下降。
-
数据库操作不当等导致服务崩溃。
-
-
缓存击穿
- 由于缓存失效或缓存击穿导致的服务请求直接打到数据库上,造成数据库过载。
-
用户大量请求
-
用户并发量过大导致服务负载过高。
-
用户请求过于集中,导致服务响应能力不足。
-
用户重试机制问题及其影响 {#%E7%94%A8%E6%88%B7%E9%87%8D%E8%AF%95%E6%9C%BA%E5%88%B6%E9%97%AE%E9%A2%98%E5%8F%8A%E5%85%B6%E5%BD%B1%E5%93%8D}
用户重试机制在服务调用中起着重要作用,但不当的重试策略可能导致流量放大,加剧服务压力。以下是关于用户重试的一些要点:
- 代码逻辑重试机制不当导致的流量放大问题。当服务调用失败时,如果重试逻辑设计不合理,可能导致大量重复请求,进一步加大服务压力。因此,需要合理设计重试逻辑,避免不必要的重复请求。同时,也需要考虑设置合适的重试次数和间隔,避免过度重试导致的流量放大问题。另外,还需要关注代码逻辑中的异常处理机制是否完善,能否有效应对异常情况并避免服务崩溃。此外,还需要关注服务调用者的可用性对服务的影响。当服务调用者出现故障时,可能会影响到服务的正常运行和响应能力。因此,需要确保服务调用者的稳定性和可靠性,避免由于调用者的问题导致服务雪崩效应的发生。针对同步等待造成的资源耗尽问题,可以通过优化资源分配策略、提高系统并发能力等方式来解决。同时还需要关注系统架构的优化和负载均衡策略的设计等方面来增强系统的稳定性和可靠性。
服务雪崩的应对策略 {#%E6%9C%8D%E5%8A%A1%E9%9B%AA%E5%B4%A9%E7%9A%84%E5%BA%94%E5%AF%B9%E7%AD%96%E7%95%A5}
-
以下是改进后的内容:
一、服务限流措施
- 网关层限流
-
实施API网关限流机制
-
设定请求频率和并发数上限
- 用户交互限流
-
针对用户行为实施限流策略,避免过度请求
-
实施会话管理,控制用户并发请求数量
- 关闭重试机制
- 在特定情况下,关闭自动重试功能以避免过度负载
二、优化缓存模式
- 缓存预加载策略
-
预先加载热门内容,提高访问速度
-
实施缓存预热和冷启动策略
- 刷新机制优化
-
由同步刷新改为异步刷新,提高系统响应速度
-
实施缓存失效策略,确保数据准确性
三、服务自动扩容策略
- 利用AWS自动扩展功能(auto scaling)
-
根据业务需求设定自动扩容规则,确保服务性能稳定。
-
实时监控资源使用情况,自动调整服务规模。
四、服务降级措施
- 资源隔离策略
-
对关键服务进行资源隔离,确保核心功能稳定运行。
-
实施防火墙和安全组策略,防止资源被滥用。
- 依赖服务分类管理
-
对依赖服务进行分类管理,明确关键服务和非关键服务。
-
针对不同类型的服务实施不同的降级策略。
- 不可用服务的快速失败策略
- 针对不可用的服务实施快速失败机制,避免长时间等待和资源浪费。
Hystrix介绍 {#hystrix%E4%BB%8B%E7%BB%8D}
-
实现熔断器、回退机制以及舱壁机制需要丰富的多线程开发经验。幸运的是,Netflix的Hystrix库已经为我们提供了这些功能,并且Spring Cloud已经将其集成到Spring Cloud Hystrix中,从而极大地简化了我们的开发工作,使得应用更加健壮。
-
Hystrix,也被称为"断路器",是为了解决服务雪崩问题而诞生的。其名字来源于豪猪(因其背上长满刺,拥有自我保护能力),代表着这款容错框架具备强大的系统保护能力。Hystrix是Netflix公司开源的一个类库,主要用于处理分布式系统交互时的超时和容错问题。
-
针对依赖的延迟和故障防护与控制措施:
-
强化网络访问的依赖防护机制,有效抵御延迟和故障风险。
-
实施阻止失败策略,确保系统迅速恢复并维持稳定运行。
-
启用回退机制,确保在出现问题时能够优雅降级服务质量和功能。
-
提供近实时的监控,实时监控依赖项的性能和状态,并实时发出告警通知,以便及时响应和处理问题。
-
请求熔断 {#%E8%AF%B7%E6%B1%82%E7%86%94%E6%96%AD}
当Hystrix Command请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open)。这时所有请求会直接失败而不会发送到后端服务。
断路器保持在开路状态一段时间后(默认5秒), 自动切换到半开路状态(HALF-OPEN)。这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN)。
Hystrix的断路器就像我们家庭电路中的保险丝, 一旦后端服务不可用, 断路器会直接切断请求链, 避免发送大量无效请求影响系统吞吐量, 并且断路器有自我检测并恢复的能力.
服务降级 {#%E6%9C%8D%E5%8A%A1%E9%99%8D%E7%BA%A7}
服务降级策略在微服务架构中扮演着至关重要的角色。当某个微服务响应时间过长或无法提供服务时,我们不应直接暴露错误信息或让请求长时间挂起。为此,我们需要预先设计一种策略(即方法),以应对此类问题。当服务出现问题时,我们可以迅速调用该方法,使请求得以快速响应,避免长时间等待或阻塞。
Fallback机制是服务降级的一种表现形式。对于查询操作,我们可以实现一个fallback方法,当后端服务请求出现异常时,该方法可以提供一个返回值。这个返回值通常是预设的默认值或是从缓存中获取的数据。通过fallback方法的返回值,我们可以告知后续请求当前服务不可用,以避免不必要的请求浪费。同时,这也提升了系统的稳定性和用户体验,确保系统在面临压力或故障时仍能保持一定的服务能力。
依赖隔离 {#%E4%BE%9D%E8%B5%96%E9%9A%94%E7%A6%BB}
资源隔离与依赖管理在Hystrix中的实现
在Hystrix中,依赖隔离主要通过线程池来实现。当涉及到多个远程服务的调用时,为每个服务分配独立的线程池是一种常见做法。
设想一个场景,如果一个服务依赖于另外两个服务,并且所有的服务调用都使用同一个线程池,那么一旦其中一个服务出现问题或响应缓慢,就会占用线程池中的资源,导致后续请求无法及时得到处理。这种情况下,一个服务的性能问题可能会影响到其他服务的正常运行,造成连锁反应。
为了解决这个问题,我们可以采用依赖隔离的策略。例如,当我们有100个线程可用时,可以为服务A分配50个线程,为服务B分配另外50个线程。这样,即使服务A出现问题或响应缓慢,服务B仍然可以正常使用其分配的线程资源进行处理。这种策略确保了不同服务之间的资源隔离,提高了系统的稳定性和容错能力。
货船为了进行防止漏水和火灾的扩散,会将货仓分隔为多个这种采用多个隔仓的来减少货船风险的方式被水密隔舱。
使用Hystrix处理容错 {#%E4%BD%BF%E7%94%A8hystrix%E5%A4%84%E7%90%86%E5%AE%B9%E9%94%99}
创建容错处理类 {#%E5%88%9B%E5%BB%BA%E5%AE%B9%E9%94%99%E5%A4%84%E7%90%86%E7%B1%BB}
demo-user-consumer项目中创建容错处理类UserFeignClientFallBack
UserFeignClientFallBack需要实现UserFeignClient接口
为接口指定容错处理 {#%E4%B8%BA%E6%8E%A5%E5%8F%A3%E6%8C%87%E5%AE%9A%E5%AE%B9%E9%94%99%E5%A4%84%E7%90%86}
demo-user-consumer项目的UserFeignClient接口中,通过@FeignClient注解的fallback属性指定容错处理类
添加配置 {#%E6%B7%BB%E5%8A%A0%E9%85%8D%E7%BD%AE}
在application. yml中添加配置开启容错
feign:
hystrix:
enabled: true
负载均衡 {#%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1}
什么是负载均衡 {#%E4%BB%80%E4%B9%88%E6%98%AF%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1}
举例 {#%E4%B8%BE%E4%BE%8B}
我们在日常生活中经常免不了要去一些比较拥挤的地方,比如地铁站、火车站、电影院、银行等。无论是买票,还是排队入场,这些场所一般都会设置多个服务点或者入口的。如果没有人引导的话,大多数情况下,最近的入口会挤满人。而哪些距离较远的服务点或者入口就宽松很多。
这种情况下,就会大大浪费资源,因为如果可以把这些排队的人很好的分散到各个入口的话会大大缩短排队时间。其实,软件的建设也是一样的。为了提升系统的服务能力,很多网站采用集群部署,就像话剧院有多个入口一样。这时候,就需要一个协调者,来均衡的分配这些用户的请求,可以让用户的可以均匀的分派到不同的服务器上。
为什么使用负载均衡 {#%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BD%BF%E7%94%A8%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1}
-
Web服务器实现动态水平扩展,确保用户无感知的流畅体验。
-
有效提升业务并发访问及处理能力,轻松解决单服务器瓶颈问题。
-
节约公网IP地址资源,降低IT支出成本,实现更高效资源管理。
-
隐藏内部服务器IP,增强内部服务器的安全性,保护敏感数据不受威胁。
-
配置过程简洁明了,遵循固定格式的配置文件,降低操作难度。
-
功能丰富多样,支持四层和七层应用,支持动态下线主机,满足多种业务需求。
-
性能卓越,可支持数万甚至数十万的并发连接,确保高效稳定运行。
Ribbon简介 {#ribbon%E7%AE%80%E4%BB%8B}
Spring Cloud Ribbon 是一个客户端负载均衡器,专为HTTP和TCP客户端设计,由Netflix开发并发布。它提供了一种高效的客户端负载均衡解决方案。
关于负载均衡:
-
服务端:
- Nginx 是一种常见的服务端负载均衡解决方案。
-
客户端负载均衡:当客户端(如浏览器)向后台发起请求时,Ribbon 作为客户端组件会发挥作用。它会从 Eureka Server 读取已注册的服务列表,并根据预设的负载均衡策略(未设置时默认为默认策略)决定向哪个服务实例发送请求。这一过程对于提高系统的可扩展性和性能至关重要。其中,"Consumer"和"Provider"是Ribbon中用于描述服务调用方和被调用方的术语。
添加依赖,整合Ribbon {#%E6%B7%BB%E5%8A%A0%E4%BE%9D%E8%B5%96%EF%BC%8C%E6%95%B4%E5%90%88ribbon}
为 demo-user-consumer项目添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
//演示使用无需导入
因为项目中已经添加"spring-cloud-starter-openfeign"依赖,在这里已经包含了Ribbon,所以不用再单独引入
-
修改demo-user-provider项目checkUser()方法
-
添加Integer类型参数count
-
控制台输出当前服务和端口信息
-
-
复制demo-user-provider项目
-
修改artifactId为:demo-user-provider-2
-
修改端口为8070
-
修改控制台输出当前服务和端口信息
-
-
修改demo-user-consumer
- 多次调用Provider服务
-
依次启动服务
-
cluster-eureka-server
-
demo-user-provider
-
demo-user-provider-2
-
demo-user-consumer
-
负载均衡策略 {#%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%AD%96%E7%95%A5}
| 类 型 | 说 明 | |---------------------------|---------------------------------------------------------------------------------------| | WeightedResponseTimeRule | 根据响应时间分配一个weight(权重),响应时间越长,weight越小,被选中的可能性越低 | | RoundRobinRule | 轮询选择server(此为默认的负载均衡策略) | | RandomRule | 随机选择一个server | | ZoneAvoidanceRule | 复合判断server所在区域的性能和server的可用性选择server | | RetryRule | 在一个配置时间段内,当选择server不成功时一直尝试重新选择 | | BestAvailableRule | 选择一个并发请求最小的server | | AvailabilityFilteringRule | 过滤掉那些因为一直连接失败而被标记为circuit tripped的server,并过滤掉那些高并发的server(active connections 超过配置的阈值) |
为 demo-user-consumer项目添加配置
demo-user-provider:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
其他负载均衡策略均定义在com.netflix.loadbalancer包中,可以根据需要选择合适的策略