服务器之家

服务器之家 > 正文

springcloud使用Hystrix进行微服务降级管理

时间:2021-07-27 12:04     来源/作者:Yrion

前言:目前我们的项目是微服务架构,基于dubbo框架,服务之间的调用是通过rpc调用的。刚开始没有任何问题,项目运行健康、良好。可是过了一段时间,线上总有人反应查询订单失败,等过了一段时间才能查到。这是怎么回事呢?打开后台的日志一看出现了一些rpcexception和timeoutexception,原来是远程调用超时了,可能某个服务在请求的高发期访问数据库异常,io阻塞,返回接口异常了。后来这个问题越来越频繁,如何解决这个棘手的问题呢?

一:hystrix是什么?

1.1:基本解释

hystrix最开始由netflix(看过美剧的都知道,它是一个美剧影视制作的巨头公司)开源的,后来由spring cloud hystrix基于这款框架实现了断路器、线程隔离等一系列服务保护功能,该框架的目标在于通过控制访问远程系统、服务和第三方库的节点,从而延迟和故障提供更强大的容错能力。hystrix具备服务降级、服务熔断、线程和信号隔离、请求缓存、请求合并以及服务监控等强大功能。起到了微服务的保护机制,防止某个单元出现故障.从而引起依赖关系引发故障的蔓延,最终导致整个系统的瘫痪。

1.2:断路器的概念

断路器本身是一个开关装置,用在电路上保护线路过载,当线路中有电器发生短路的时候。“断路器”能够及时切断故障,防止发生过载、发热甚至起火等严重后果。当分布式架构中,断路器模式起到的作用也是类似的。当某个服务发生故障的时候,通过断路器的故障监控向调用方返回一个错误响应,而不是长时间的线程挂机,无限等待。这样就不会使线程因故障服务被长时间占用不释放,避免了故障在分布式系统中的蔓延。如下图是现实中的断路器,它是一个开关装置:

springcloud使用Hystrix进行微服务降级管理

二:hystrix解决超时问题

2.1:问题

假设我们前端提供了用户查询订单的功能,首先请求映射到ordercontroller,控制器通过调用服务orderservice获取订单信息,前端传过来两个参数:一个是订单id,一个是用户id,orderservice需要通过用户id调取用户服务来获取用户的相关信息返回给订单服务去组装信息,假设这里是通过http请求的,我们有一个单独的工程叫做:userservice部署在其他的服务器上。但是这个服务器宕机了,这时候订单服务调取用户信息就失败了,然后查询订单整个请求就失败了!由一个服务的宕机就导致整个查询都失败了,牵一发而动全身。流程见下图:

springcloud使用Hystrix进行微服务降级管理

2.2:使用hystrix进行服务降级

2.2.1:引入hystrix依赖 这里引入了spring-cloud-starter-netflix-hystrix,springboot的starter里面整合了hystrix

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<properties>
    <java.version>1.8</java.version>
    <spring-cloud.version>greenwich.sr1</spring-cloud.version>
  </properties>
 
  <dependencies>
    <dependency>
      <groupid>org.springframework.cloud</groupid>
      <artifactid>spring-cloud-starter-netflix-hystrix</artifactid>
    </dependency>
    <dependency>
      <groupid>org.springframework.cloud</groupid>
      <artifactid>spring-cloud-starter-netflix-hystrix-dashboard</artifactid>
    </dependency>
 
    <dependency>
      <groupid>cn.hutool</groupid>
      <artifactid>hutool-all</artifactid>
      <version>4.5.1</version>
    </dependency>
 
    <dependency>
      <groupid>org.springframework.boot</groupid>
      <artifactid>spring-boot-starter-test</artifactid>
      <scope>test</scope>
    </dependency>
  </dependencies>
 
  <dependencymanagement>
    <dependencies>
      <dependency>
        <groupid>org.springframework.cloud</groupid>
        <artifactid>spring-cloud-dependencies</artifactid>
        <version>${spring-cloud.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencymanagement>

2.2.2:模拟订单请求

首先通过ordercontroller映射/order请求,获取前端传入的参数orderid和useid,然后调用orderdetailservice方法,

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@restcontroller
public class ordercontroller {
 
  @resource
  private orderservice orderservice;
 
 
  /**
   * 获取订单信息
   *
   * @param orderno
   * @return
   */
  @postmapping("/order")
  public resultvo<orderdetail> getorderinfo(@requestparam("orderid") long orderno, @requestparam("userid") long userid) {
 
    orderdetail orderdetail = orderservice.orderdetailservice(orderno, userid);
    resultvo resultvo = new resultvo<>();
    resultvo.setcode(100);
    resultvo.setmessage("请求成功");
    resultvo.setdata(orderdetail);
    return resultvo;
  }
}

2.2.3:订单服务调取其他服务

这里引入了resttemplate,它是一个spring封装的http映射请求工具类,然后通过http请求访问url = "http://192.168.80.153:8070/user/getuser"获取用户名,将值给订单对象。不过假如在这其中发生了调用异常,请求用户服务异常的话,那么返回给前端就是一串空的订单信息,导致用户看到的订单为空。在使用hystrix之后,可以用@hystrixcommand(fallbackmethod = "orderfallback")注解,在fallbackmethod中指定回退的方法,这里必须注意在@hystrixcommand上的方法其指定的回调方法必须和原方法的参数保持一致,这里包括参数类型、参数个数、参数顺序。我们在回调用法中模拟去查询缓存数据,返回给订单。有人又要问了,如果查询缓存服务器再异常呢?不排除这种可能性。如果是这样的话,依然可以使用@hystrixcommand注解在回调方法中,再指定其他的回调方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@service
public class orderservice {
  @autowired
  private resttemplate resttemplate;
  /**
   * 根据订单id获取订单详情
   *
   * @param orderid
   * @param userid
   * @return
   */
  @hystrixcommand(fallbackmethod = "orderfallback")
  public orderdetail orderdetailservice(long orderid, long userid) {
 
    if (objects.isnull(orderid)) {
      return null;
    }
 
    orderdetail orderdetail = orderdbsource.getorderdb().get(orderid);
    //调用user服务
    final string url = "http://192.168.80.153:8070/user/getuser";
    string username = "";
    responseentity<string> responseentity = resttemplate.postforentity(url, userid, string.class);
    string returncontent = responseentity.getbody();
    if (objects.nonnull(responseentity) && strutil.isnotempty(returncontent)) {
      username = returncontent;
    }
    if (objectutil.isnotnull(orderdetail)){
      orderdetail.setusername(username);
    }
    return orderdetail;
  }
  /**
   * 异常调用的回调方法
   *
   * @return
   */
  public orderdetail orderfallback(long orderid, long userid) {
    orderdetail orderdetail = orderdbsource.getordercache().get(orderid);
    final string unknown = "未知用户";
    orderdetail.setusername(unknown);
    return orderdetail;
  }
}

2.3.4:模拟测试

为了方便测试,首先我们将请求服务暂时先注释,然后用postman测试看正常的返回应该是这样的,这里使用了备注为数据库获取的订单,表明它没有走回调方法,因为这里没有访问用户url获取用户信息,程序可以正常访问。我再放开

springcloud使用Hystrix进行微服务降级管理

加上获取用户服务的链接,实际上用户服务是无法访问到的,访问的话就会超时,超时会被hystrix捕捉到,然后走fallback指定的方法,我们来测试一下,可以看到实际上走的是缓存中查询到的订单,可以看到用户服务已经成功的降级了,降级后的订单信息虽然是缓存获取到的,可能会存在延时等问题(当然只要维护好缓存就可以避免这个问题)。但是比没有任何数据带来的用户一点会更好!

springcloud使用Hystrix进行微服务降级管理

三:hystrix的流程

hystrix实际上的工作原理是这样的:通过command来解耦请求与返回操作,在具体的实例中就是,hystrix会对依赖的服务进行观察,通过command.toobservable调用返回一个观察的对象,同时发起一个事件,然后用subscriber对接受到的事件进行处理。在command命令发出请求后,它通过一系列的判断,顺序依次是缓存是否命中、断路器是否打开、线程池是否占满,然后它才会开始对我们编写的代码进行实际的请求依赖服务的处理,也就是hystrix.run方法,如果在这其中任一节点出现错误或者抛出异常,它都会返回到fallback方法进行服务降级处理,当降级处理完成之后,它会将结果返回给,际的调用者,经过一系列流程处理的,它的具体工作流程如下:

springcloud使用Hystrix进行微服务降级管理

四:总结

本篇博客讲述了hystrix是什么?然后解释了hystrix如何进行服务降级处理以及简单的处理流程,讲到的内容是最为常用的功能,还有一些关于hystrix的缓存、线程池的隔离技术等由于篇幅的原因,没有详细的讲解到,不过作为一篇入门级的hystrix教程博客是基本够的。在实际的开发中,如何保持服务的健壮性、服务的可用性、尽量的减少bug,提升用户体验都是我们开发者的使命,这条优化和提升之路永远没有尽头,go ahead!

参考资料《spring cloud微服务实战》

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

相关文章

热门资讯

2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总 2020-11-13
2021德云社封箱演出完整版 2021年德云社封箱演出在线看
2021德云社封箱演出完整版 2021年德云社封箱演出在线看 2021-03-15
返回顶部