开发者学堂课程【微服务框架 Spring Cloud 快速入门:服务降级熔断小总结】学习笔记与课程紧密联系,让用户快速学习知识
课程地址:https://developer.aliyun.com/learning/course/614/detail/9364
服务降级熔断小总结
目录
一、分布式系统面临的问题
二、服务雪崩解释
三、何为服务熔断
四、何为降级
前面已经完成了服务熔断和服务降级,这两个概念非常容易让人模糊,现在进行一下简单的总结。
一、分布式系统面临的问题
复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免的失败。
例子:
前面讲过,在复杂的分布式系统当中,一定会有各个微服务之间的调用,在调用的过程当中,由于微服务之间结偶了,但是服务型的通信避免不了有异常超时,这个时候如图中所说,这个A在I这儿,假设现在是一个用户请求,但如果10万个用户请求,都会到I这儿,每个用户等三秒钟,10万个的时候为了避免在超时出故障的时候,引起大面积的服务调用系统资源瞬间被挂起耗死的情况,这个时候只能完成相应的切割和熔断。
二、服务雪崩解释:
多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其他微服务。这就是所谓的扇出,如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用,就会占用越来越多的系统资源,进而引起系统崩溃,所谓的雪崩效应。
回忆一下刚才所说的:
Public
class
DeptController
{
@Autowired
private
DeptService
service
=
null;
@RequestMapping(value = "/dept/get/
{
id
}
", method = RequestMethod.GET)
//-旦调用服务方法失败并抛出了错误信息后,会自动调用 @HystrixCommand 标注好的 fallbackMethod 调用类中的指定方法
@HystrixCommand(fallbackMethod = "processHystrix_Get")
public
Dept
get(@PathVariable("id")
Long
id)
{
//由于他这是要返回一个Dept,干脆因势利导也返回一个Dept,但是这个 Dept 里面的信息已经完全变了,相当于是一个带着异常信息的一个返回值。
Dept
dept
=
this.service.get(id);
if (null == dept)
{
throw
new
RuntimeException
("该ID:"+ id + "没有对应的信息");
}
//故意人为的抛出一个异常,可以当作在调微服务提供者在熔断8001的时候故意A调B,B这个微服务就是这个熔断8001出了故障,要是出了故障,这个时候抛出了一个异常,针对于我调用哪个方法(get)哪个方法出现了异常。用了@HystrixCommand这个,然后由fallbackMethod来进行操作。
(
processHystrix_Get
)。
return
dept;
}
Public
Dept
processHystrix
_
Get(@PathVariable("id")
Long
id)
{
return new Dept().setDeptno(id).setDname
("该ID:"+ id + 没有没有对应的信息,null--@HystrixCommand")
.
setDb_source("no this database in MySQL");
//前端工程师去解析的时候,比如【no this database in MySQL】写成【4444】,假设前端工程师取某一个字段是一个失败的值的话,那么就会进行一种友好页面的提示或者是异常的处理。
三、何为服务熔断?
服务熔断:
一般是某个故障或者异常引起,类似现实世界中的“保险丝”,当某个异常条件被触发,直接熔断整个服务。而不会一直等到此服务超时。导致服务系统的资源大面积的被占用。
异常引起:
Public
class
DeptController
{
@Autowired
private
DeptService
service
=
null;
@RequestMapping(value = "/dept/get/
{
id
}
", method = RequestMethod.GET)
//-旦调用服务方法失败并抛出了错误信息后,会自动调用 @HystrixCommand标注好的 fallbackMethod 调用类中的指定方法
@HystrixCommand(fallbackMethod = "processHystrix_Get")
public
Dept
get(@PathVariable("id")
Long
id)
{
Dept
dept
=
this.service.get(id);
if (null == dept)
{
throw
new
RuntimeException
("该ID:"+ id + "没有对应的信息");
}
//故意当查询235的那个号或者9999这个 ID 数据库里面没有的,查出来是个 null,是null 就抛异常。
return
dept;
}
Public
Dept
processHystrix
_
Get(@PathVariable("id")
Long
id)
{
return new Dept().setDeptno(id).setDname
("该ID:"+ id + 没有没有对应的信息,null--@HystrixCommand")
.
setDb_source("no this database in MySQL");
这就是服务熔断,后面讲的两个小问题,既然由熔断了从技术和应用的角度又为什么会有降级?
先说技术:Spring Cloud 有两个重要的支柱,一个是 IOC 一个是 AOP。AOP 就是面向切面的工程,应该把主业物跟异常处理给他做成一个切面,用织入的方式执行。也就是说业务逻辑方法里面就不应该带着这么多横向的横切性关注点,这种异常的处理信息。实现主业务方法后的异常处理,熔断处理的解耦,这是第一步,第二个要避免方法膨胀,这些get方法及底层还是调这个 service 接口。
package
com. atguigu. spr ingc loud.service;
import
java
.
util.list;
public interface DeptService
{
public
boolean ada(Dept dept);
public
Dept
get(Long id);
public List list();
}
这个接口里面这个方法,如果针对这个接口里面的每一个方法做一次熔断处理,做一次服务的异常情况的处理,可以避免不用每一个方法头上都添加一个fallbackMethod方法,将把分散的fallbackMethod方法集中起来统一的放在一个接口里面
* @Desription:修改 microsenicecloud-api 工程,根已有的 DeptClientService接口
一个实现了 FallbackFactory 接口的 DeptClientServiceFallbackFactory
* @author zzyy
* @date 201844月21日
*
/
//@FeignClient(value = "MICROSERVICECLOUD
-
DEPT")
@FeignClient(value - "MICROSERVICECLOUD-DEPT",fallbackFactory=DeptClientServiceFallbackFactory.class
)
public interface DeptClientService
{
@RequestMapping(value
=
"/dept/get/
{
id
}
",
method
=
RequestMethod
GET)
public Dept get (@PathVariable("id") long id);
@RequestMapping(value
= "
/dept/list",
method
=
RequestMethod.GET)
public List list();
@RequestMapping(value
=
"/dept/add",
method
=
RequestMethod.POST)
public boolean add(Dept dept);
}
注意这个接口是API的,这个接口统一的提出来让他针对于某个微服务,然后这个微服务要用这个接口,如果调用这个接口里面的任何一个方法,出了问题以后由FallbackFactory这个类来实现。
import
java.util.List;
@Component
//不要忘记添加,不要忘记添加
Public
class
DeptClientServiceFallbackFactory
implements
FallbackFactory
<
DeptClientServiceoverride
>
{
@Override
public DeptClientService create(Throwable
throwable)
return new
DeptClientService(){
@Overrid
Public
Dept
get(long
v
id)
{
return new
Dept().setDeptno
(ID).setDname
("该ID:"+id+"没有没有对应的信息,Consumer 客户端提供的降级信息,此刻服务 provider 已经关闭”)
.setDb_source("no this database in
MySQL");
}
@Override
publicListlist()
Return
null;
}
@Override
public boolean
add (Dept
dept)
{
Return
false;
}
四、何为降级:
比如现在 ABC 三个系统,每个系统有5个开发工程师支撑,平时都是大家是平等的关系,但是,为了保证A系统能够充分的开发,现在客户比较注重A系统的功能,要投入更多的资源,希望这一个月以内程序员的数量增加到10个,这个时候要从其他项目做借调资源程序员过来支援A,这就是忍痛将某些服务先关掉,现在这种情况,刚才的这种项目管理上借调这种问题,就是为了保证A这个系统资源开发充分。先把C借调过来。C这个微服务,这个项目的资源被抽掉了,抽掉了以后,对C而言服务被做了降级,但是有可能还有其他FM这个C,这个时候就要从服务降级的侧面考虑。
服务降级:
所谓降级,一般是从整体到负荷考虑,是当某个服务熔断之后,服务器将不再被调用,此时客户端可以自己准备一个本地的 Fall back 回调,返回一个缺省值。
降级说过了,一般从整体符合考虑一定要深刻理会理会这句话整体资源快不够了,忍痛将某些服务先关掉,就可以看到服务器都关了,将不再被调用,8001(C)现在都给它关了,客户端为了避免导致整个系统被挂机资源被占用耗尽死循环死锁各种异常现象,赶快保证服务的健壮性,客户端自己就做了一套本地的 Fall back 回调的方法,可以返回一个缺省值。