王富贵

Stay hungry,Stay foolish

若你自认理性且正确,那更应该心平气和,言之有据地与人交流,即使不能立刻说服对方,但也至少埋下了一颗种子,冷嘲热讽或居高临下的态度,总会加大人与人之间的隔阂,最终只是在自己的小圈子中制造回声。愿我们最终都能成为乐观且包容的人,愿意耐心听取他人的苦衷和心声。
  menu
69 文章
0 浏览
1 当前访客
ღゝ◡╹)ノ❤️

微服务03-OpenFeign声明式客户端

1、OpenFeign声明式客户端

Feign是Netfix开发的声明式http客户端,由于他闭源了,所以spring官方开发了OpenFeign对Feign进行了一个增强,使他支持Spring MVC的注解

1.1、OpenFeign客户端是什么

OpenFeign是一个Web声明式的Http客户端调用工具,提供接口和注解形式调用

OpenFeign是一个声明式RESTful网络请求客户端。OpenFeign会根据带有注解的函数信息构建出网络请求的模板,在发送网络请求之前,OpenFeign会将函数的参数值设置到这些请求模板中。虽然OpenFeign只能支持基于文本的网络请求,但是它可以极大简化网络请求的实现,方便编程人员快速构建自己的网络请求应用

如图所示,使用OpenFeign的Spring应用架构一般分为三个部分,分别为服务注册中心、服务提供者和服务消费者。服务提供者向服务注册中心注册自己,然后服务消费者通过OpenFeign发送请求时,OpenFeign会向服务注册中心获取关于服务提供者的信息,然后再向服务提供者发送网络请求

openFeign的位置在服务消费者方

6

那么这和我们之前学的ribbon有什么区别呢?

ribbon调用可以看见我们是使用链接的方式拿数据,并且还需要指定数据的接收类型,这极其不符合我们单体时候拿对象的面向对象思维,如下代码

@GetMapping("/hello")
public String hello(){
    String forObject = restTemplate.getForObject("http://provider/hello/", String.class);
    return "我是消费者拿生产者:"+forObject;
}

我们想实现的是以下效果:调用本地方法一样的体验

@GetMapping("/hello")
public String hello(){
    String forObject = providerService.getHello();//这里替代上面写死链接的方式,看着像本地方法
    return "我是消费者拿生产者:"+forObject;
}

事实上,Feign就是实现了这一功能,他封装了我们的调用,让我们通过接口的方式来调用数据,而不是写链接

同时,我们知道现在都是使用rest风格的调用,他是通过json来传输数据的,实现类似于post,get,delete,update的请求风格,原来的restTemplate就比较麻烦了

1.2、简单使用OpenFeign

1.引入依赖

<!-- 整合OpenFeign -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2.编写feign包

我们到这里封装工具类,类似于服务提供方的controller层

/**
 * name = 服务名,也就是生产者名称
 * path = 指定调用rest接口所在的controller指定的@RequestMapping,其实就是路径,这里我们没有,就不写了
 */
@FeignClient(name ="provider")
public interface ProviderFeignService {
    //也就是说,在这里我们rest的接收,和服务提供方接口一致
    @GetMapping("hello")
    String hello();

    //如果我们需要使用到路径数据,也与springMVC一致
//    @PostMapping("/meg/{id}")
//    String get(@PathVariable Integer id);
}

3.主类添加注解@EnableFeignClients

我们可以指定扫描包,扫描到feign的包@EnableFeignClients("com.hy.feign")

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ConsumerWithOpenFeign {

    public static void main(String[] args) {

        SpringApplication.run(ConsumerWithOpenFeign.class, args);

    }
}

4.测试调用

我们直接拿到ProviderFeignService进行面向对象方式的调用即可

@RestController
public class HelloController {

    @Autowired
    ProviderFeignService providerFeignService;

    @GetMapping("/hello")
    public String hello(){
        String forObject = providerFeignService.hello();
        return "我是消费者拿生产者:"+forObject;
    }
}

5.如果报错类找不到

重新清理编译文件,重新编译

15

1.3、Feign的负载均衡

我们知道负载均衡通常使用ribbon,那么ribbon即可以通过配置类并在主类配置扫描来负载均衡,也可以修改yaml文件进行负载均衡。OpenFeign是默认继承ribbon的,所以不需要做额外的配置。

1.4、OpenFeign日志配置

Feign提供了很多扩展机制,让用户可以更加灵活的使用

1.4.1.日志配置

有时候我们遇到bug,比如接口调用失败,参数没收到等问题,或者想看看调用性能,就需要配置feign的日志了,以此让Feign把请求信息输出出来

那么我们有四个日志级别

  1. NONE【性能最佳,适用于生产】:不纪录任何日志(默认值)
  2. BASIC【适用于生产环境的追踪问题】:纪录请求方法,URL,响应状态码以及执行时间
  3. HEADERS:BASIC的基础上,纪录请求和响应的header
  4. FULL【比较适用于开发及测试环境定位问题】:路基请求和响应的header,body和原数据

1.4.1.1.配置类配置

1.定义一个配置类,指定日志级别

//如果我们添加配置类注解,那就是全局配置,所有feign客户端都会使用这么一个配置
@Configuration
public class FeignConfig {
    @Bean
    public Logger.Level FeignLoggerLevel() {
        return Logger.Level.FULL;
    }
}

2.非全局配置

如果我们不想全局配置,而是定义某个feign客户端的日志配置

第一个,我们不能在配置类中添加@Configuration注入

并且,我们在@FeignClient上面添加配置

// configuration = 配置类的class文件
@FeignClient(name ="provider",configuration = FeignConfig.class)
public interface ProviderFeignService {
    //也就是说,在这里我们rest的接收,和服务提供方接口一致
    @GetMapping("hello")
    String hello();

    //如果我们需要使用到路径数据,也与springMVC一致
//    @PostMapping("/meg/{id}")
//    String get(@PathVariable("id") Integer id);
}

3.配置开启文件日志

# 开启日志
logging:
  level:
    # 打印日志的全类名
    com.hy.feign.ProviderfeignService: debug

4.注意

我们必须在使用@PathVariable的时候指定映射属性的名称

@FeignClient(name ="provider",configuration = FeignConfig.class)
public interface ProviderFeignService {

    //@PathVariable("id")必须指定名称
    @PostMapping("/meg/{id}")
    String get(@PathVariable("id") Integer id);
}

1.4.1.2.配置类配置

feign:
  client:
    config:
      provider: # 服务提供者名称
        loggerLevel: BASIC

1.5、Feign契约配置

Spring Cloud在Feign的基础上做了拓展,使用Spring MVC的注解来完成Feign的功能。原生的Feign是不支持Spring MVC的功能的,如果你想在Spring Cloud中使用原生的注解方式来定义客户端也是可以的,通过配置契约来改变这个配置,Spring Cloud默认的是SpringMVCContract

为什么我用MVC注解就行还要使用这个契约配置呢?因为Spring Cloud1.0版本是使用的Feign原生注解,如果你想升级并且不想修改到MVC的代码,那么你就可以这样做

1.修改契约配置,支持Feign原生注解

@Configuration
public class FeignConfig {
    /**
     * 修改契约配置,支持feign原生注解
     * @return
     */
    @Bean
    public Contract feignContract() {
        return new Contract.Default();
    }
}

注意:如果使用契约配置,那么将不再支持Spring MVC的注解了

2.原生注解简单使用

Feign契约注解

// 对比mvc 
// @FeignClient(name ="provider",configuration = FeignConfig.class)
@FeignClient(value = "provider",path ="/provider")
public interface ProviderFeignService {
    //对比mvc
    //@PostMapping("/meg/{id}")
    //String get(@PathVariable("id") Integer id);
  
    @@RequestLine("GET /meg/{id}")
    String get(@Param("id") Integer id);
}

3.yaml配置也可以

feign:
  client:
    config:
      # 提供方的服务名
      product-service:
        #请求日志级别
        loggerLevel: BASIC
        contract: feign.Contract.Default #设置为默认的契约(还原成原生注解)

1.6、超时时间配置

通过Options可以配置连接超时时间和读取超时时间,Options的第一个参数是连接超时时间(ms),默认值是2s,第二个请求参数是请求处理超时时间(ms),默认值是5s

1.全局配置

@Configuration
public class FeignConfig {
    @Bean
    public Request.Options options() {
        //五秒连接超时,十秒处理超时
        return new Request.Options(5000,10000);
    }
}

2.yaml配置

老样子,yaml可以精细化对于具体的服务提供者进行配置

feign:
  client:
    config:
      provider: # 服务提供者名
        # 连接超时时间,默认2s
        connectTimeout: 5000
        # 请求处理超时,默认5s
        readTimeout: 10000

注意:Feign的底层用的是ribbon,但超时时间一Feign为准

1.7、自定义拦截器

我们服务消费方调用服务提供方的时候,可以使用我们的拦截器。比如调用的时候记录一些日志,携带token等等。

注意要和我们的前后端分离开来,在微服务项目中一般是使用网关来做前后端交互的校验

1.自定义拦截器,实现RequestInterceptor

public class FeignAuthRequestInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        // 业务逻辑
        String s = UUID.randomUUID().toString();
        requestTemplate.header("Authorization",s);
    }
}

2.在Feign中配置拦截器

@Configuration
public class FeignHandlerConfig {
    @Bean
    public FeignAuthRequestInterceptor feignAuthRequestInterceptor() {
        return new FeignAuthRequestInterceptor();
    }
}

标题:微服务03-OpenFeign声明式客户端
作者:1938857445
地址:https://www.lmlx66.top/articles/2022/04/25/1650861270057.html