SpringCloud微服务架构-使用Hystrix实现微服务的容错机制

继续我们 SpringCloud 之旅,签名谈及到了 Eureka实现服务注册与发现,有使用 Ribbon 实现负责均衡,使用 Feign 实现声明式 API 调用,接下来我们的处理下容错问题了。

Hystrix 介绍

Hystrixs 是Netflix 实现的一个开源延迟和容错库,我们发现一个请求出现问题的时候,需要能够自动处理这个错误,避免错误的扩展,比如 A 服务依赖 B,B 又依赖 C,如果此时 C 发生错误,首先影响到 B,B 又影响到 A,这样的雪崩效应最终导致整个系统故障。

Hystrix 通过如下几点实现:

  • [x] 包裹请求
  • [x] 跳闸机制
  • [x] 资源隔离
  • [x] 监控
  • [x] 回退机制
  • [x] 自我修复

集成 Hystrix

首先在 movie 的 pom 里面增加依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
            <version>1.3.5.RELEASE</version>
        </dependency>

其次在启动类上增加@EnableCircuitBreaker和@EnableHystrix,为项目启用断路器支持

再次在 control 里面修改对应的方法,使得某个方法不能正常使用的时候,使用默认返回值。

    @GetMapping("/user/{id}")
    @HystrixCommand(fallbackMethod="findByUserIdFallback")
    public User findByUserId(@PathVariable Integer id){
        return restTemplate.getForObject("http://MS-SIMPLE-PROVIDER-USER/user/find?id="+id, User.class);
        //return userFeignClient.findById(id);
    }
    
    //这个方法是上面的方法发生错误的时候调用
    public User findByUserIdFallback(Integer id){
        User user=new User();
        user.setId(0);
        user.setName("NULL");
        user.setNickName("默认用户");
        user.setPassword("");
        user.setLastLoginDt(null);
        return user;
    }

在原先的方法上增加@HystrixCommand(fallbackMethod="findByUserIdFallback"),使得错误发生的时候能够调用下面的回调方法,回调方法参数与上面的一模一样。
@HystrixCommand该注解的里面参数非常多,需要的时候可以查阅文档,包括超时多久进行回调,线程池配置参数等。

以上是一个基本的演示配置,接下来我们先运行试试看,开启 eureka,开启 user,开启 movie,在浏览器浏览 http://localhost:8010/user/1 返回的就是 我们默认的用户信息,因为之前的user模块需要用户密码访问,我们这里面直接访问是不行的。


如果发现

com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect]: Factory method 'hystrixCommandAspect' threw exception; nested exception is java.lang.NoClassDefFoundError: org/aspectj/lang/JoinPoint

需要增加

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.6</version>
        </dependency>

Feign 使用 Hystrix

上面的例子没有使用 Feign 的,现在我们来用 Feign 使用 Hystrix。不废话,直接来干货吧。
因为 feign 是接口,我们需要在接口做一些动作。

首先使用之前的 FeignClient 接口方式来,对项目进行修正下,注释掉 movie 项目 Controller 的userUserFeignClient和adminUserFeignClient,以及相关的代码,然后修改映射方法为

    @GetMapping("/user/{id}")
//  @HystrixCommand(fallbackMethod="findByUserIdFallback")
    public User findByUserId(@PathVariable Integer id){
        //return restTemplate.getForObject("http://MS-SIMPLE-PROVIDER-USER/user/find?id="+id, User.class);
        return userFeignClient.findById(id);
    }

接下来在接口UserFeignClient 做如下修改

@FeignClient(name="MS-SIMPLE-PROVIDER-USER",fallback=UserFeignClientFallBack.class)
public interface UserFeignClient {

    @RequestMapping(value="/user/find?id={id}",method=RequestMethod.GET)
    public User findById(@PathVariable("id") Integer id);
    
}

这里需要一个UserFeignClientFallBack类实现了该接口

@Component
public class UserFeignClientFallBack implements UserFeignClient{

    
    @Override
    public User findById(Integer id) {
        User user=new User();
        user.setId(0);
        user.setName("NULL");
        user.setNickName("默认用户");
        user.setPassword("");
        user.setLastLoginDt(null);
        return user;
    }
}

这些操作完成后重启 movie,访问 http://localhost:8010/user/1
同样得到

使用回调工厂检查原因

改变不是太大,在接口的地方回调的是一个工厂类

package cn.ts.ms.movie.feign;

import org.springframework.stereotype.Component;

import cn.ts.ms.movie.model.User;
import feign.hystrix.FallbackFactory;

@Component
public class UserFeignClientFactory implements FallbackFactory<UserFeignClient> {

    @Override
    public UserFeignClient create(Throwable cause) {
        return new UserFeignClient(){
            @Override
            public User findById(Integer id) {
                
                //这里打印输出错误
                System.out.println(cause);
                
                User user=new User();
                user.setId(0);
                user.setName("NULL");
                user.setNickName("默认用户-Factory");
                user.setPassword("");
                user.setLastLoginDt(null);
                return user;
            }
        };
    }

}

修改接口出的 fallback 类@FeignClient(name="MS-SIMPLE-PROVIDER-USER",fallbackFactory=UserFeignClientFactory.class),注意是fallbackFactory

重启运行 movie,效果一样

全局禁用Hystrix
只须在application.yml中配置feign.hystrix.enabled=false即可。

Hystrix线程隔离策略与传播上下文

hystrix的隔离策略有两种:线程隔离和信号量隔离
线程隔离(THREAD):使用该方式,HystrixCommand将会在单独的线程上执行,并发请求受线程池中的线程数量的限制。
信号量隔离(SEMAPHORE):使用该方式,HystrixCommand将会在调用线程上执行,开销相对较小,并发请求受信号量个数的限制。

hystrix中默认并且推荐使用线程隔离,因为这种方式有一个除网络超时以外的额外保护层。

一般来说,只有当调用负载非常高时(如:每个实例每秒调用数百次)才需要使用信号量隔离,因为这种场景下使用线程隔离开销会比较大。信号量隔离一般仅适用于非网络调用的隔离。
可使用execution.isolation.strategy属性指定隔离策略。

使用 Hystrix Dashboard 来监控数据

首先引入依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
            <version>1.3.5.RELEASE</version>
        </dependency>

启动类增加注解 @EnableHystrixDashboard

重新启动 movie,浏览 http://localhost:8010/hystrix
出现


基本配置下进入

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,783评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,396评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,834评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,036评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,035评论 5 362
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,242评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,727评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,376评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,508评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,415评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,463评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,140评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,734评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,809评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,028评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,521评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,119评论 2 341

推荐阅读更多精彩内容