1.5 基于Feign的远程服务调用



1.概述

1.1 背景分析

服务消费方基于rest方式请求服务提供方的服务时,一种直接的方式就是自己拼接url,拼接参数然后实现服务调用,但每次服务调用都需要这样拼接,代码量复杂且不易维护,此时Feign诞生。

1.2 Feign是什么

Feign 是一种声明式Web服务客户端,底层封装了对Rest技术的应用,通过Feign可以简化服务消费方对远程服务提供方法的调用实现。如图所示:
在这里插入图片描述

Feign 最早是由 Netflix 公司进行维护的,后来 Netflix 不再对其进行维护,最终 Feign 由一些社区进行维护,更名为 OpenFeign。

2.Feign应用实践(掌握)

2.1 Feign应用配置基础

第一步:在服务消费方,添加项目依赖(SpringCloud团队基于OpenFeign研发了starter),代码如下:

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

第二步:在启动类上添加@EnableFeignClients注解,代码如下:

@EnableFeignClients
@SpringBootApplication
public class ConsumerApplication {}

第三步:定义Http请求API,基于此API借助OpenFeign访问远端服务,代码如下:

package com.jt.consumer.service;
@FeignClient(name="sca-provider")//sca-provider为服务提供者名称
public interface RemoteProviderService{
    @GetMapping("/provider/echo/{msg}")//前提是远端需要有这个服务
    public String echoMessage(@PathVariable("msg") String msg);
}

其中,@FeignClient注解用于描述Feign远程服务调用接口,假设在项目配置类或启动类上添加了@EnableFeignClients注解,系统会在启动时,扫描@FeignClient注解,@FeignClient注解描述的接口底层会为其创建实现类(这个实现类我们称其为代理对象),此对象内部封装了对远程服务调用的过程。

@FeignClient注解中传入的name的值有俩层含义:
1. RemoteProviderService接口类型对象交给spring管理时,这个对象(bean)的名字
2. 远程调用的服务名

第四步:创建FeignConsumerController中并添加feign访问,代码如下:

package com.jt.consumer.controller;
@RestController
@RequestMapping("/consumer/ ")
public class FeignConsumerController {
    @Autowired
    private RemoteProviderService remoteProviderService;
    /**基于feign方式的服务调用*/
    @GetMapping("/echo/{msg}")
    public String doFeignEcho(@PathVariable  String msg){
        //基于feign方式进行远端服务调用(前提是服务必须存在)
        return remoteProviderService.echoMessage(msg);
    }
}

第五步:启动消费者服务,在浏览器中直接通过feign客户端进行访问,如图所示(反复刷新检测其响应结果):
在这里插入图片描述
说明,feign方式的远程服务调用,底层会自动基于ribbon组件实现负载均衡。

2.2 Feign配置进阶实践

一个服务提供方通常会提供很多资源服务,服务消费方基于同一个服务提供方写了很多服务调用接口,此时假如没有指定contextId服务,启动就会失败,例如,假如在服务消费方再添加一个如下接口,消费方启动时就会启动失败,例如:

 @FeignClient(name="sca-provider")
 public interface RemoteOtherService {
     @GetMapping("/doSomeThing")
     public String doSomeThing();
}

其启动异常如下:

The bean 'optimization-user.FeignClientSpecification', defined in null, could not be registered. A bean with that name has already been defined in null and overriding is disabled.

假如我们希望@FeignClient注解描述的接口对应的Bean名字不再是name属性的值,此时我们需要为远程调用服务接口指定一个contextId,作为远程调用服务的唯一标识(这个标识是Bean对象的名字)即可,例如:

@FeignClient(name="sca-provider",contextId="remoteProviderService")//sca-provider为服务提供者名称
interface RemoteProviderService{
    @GetMapping("/provider/echo/{string}")//前提是远端需要有这个服务
    public String echoMessage(@PathVariable("string") String string);
}

还有,当我们在进行远程服务调用时,假如调用的服务突然不可用了或者调用过程超时了,怎么办呢?我们可以在服务提供方对应的调用方法中添加Thread.sleep(5000)模拟耗时操作,然后启动服务进行访问测试.

在这里插入图片描述

在这里插入图片描述

一般服务消费端会给出具体的容错方案,例如,在Feign应用中通过FallbackFactory接口的实现类进行默认的相关处理,例如:

第一步:定义FallbackFactory接口的实现,代码如下:

package com.jt.consumer.service;

import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;

/**
 * 基于此对象处理RemoteProviderService接口调用时出现的服务中断,超时等问题
 */
@Component
public class ProviderFallbackFactory implements FallbackFactory<RemoteProviderService> {
    /**
     * 此方法会在RemoteProviderService接口服务调用时,出现了异常后执行.
     * @param throwable 用于接收异常
     */
    @Override
    public RemoteProviderService create(Throwable throwable) {
        return (msg)->{
            return "服务维护中,稍等片刻再访问";
        };
    }
}

第二步:在Feign访问接口中应用FallbackFactory对象,例如:

@FeignClient(name = "sca-provider", contextId = "remoteProviderService",
             fallbackFactory = ProviderFallbackFactory.class)//sca-provider为nacos中的服务名
public interface RemoteProviderService {
    @GetMapping("/provider/echo/{msg}")
    public String echoMsg(@PathVariable String msg);
}

第三步:在配置文件application.yml中添加如下配置,启动feign方式调用时的服务熔断处理机制.

feign:  
  hystrix:
    enabled: true #默认值为false

当然我们也可以设置默认超时时间,选择继续等待连接,而不是熔断:

feign:
  hystrix:
    enabled: false #默认值为false
  client:
    config:
      default:
        connect-timeout: 20000 #设置连接超时时间
        read-timeout: 20000 #设置读超时时间

最后我们访问页面测试当前设置是否生效:
在这里插入图片描述

2.3 Feign 调用过程分析(了解)

Feign应用过程分析(底层逻辑先了解):

  1. 通过 @EnableFeignCleints 注解告诉springcloud,启动 Feign Starter 组件;
  2. Feign Starter 会在项目启动过程中注册全局配置,扫描包下所由@FeignClient注解描述的接口,然后由系统底层创建接口实现类(JDK代理类),并构建类的对象,然后交给spring管理(注册 IOC 容器);
  3. Feign接口被调用时,底层代理对象会将接口中的请求信息通过编码器创建 Request对象,基于此对象进行远程过程调用;
  4. Feign客户端请求对象会经Ribbon进行负载均衡,挑选出一个健康的 Server 实例(instance);
  5. Feign客户端会携带 Request 调用远端服务并返回一个响应;
  6. Feign客户端对象对Response信息进行解析然后返回客户端;

3. 总结(Summary)

  1. 为什么使用Feign方式的服务调用?

    • 主要解决了代码结构的优化,简化了服务调用过程中代码的编写
  2. 如何基于Feign方式实现远程服务调用?

    • 需要添加openFeign的依赖,添加依赖后需要在启动类或配置了添加@EnableFeignCleints 注解,最后使用@FeignCleint 注解定义一个feign接口即可,其是声明式接口,所以只要声明接口即可,不用去实现定义的接口;
  3. @EnableFeignCleints 注解的作用是什么?

    • 描述配置类或启动类,告诉底层要启动Feign Start组件;
  4. @FeignCleint 注解的作用是什么?

    • 描述Feign接口,告诉Feign Start组件在项目启动时,为此注解描述的接口创建实现类;
  5. 如何理解基于Feign方式的远程服务调用?

    • Feign的远程调用为声明式远程服务调用,底层封装了服务调用过程
  6. Feign方式如何实现负载均衡?

    • Feign默认集成了ribbon组件,底层基于ribbon组件实现负载均衡
  7. Feign接口指向的对象是谁?

    • 实现了此接口的一个代理对象
  8. 我们常用的服务发现,服务调用方式有哪些?

    • 基于RestTemplate直接去调用远程服务
    • 基于LoadBalancerClient通过nacos获取服务列表,拿到服务列表后通过RestTemplate基于负载均衡算法进行服务的调用;
    • 使用@LoadBalanced注解去描述一个方法,通过此方法创建RestTemplate对象,进行远程服务的调用
    • 使用Feign方式进行远程服务的调用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值