新 Spring Cloud(四) 之 Fegin远程调用

零、前言

0. 之前写过两篇Spring Cloud,但是感觉不够具体,所以重新写了一份。

新 Spring Cloud (一) 之 Eureka 服务注册中心
新 SpringCloud (二) 之 Ribbon 负载均衡
新 Spring Cloud (三) 之 Hystrix熔断保护
新 Spring Cloud (四) 之 Fegin远程调用
新 Spring Cloud (五) 之 Zuul 网关

一、Fegin 简介

上回书说道,我们在项目中继承了Ribbon 实现了负载均衡,同时通过Hystrix 实现了熔断保护。看似完美,实则美中不足,在我们进行请求的时候,我们会写大量关于请求链接的地址。
如下 : 如果我们调用这个driver/takeOrder 100次,则我们需要重复写100次,如果我们需要调用其他的接口,则也要重复书写 restTemplate.postForObject("http://eureka-server-provider/xxxxx",multiValueMap,XXX.class); 这种类似的代码,麻烦且不说,而且易错。

String result = restTemplate.postForObject("http://eureka-server-provider/driver/takeOrder", multiValueMap, String.class);		// 麻烦易错!!!!!

所以我们在这里继承Fegin,可以改变这个现状。那么什么是Fegin呢?
Feign是Nettix开发的声明式、模板化的HTTP客户端,其灵感来自Retroft、JAXRS-2.0
以及WebSocket。Feign 可帮助我们更加便捷、优雅地调用HTTP API。在Spring Cloud中,使用Feign非常简单一创建一 个接口, 并在接口上添加一些注解,代码就完成了。Feign 支持多种注解,例如Feign自带的注解或者JAX-RS注解等。Spring Cloud对Feign进行了增强,使Feign支持了Spring MVC注解,并整合了Ribbon和Eureka,从而让Feign的使用更加方便。

简而言之:
• Feign 采用的是基于接口的注解
• Feign 整合了ribbon
• Feign可以把Rest的请求进行隐藏,伪装成类似SpringMVC的Controller一样

二、项目搭建

1. 基础使用

这里的操作都是对服务消费者来说(EurekaServerConsumer)

  1. 首先我们需要引入对应依赖

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
  2. 我们在启动类上加上 @EnableFeignClients 注解用于开启Fegin客户端。因为Fegin 内部自动集成了Ribbon负载均衡的RestTemplate,并且默认开启了负载均衡,所以我们不需要再注入RestTemplate。也不需要使用 @LoadBalanced 注解来开启负载均衡。

    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableFeignClients     // 开启 Fegin客户端
    public class EurekaServerConsumerApplication {
        public static void main(String[] args) {
            SpringApplication.run(EurekaServerConsumerApplication.class, args);
        }
    }
    
  3. 我们需要创建一个Fegin接口,来代理服务提供者的服务(EurekaServerProvider)。看似很高大上是吧,其实简单来说 Fegin就是对我们Ribbon的处理做了一个封装,让客户端实现了RPC调用。类似Dubbo中暴露远程服务的方式,区别在于Dubbo是基于私有二进制协议,而Feign本质上还是个HTTP客户端。

    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    
    /**
     * @Data: 2019/10/25
     * @Des:
     */
    @FeignClient(value = "eureka-server-provider") // 标注该类是一个feign接口,其服务名是 eurake-server-provider
    @RequestMapping("driver")
    public interface DriverClient {
        /**
         *  司机接单服务
         * @param msg
         * @return
         */
        @RequestMapping("takeOrder")
        String takeOrder(@RequestParam("msg") String msg);
    }
    
  • 首先这是一个接口,Feign会通过动态代理,帮我们生成实现类。这点跟mybatis的mapper很像
  • @FeignClient,声明这是一个Feign客户端,类似@Mapper注解。同时通过value属性指定服务名称
  • 接口中的定义方法,完全采用SpringMVC的注解,Feign会根据注解帮我们生成URL,并访问获取结果
  1. 改造原来接口的调用逻辑如下:

    
        @Autowired
        private DriverClient driverClient ;	// 注入Fegin接口
    
        @RequestMapping("callTaxi")
        public String callTaxi(String msg) {
            // 通过Fegin接口访问服务消费者的服务
            String result = driverClient.takeOrder(msg);
            System.out.println("乘客收到信息: " + result);
            return result;
        }
    
  2. 结束,调用可以,
    在这里插入图片描述

2. Fegin 负载均衡

Fegin内部集成了Ribbon,并默认开启了负载均衡,所以对于负载均衡我们并不需要做什么处理了。
对于负载均衡策略的配置,和集成 Ribbon 的配置相同,可以通过yml配置或者通过注入Bean配置。
如果不需要配置负载均衡策略,我们就不需要做任何事。

3. Fegin 集成 Hystrix

Fegin内部也集成了Hystrix。但是默认是不开启, 所以我们需要通过配置开启他。
以下:所有的配置都在服务消费者(EurekaServerConsumer)中

  1. 在yml文件中开启 hystrix 熔断功能
feign:
  hystrix:
    enabled: true   # 开启Fegin的熔断功能
  1. 我们在上一篇介绍Hystrix 的文章中将服务提供者的接口内容进行了修改,如下。改造之前的服务提供者服务(EurekaServerProvider),如下,不接待叫张三的人,目的是为了在伪造某种请求失败的状况来触发熔断。也就是说,这里如果请求参数是 张三,则请求失败,如果是其它,则请求成功。

    在这里插入图片描述

1. 通过Fallback来进行熔断
  1. 在DriverClient 熔断类的 @FeignClient 注解指定熔断类为 DriverClientFallBack。注意,@RequestMapping一定不要写在类上面,在方法上拼接,否则会出现异常,提示DriverClient 注入了多个实例(找了一下午才找到的原因)

    @FeignClient(value = "eureka-server-provider", fallback = DriverClientFallBack.class) // 标注该类是一个feign接口,其服务名是 eurake-server-provider,fallback 指定熔断类
    public interface DriverClient {
        /**
         *  司机接单服务
         * @param msg
         * @return
         */
        @RequestMapping("driver/takeOrder")
        String takeOrder(@RequestParam("msg") String msg);
    }
    
  2. DriverClientFallBack 类是一个实现了 DriverClient 接口的类,并注入Spring容器中,如下。当调用driver/takeOrder 出现异常时,会进入 takeOrder 该熔断方法内。

    @Component
    public class DriverClientFallBack implements DriverClient {
        @Override
        public String takeOrder(String msg) {
            return "DriverServiceFallBack  服务正忙,请稍后再试";
        }
    }
    
  3. 调用结果如下,张三会走到熔断方法,其余参数正常调用:
    在这里插入图片描述
    在这里插入图片描述

2. 通过FallbackFactory来进行熔断

通过FallbackFactory 可以进行熔断,但是我们没有办法看到是为什么熔断,如果想看到异常信息,可以使用Fallback的增强版 FallbackFactory。

  1. 创建一个 DriverClientFallBackFactory 类 继承 FallbackFactory 类,

    import feign.hystrix.FallbackFactory;
    import org.springframework.stereotype.Component;
    
    @Component
    public class DriverClientFallBackFactory implements FallbackFactory<DriverClient> {
    
        @Override
        public DriverClient create(Throwable throwable) {
            System.out.println("DriverServiceFallBackFactory     " + throwable.getMessage());
            return new DriverClient() {
                @Override
                public String takeOrder(String msg) {
                    return "DriverServiceFallBackFactory  服务正忙,请稍后再试";
                }
            };
        }
    }
    
  2. 修改DriverClient 方法,使用fallbackFactory 指定熔断工厂类:

    @FeignClient(value = "eureka-server-provider", fallbackFactory = DriverClientFallBackFactory.class) // 标注该类是一个feign接口,其服务名是 eurake-server-provider
    public interface DriverClient {
        /**
         *  司机接单服务
         * @param msg
         * @return
         */
        @RequestMapping("driver/takeOrder")
        String takeOrder(@RequestParam("msg") String msg);
    }
    
  3. 调用可以看到,错误信息。
    在这里插入图片描述

3. Hystrix局部配置

一个服务中肯定会有多个Fegin客户端,而有的服务需要服务降级,有的不需要,这时就不能仅仅通过yml的全局配置来决定了。
比如滴滴平台上有多位注册司机,有的司机说,我不愿意接离跑太远的乘客,那么我们可以给他配置Hystrix熔断,超过一定“距离“ 熔断,有的司机愿意接远距离乘客,那么我们就没必要给他配置熔断(例子不太合适,方便理解一下而已)。

首先我们先来看一下@FeignClient 注解参数的意义:

参数意义
name指定FeignClient的名称,如果项目使用了Ribbon,name属性会作为微服务的名称,用于服务发现
decode404当发生http 404错误时,如果该字段位true,会调用decoder进行解码,否则抛出FeignException
urlurl一般用于调试,可以手动指定@FeignClient调用的地址
configurationFeign配置类,可以自定义Feign的Encoder、Decoder、LogLevel、Contract
fallback定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口
fallbackFactory工厂类,用于生成fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码
path定义当前FeignClient的统一前缀
  1. 编写配置类

    @Configuration
    public class DriverConfiguration {
        /**
         *  配置日志级别
         *  - NONE:不记录任何日志信息,这是默认值。
         * - BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
         * - HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
         * - FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。
         * @return
         */
        @Bean
        Logger.Level feignLoggerLevel(){
            return Logger.Level.FULL;
        }
    
        /**
         * 配置不进行熔断
         * @return
         */
        @Bean
        public Feign.Builder feignBuilder() {
            return Feign.builder();
        }
    }
    
  2. 指定配置类对应的FeginClient
    在这里插入图片描述

  3. 再次访问,发现DriverClient已经关闭了Hystix 熔断。
    在这里插入图片描述
    以上:内容部分参考
    https://www.cnblogs.com/shmilyToHu/p/10725944.html
    https://blog.csdn.net/a15514920226/article/details/78924483
    如有侵扰,联系删除。 内容仅用于自我记录学习使用。如有错误,欢迎指正

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫吻鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值