在微服务架构体系中,各服务中间的相互调用是常态,没有哪个服务能保证自身百分百不会出问题,然后再加上网络的波动以及环境等问题,服务间调用的稳定性无法保证,这时候就需要一个有容错能力的组件来介入,当调用出现问题时能够做出及时响应,确保用户的体验和服务本身不受影响;而hystrix就是这样一个具备容错能力的组件,可以通过hystrix来实现服务的熔断、降级和隔离等功能, 从而提升服务的可用性与容错性 ;下面先简单介绍下熔断、降级和隔离;

        熔断

当服务调用出现问题时实现快速失败的一种手段,避免占用服务器资源造成宕机甚至雪崩的风险;

        降级

        当服务不可用时给客户端友好响应的一种处理手段,具体可根据实际业务需求角度来考虑降低的具体方案;

隔离

当请求量激增时为了保护整个微服务不被搞垮可以使用服务内的服务隔离来解决;hystrix的隔离策略分为信号量隔离和线程池隔离两种方式,默认使用的是线程池隔离;

信号量隔离维护的是web容器(如tomcat)的线程,不需要服务内部开启线程,更轻量;由于使用的是web容器的请求线程,导致其不支持异步调用,不能单独为其设置超时机制;而线程池隔离是由hystrix自己维护的线程进行远程调用,可以做成异步调用,但其又新增了线程的开销和维护;所以当服务属于io密集型时可以选择线程池隔离策略,而当服务更多的是执行本地计算等cpu密集型时可考虑使用信号量隔离;当请求达到信号量或是线程池设置的线程数的上限时,请求会被直接拒绝,等到信号量有余量或者线程池有空闲了再接纳请求,这样即使微服务中的某一请求出现异常了也不至于导致整个服务异常;

下面上源码来看看hystrix该如何配置上述功能

首先引入依赖:

     <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>
spring-cloud-starter-netflix-hystrix
</artifactId>
</dependency>

hystrix整合restTemplate

  启动类添加@EnableCircuitBreaker注解,然后再需要做熔断的方法上添加@HystrixCommand注解并指定熔断后处理的方法即可,代码如下:

package com.darling.eureka.consumer.service.impl;

import com.darling.eureka.consumer.service.TestRestTemplateService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate; import javax.annotation.Resource;
import java.net.URI; /**
* @description:
* @author: dll
* @date: Created in 2021/9/23 11:21
* @version:
* @modified By:
*/
@Service
public class TestRestTemplateServiceImpl implements TestRestTemplateService { @Resource
private RestTemplate restTemplate; @Override
@HystrixCommand(fallbackMethod = "sayRestHiCallBack")
public String sayRestHi(String name) {
String url = "http://EUREKA-PROVIDER//serverApis/test/sayHi?name="+name;
String object = restTemplate.getForObject(url, String.class);
return object;
} /**
* 当sayRestHi方法发起远程调用失败时调用本方法
* @param name
* @return
*/
public String sayRestHiCallBack(String name) {
return "向"+name+"sayRestHi失败啦!";
}
}

hystrix整合Feign

        由于feign本身支持hystrix,所以只需在配置文件打开hystrix的开关即可:feign.hystrix.enabled=true;有两种整合方式,一种是回调普通类另一种是回调一个工厂类,具体配置如下:

  回调普通类:

  在@FeignClient注解上新增属性fallback,值为指定的处理熔断方法的类,该类需实现@FeignClient注解所在的service;配置代码如下:

package com.darling.eureka.consumer.service;

import com.darling.api.service.UserService;
import com.darling.eureka.consumer.model.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*; /**
* @description: 通过openFeign远程调用服务提供者
* @author: dll
* @date: Created in 2021/9/14 12:29
* @version: 1.0
* @modified By:
*/
@FeignClient(name = "EUREKA-PROVIDER",fallback = UserClientFallback.class)
public interface UserApiService extends UserService{ @GetMapping("/serverApis/test/sayHi?name={name}")
String sayHi(@PathVariable String name); /**
* 测试 插入一条信息
* @param user
* @return
*/
@GetMapping("/serverApis/test/insertInfo")
String insertInfo(@RequestBody User user); }

  处理熔断方法的类代码如下:

package com.darling.eureka.consumer.service;

import com.darling.api.model.UserInfo;
import com.darling.eureka.consumer.model.User;
import org.springframework.stereotype.Component; /**
* @description: 基于htstrix封装的处理feign调用出错的熔断策略
* @author: dll
* @date: Created in 2021/9/22 12:08
* @version:
* @modified By:
*/
@Component
public class UserClientFallback implements UserApiService { @Override
public String sayHi(String name) {
return "我被降级了。。。";
} @Override
public String insertInfo(User user) {
return null;
} @Override
public UserInfo test() {
return null;
} @Override
public UserInfo getInfo() {
UserInfo userInfo = new UserInfo();
userInfo.setServerPort("我被降级啦");
return userInfo;
}
}

  回调工厂类:

  在@FeignClient注解上新增属性fallbackFactory,值为指定的处理熔断方法的工厂类,该类需实现FallbackFactory;配置代码如下:

package com.darling.eureka.consumer.service;

import com.darling.api.service.UserService;
import com.darling.eureka.consumer.model.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*; /**
* @description: 通过openFeign远程调用服务提供者
* @author: dll
* @date: Created in 2021/9/14 12:29
* @version: 1.0
* @modified By:
*/
@FeignClient(name = "EUREKA-PROVIDER",fallbackFactory = UserClientFallbackFactory.class)
public interface UserApiService extends UserService{ @GetMapping("/serverApis/test/sayHi?name={name}")
String sayHi(@PathVariable String name); /**
* 测试 插入一条信息
* @param user
* @return
*/
@GetMapping("/serverApis/test/insertInfo")
String insertInfo(@RequestBody User user); }

工厂类代码如下:

package com.darling.eureka.consumer.service;

import com.darling.api.model.UserInfo;
import com.darling.eureka.consumer.model.User;
import com.netflix.hystrix.exception.HystrixTimeoutException;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component; import java.util.Objects; /**
* @description: 基于htstrix封装的处理feign调用出错的熔断策略工厂
* @author: dll
* @date: Created in 2021/9/22 13:06
* @version:
* @modified By:
*/
@Component
public class UserClientFallbackFactory implements FallbackFactory<UserApiService> { @Override
public UserApiService create(Throwable throwable) { return new UserApiService() {
@Override
public String sayHi(String name) {
System.out.println("throwable = " + throwable);
if (throwable instanceof HystrixTimeoutException) {
return "连接超时了";
}
return "系统异常";
} @Override
public String insertInfo(User user) {
return null;
} @Override
public UserInfo test() {
return null;
} @Override
public UserInfo getInfo() {
UserInfo userInfo = new UserInfo();
userInfo.setServerPort("我被降级啦");
return userInfo;
}
};
}
}

  两种回调方法总结:

使用普通类回调无法定位具体错误,通过工厂类回调由于参数会传入一个Throwable对象,调用者可以根据不同的错误类型做不同的降级策略,个人认为会更友好;

 

springcloud组件梳理之hystrix的更多相关文章

  1. springcloud组件梳理之Feign

    最近刚好打算做一个springcloud系列的分享,趁此机会刚好梳理下springcloud常用组件的使用,今天先对feign做个简单介绍! feign是一个声明式的Web服务客户端,它使得发送web ...

  2. SpringCloud组件及功能介绍

    1.什么是SpringClould?    SpringCloud是一个基于SpringBoot实现的微服务架构开发工具.它为微服务架构中涉及的配置管理.服务治理.断路器.智能路由.微代理.控制总线. ...

  3. 微服务介绍和springCloud组件

      微服务架构模式是:将整个web服务 组织成一系列小的web 服务,这些小的web服务可以进行独立的编译和部署,并通过各自暴露的API接口 进行相互通信,他们相互协作,作为一个整体,为客户提供服务功 ...

  4. Tomcat组件梳理—Service组件

    Tomcat组件梳理-Service组件 1.组件定义 Tomcat中只有一个Server,一个Server可以用多个Service,一个Service可以有多个Connector和一个Contain ...

  5. Tomcat组件梳理—Digester的使用

    Tomcat组件梳理-Digester的使用 再吐槽一下,本来以为可以不用再开一个篇章来梳理Digester了,但是发现在研究Service的创建时,还是对Digester的很多接口或者机制不熟悉,简 ...

  6. Tomcat组件梳理--Server

    Tomcat组件梳理--Server 1.Server组件的定义和功能概述 定义: Server组件用于描述一个启动的Tomcat实例,一个Tocmat被启动,在操作系统中占用一个进程号,提供web服 ...

  7. Tomcat组件梳理--Catalina

    Tomcat组件梳理--Catalina 1.定义和功能 Catalina是Tomcat的核心组件,是Servlet容器,Catalina包含了所有的容器组件,其他模块均为Catalina提供支撑.通 ...

  8. 1.Tomcat组件梳理—Bootstrap启动器

    Tomcat组件梳理-Bootstrap启动器 一开始是直接从Server开始做梳理的,但是发现有很多东西是从Catalina传输过来的,Catalina又是从Bootstrap启动的,所以还是回过头 ...

  9. ④SpringCloud 实战:引入Hystrix组件,分布式系统容错

    这是SpringCloud实战系列中第4篇文章,了解前面第两篇文章更有助于更好理解本文内容: ①SpringCloud 实战:引入Eureka组件,完善服务治理 ②SpringCloud 实战:引入F ...

随机推荐

  1. String vs StringBuffer vs StringBuilder

    String vs StringBuffer vs StringBuilder 本文翻译自:https://www.digitalocean.com/community/tutorials/strin ...

  2. K8S中部署apisix(非ingress)

    不使用pvc的方式在K8S中部署apisix-gateway 简介 因为公司项目准备重构,现在做技术储备,之前公司项目使用的ocelot做网关,ocelot是.net平台下的一个网关,也是很不错,但是 ...

  3. 「SHOI2014」概率充电器

    题面 n <= 500000   0<= p,qi <= 100 题解 这是道概率树形DP题,但是很难推怎么用加法原理和乘法原理正向求每个点被充电的概率,所以我们求每个点不被充电的概 ...

  4. RabbitMQ 入门系列:9、扩展内容:死信队列:真不适合当延时队列。

    系列目录 RabbitMQ 入门系列:1.MQ的应用场景的选择与RabbitMQ安装. RabbitMQ 入门系列:2.基础含义:链接.通道.队列.交换机. RabbitMQ 入门系列:3.基础含义: ...

  5. E - Road Reduction

    E - Road Reduction (atcoder.jp) 题意:一棵树n个点,m条路, di表示1-i的距离,问怎么选择边可以使得d2+...dn最短. 题解: 很明显,就是直接套最短路板子,判 ...

  6. 第五十六篇:webpack的loader(四) -打包js中的高级语法

    好家伙, 1.打包处理js文件中的高级语法 webpack只能打包处理一部分高级的JavaScript 语法.对于那些webpack无法处理的高级js 语法,需要借 助于 babel-loader 进 ...

  7. mydodo协议

    mydodo协议 目录 数据帧结构 命令 协议 代码样例 数据帧结构 帧头1 帧头2 设备号 命令 数据长度 数据 0x4D 0x59 xxx cmd nByte data 例子:设备my01 的继电 ...

  8. Gitea v1.17.0 正式发布 | 集成软件包管理器、容器镜像仓库

    我们自豪地宣布 Gitea v1.17.0 发布了.本次发布带来了诸多新特性和累积的更新,我们强烈建议用户在更新到最新版本之前仔细阅读发行注记. 在 1.17.0 版本的开发中我们一共合并了 645 ...

  9. 第一行代码Android(第3版).pdf下载

    2020年人民邮电出版社出版的图书 <第一行代码Android(第3版)>是2020年4月人民邮电出版社出版的图书,作者是郭霖. 封面: 内容简介: <第一行代码 Android 第 ...

  10. 基于koa模块和socket.io模块搭建的node服务器实现通过jwt 验证来渲染列表、私聊、群聊功能

    1. 具体代码在需要的下载 https://gitee.com/zyqwasd/socket 效果: 2. package.json文件 1. 下载基本的模块  修改了start 脚本  nodemo ...