在微服务架构中,我们将业务拆分成一个个的服务,服务与服务之间可以相互调用,但是由于网络原因或者自身的原因,服务并不能保证服务的100%可用,如果单个服务出现问题,调用这个服务就会出现网烙延迟,此时若有大量的网络涌入,会形成任务堆积。最终导致服务瘫痪。
在分布式系统中,由于网络原因或自身的原因,服务一般无法保证100%可用。如果一个服务出现了问题,调用这个服务就会出现线程阻塞的情况,此时若有大量的请求涌入,就会出现多条线程阻塞等待,进而导致服务瘫痪。
由于服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的“雪崩”效应。
雪崩发生的原因多种多样,有不合理的容量设计,或者是高并发下某一个方法响应变慢,亦或是某台机器的资源耗尽。我们无法完全杜绝雪崩源头的发生,只有做好足够的容错,保证在一个服务发生问题,不会影响到其它服务的正常运行。也就是”雪落而不雪崩”。
要防止雪崩的扩散,我们就要做好服务的容错,容错说白了就是保护自己不被猪队友拖垮的一些措施,下面介绍常见的服务容错思路和组件。
常见的容错思路有隔离、超时、限流、熔断、降级这几种,下面分别介绍一下。
什么是Sentinel
Sentinel (分布式系统的流量防卫兵)是阿里开源的一套用于服务容错的综合性解决方案。它以流量为切入点从流量控制、熔断降级、系统负载保护等多个维度来保护服务的稳定性。
丰富的应用场景: Sentinel 承接了阿里巴巴近10年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
完备的实时监控: Sentinel提供了实时的监控功能。通过控制台可以看到接入应用的单台机器秒级数据,甚至500台以下规模的集群的汇总运行情况。
广泛的开源生态: Sentinel提供开箱即用的与其它开源框架/库的整合模块,例如与Spring Cloud、Dubbo.gRPC的整合。只需要引入相应的依赖并进行简单的配置即可快速地接入Sentinel。
完善的SPI扩展点: Sentinel提供简单易用、完善的SPI扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>
Sentinel提供一个轻是级的控制台,它提供机器发现、单机资源实时监控以及规则管理等功能。
下载地址:https://download.csdn.net/download/lmd770013209/87372940?spm=1001.2014.3001.5503
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.7.0.jar
#跟控制台交流的端口,随意指定一个未使用的端口即可
spring.cloud.sentinel.transport.port=9999
#指定控制台服务的地址
spring.cloud.sentinel.transport.dashboard=localhost:8080
然后就可以启动在控制台中进行相关的容错处理
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>
#开启feign对sentinel的支持
feign.sentinel.enabled=true
package com.web.service.fullback;
import com.web.service.MemberService;
import org.springframework.stereotype.Service;
@Service
public class fullbackService implements MemberService {
@Override
public String GetMember() {
return "获取会员信息失败";
}
}
package com.web.service;
import com.web.service.fullback.fullbackService;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
@FeignClient(value = "web-member",
fallback = fullbackService.class
)
@Service
public interface MemberService {
@RequestMapping("/getMember")
String GetMember();
}
@RequestMapping("/getOrder")
public Object getOrder(){
//这个地方就是返回的信息,当失败后
if(this.memberService.GetMember().equals("获取会员信息失败")){
return "获取会员信息失败";
}
String url = "http://web-member/getMember";
String s = resttemplate.getForObject(url,String.class);
return "这是我的订单接口获取到的数据"+s;
}
效果就是降级处理,返回 “获取会员信息失败"。