【三】Spring Cloud Feign+Hystrix 使用

一、Spring Cloud Feign + Hystrix使用

前面两篇已经讲过了直接HTTP调用,和用feign,用erueka注册中心做RPC调用。

这张加上Hystrix做熔断降级的使用方式。不整个项目截图了,就做在前面两张的基础之前需要做什么修改和注意什么。

首先是服务A调用服务B,那么实在服务A中加入Hystrix相关的东西

对应到demo就是在order订单系统里面加Hystrix,不需要在item商品系统做修改

依赖需要加入

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

applicatiom.yml需要加入

#开启hystrix断路器
feign:
  hystrix:
    enabled: true

 此次还能有其他的hystrix配置,这里没做介绍,只是用默认的,thread线程隔离

启动类需要加入

@EnableHystrix

@EnableEurekaClient
@EnableFeignClients
@EnableHystrix
@SpringBootApplication
public class OrderApp {
    public static void main(String[] args) {
        SpringApplication.run(OrderApp.class, args);
    }

    @Bean
    /**
     * 如果要使用ribbon负载需要加上@LoadBalanced
     * */
    @LoadBalanced
    public RestTemplate restTemplate() {

        /**
         * 向Spring容器中定义RestTemplate对象  这里就是表示用OKHTTP
         * @return
         */
        return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
    }

}

2.在服务中使用hystrix有三种方式

方法1

 1.新建一个Fallback类,继承feignclient类。

在这个类里面写的逻辑就是服务降级的时候执行的逻辑

package com.sid.rpc.fallback;

import com.sid.rpc.model.Item;
import com.sid.rpc.feignClient.ItemFeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * 此类中的方法专门用于服务降级,该类一般要实现调用远程服务的接口(这样保证方法名一致)
 */
@Component
public class ItemServiceFallback  implements ItemFeignClient {
    /**
     * 服务降级的方法要和原方法一致(名称、参数列表)
     * @param id
     * @return
     */
    @Override
    public Item queryItemById(@PathVariable("id") Long id) {
        return new Item(null, "服务降级方法queryItemById", null);
    }

}

2.在@FeignClient中指定fallback

@FeignClient(value = "app-item",fallback = ItemServiceFallback.class)

package com.sid.rpc.feignClient;

import com.sid.rpc.fallback.ItemServiceFallback;
import com.sid.rpc.model.Item;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@FeignClient(value = "app-item",fallback = ItemServiceFallback.class)
public interface ItemFeignClient {

    @RequestMapping(value = "/item/{id}", method = RequestMethod.GET)
    Item queryItemById(@PathVariable("id") Long id);

}

3.该方法的缺点

缺点: 无法得到throwable

RPC调用的throwable得不到

比如说,A调用B,B里面有个除以零的异常,A这边是不知道发生了啥,只知道调用服务B发生了服务降级,不知道是连接超时吗 B返回了异常吗 B报错了吗,A什么都不知道

Hystrix封装后的异常也得不到

方法2

 这里的代码例子是business服务调用storage服务

1.在RPC调用方法上加上注解

 @HystrixCommand(fallbackMethod = "deductFallbackMethod")

这就就指定了该方法的降级方法是哪个 

2.写这个降级方法deductFallbackMethod的逻辑

package com.sid.rpc.service;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.sid.rpc.feignClient.StorageFeignClient;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
public class StorageService {

    @Resource
    StorageFeignClient storageFeignClient;

    /**
     * 这里要注意一下,如果使用@HystrixCommand方式指定降级的方法,那么即使
     * feign:
     *   hystrix:
     *     enabled: false
     * RPC调用的时候也会使用Hystrix的线程池hystrix-StorageService-2,而不是http-nio-8085-exec-4
     * */
    @HystrixCommand(fallbackMethod = "deductFallbackMethod")
    public String deduct(String commodityCode, int count){
        return storageFeignClient.deduct(commodityCode,count);
    }

    /**
     * 请求失败执行的方法
     * fallbackMethod的方法参数个数类型要和原方法一致
     *
     * 这里看到的Throwable的异常,是Hystrix封装过的,比如HystrixTimeOutException,HystrixRunTimeException
     *      * 不会显示storage服务到底返回了什么内容
     *      * 且会显示
     * deductFallbackMethod throwable:com.netflix.hystrix.exception.HystrixRuntimeException: StorageFeignClient#deduct(String,int) failed and no fallback available.
     *
     * @param commodityCode
     * @param count
     * @return
     */
    public String deductFallbackMethod(String commodityCode, int count, Throwable throwable){
        System.out.println("deductFallbackMethod throwable:" + throwable.fillInStackTrace());
        return "StorageService.deduct fail 服务降级";
    }

}

3.缺点

缺点1.如果使用@HystrixCommand方式指定降级的方法,那么即使  feign.hystrix.enabled=false  RPC调用的时候也会使用Hystrix的线程池hystrix-StorageService-2,而不是http-nio-8085-exec-4

缺点2. 这里看到的Throwable的异常,是Hystrix封装过的,比如HystrixTimeOutException,HystrixRunTimeException

不会显示storage服务到底返回了什么内容

且会显示deductFallbackMethod throwable:com.netflix.hystrix.exception.HystrixRuntimeException: StorageFeignClient#deduct(String,int) failed and no fallback available.

方法3

这个例子是order服务调用Account服务

1.新建一个类实现FallbackFactory接口

package com.sid.rpc.fallback;

import com.sid.rpc.feignClient.AccountFeignClient;
import feign.hystrix.FallbackFactory;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class AccountServiceFallback implements FallbackFactory<AccountFeignClient> {
    private static final Logger logger = LoggerFactory.getLogger(AccountServiceFallback.class);

    @Override
    public AccountFeignClient create(Throwable throwable) {
        String msg = throwable == null ? "" : throwable.getMessage();

        /**
         * 这里就能看到account的debit方法被调用里面抛出了除以0的异常
         *
         * 2021-03-19 10:53:12.016 ERROR[hystrix-app-account-2]com.sid.rpc.fallback.AccountServiceFallback.create:39 -AccountServiceFallback 中有方法降级,throwable.getMessage():status 500 reading AccountFeignClient#debit(String,Double); content:
         * {"timestamp":"2021-03-19T02:53:12.008+0000","status":500,"error":"Internal Server Error","message":"/ by zero","path":"/account/debit"}
         * */
        if (!StringUtils.isEmpty(msg)) {
            logger.error("AccountServiceFallback 中有方法降级,throwable.getMessage():" + msg);
        }
        return new AccountFeignClient() {
            @Override
            public String debit(String userId, Double money) {
                return "AccountService.debit fail 服务降级";
            }
        };
    }
}

2.在@FeignClient中加入fallbackFactory = AccountServiceFallback.class,指定降级方法的实现类

package com.sid.rpc.feignClient;

import com.sid.config.FeignConfiguration;
import com.sid.rpc.fallback.AccountServiceFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;


@FeignClient(value = "app-account",configuration = FeignConfiguration.class,fallbackFactory = AccountServiceFallback.class)
public interface AccountFeignClient {

    @RequestMapping(value = "/account/debit", method = RequestMethod.POST)
    String debit(@RequestParam("userId") String userId,@RequestParam("money") Double money);

}

3.优点

这里就能看到account的debit方法被调用里面抛出了除以0的异常

2021-03-19 10:53:12.016 ERROR[hystrix-app-account-2]com.sid.rpc.fallback.AccountServiceFallback.create:39 -AccountServiceFallback 中有方法降级,throwable.getMessage():status 500 reading

AccountFeignClient#debit(String,Double); content: * {"timestamp":"2021-03-19T02:53:12.008+0000","status":500,"error":"Internal Server Error","message":"/ by zero","path":"/account/debit"} 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值