Spring Cloud ( openFeign 服务发现配置公共client抽取 )

Posted 白日日白

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Cloud ( openFeign 服务发现配置公共client抽取 )相关的知识,希望对你有一定的参考价值。

本章目录:

  • openFeign的引出
  • 快速入门
    • 引入依赖
    • 添加@EnableFeignClients注解
    • 编写FeignClient接口
    • 使用FeignClient中定义的方法代替RestTemplate
  • 日志配置
  • 连接池配置
  • 公共client抽取

一、openFeign的引出

先来看我们之前服务通信使用的方法:

我们调用RestTemplate的getObject并手写url来完成服务调用,这样做的缺点是:

  • 代码可读性差,编程体验不统一
  • 参数复杂URL难以维护

目前我们只有一个参数(UserID),日后参数复杂了,难道我们要拼接一个一长串的请求路径吗?

Feign可以帮我们轻松解决上述问题:

Feign是一个声明式的http客户端

官方地址:https://github.com/OpenFeign/feign

其作用就是帮助我们优雅的实现http请求的发送,解决上面提到的问题。

使用feign后和我们平常的接口调用没什么区别,代码优雅简介。


二、快速入门

2.1、引入依赖

在服务消费者的pom文件内引入feign依赖

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

2.2、 添加@EnableFeignClients注解

在springBoot启动类上添加依赖

2.3、 编写FeignClient接口

新建一个client包,编写UserClient类

@FeignClient("userService")
public interface UserClient 

    @GetMapping("/user/id")
    User findById(@PathVariable("id") Long id);

如下图,feignClient其实就是将硬编码的请求方式替换为了我们熟知的Rest风格的请求

2.4、使用FeignClient中定义的方法代替RestTemplate

 把UserClient注入到service层,消费服务。


三、日志配置

feign共有四个日志级别:

日志级别打印内容
NONE(默认)不记录任何日志
FULL记录请求和响应的header、body和元数据。
HEADER记录基本信息以及请求和响应标头。
BASIC只记录请求方法和URL以及响应状态代码和执行时间。

feign日志有两种配置方式:

  • 配置Logger.Level这个Bean
  • yml文件配置

3.1、使用yml配置日志

feign:
  client:
    # 配置
    config:
      #default为全局配置,如需对指定服务记录日志,换成服务名即可
      default:
        # 控制日志Level,默认:null即NONE
        # NONE 没有日志
        # BASIC 只记录请求方法和URL以及响应状态码和执行时间
        # HEADERS 记录基本信息以及请求和响应头
        # FULL 记录请求和响应的头、正文和元数据
        loggerLevel: FULL

这里要注意的是:

feign日志记录只响应debug级别,所以我们要对Feign客户端(client)的接口的完整类名指定日志级别为:DEBUG

yml配置如下:

3.2、使用Logger.Level配置日志

新建一个config包,编写如下代码:

package cn.itcast.order.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;

public class FeignConfig 
    @Bean
    public Logger.Level feignLogLevel()
        return Logger.Level.FULL;
    

如果是全局配置,则把它放到@EnableFeignClients这个注解中

如果是对特定服务开启日志记录,则把它放到@FeignClient这个注解中

比如我要对userService服务开启日志

总结如下:

Feign的日志配置:

方式一:配置文件(feign.client.config.xxx.loggerLevel)

  • 如果xxx是default则代表全局
  • 如果xxx是服务名称,例如userservice则代表某服务

方式二:java代码配置Logger.Level这个Bean

  • 如果在@EnableFeignClients注解声明则代表全局
  • 如果在@FeignClient注解中声明则代表某服务 

四、连接池配置

Feign底层的客户端实现:

  • URLConnection:默认实现,
  • 不支持连接池 Apache HttpClient 
  • 支持连接池 OKHttp:支持连接池

feign默认使用URLConnection,是没有连接池的

我们都了解过线程池、数据库连接池等;它的好处是避免了频繁的创建连接和销毁的步骤。首先我们知道HTTP连接需要经过三次握手,四次挥手的过程,这是很耗费性能的

 而如果我们直接采用 http 连接池,节约了大量的 3 次握手 4 次分手;这样能大大提升吞吐率

 以下是具体实现:

4.1引入httpClient依赖

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

4.2、配置连接池

feign:
  httpclient:
    enabled: true                   #开启feign对HttpClient的支持
    max-connections: 200            #最大的连接数
    max-connections-per-route: 50   #单个路径的最大连接数
    onnections-per-route: 50        #单个路径的最大连接数

 五、公共client抽取

上述案例,当一个服务消费者 消费 一个服务提供者,我们需要编写服务提供者的client,client内接口返回的服务提供者的实体类对象,feign配置等等信息。

那么如果这个服务提供者 被多个服务消费者 消费,难道我们要在多个服务消费者内都编写服务提供者的client吗?显然这是不合理的

对于这种情况,我们可以抽取一个moudle,专门编写服务提供者的client,pojo,config等信息。

当某个消费者服务需要使用client,只需要在pom.xml内引入该moudle依赖,然后@Autowired对应client即可。

抽取一个feign-api

比如orderService需要使用UserClient

在orderService的pom.xml内引入feign-api

接着更改启动类@EnableFeignClients注解内的内容

然后把调用client的service层里导入的包都更改为被抽取模块(feign-api)的包

现在我们使用的userClient属于feign-api,不在当前的服务中了,我们需要在当前服务重新指定日志级别

这一步很重要,否则日志不会生效 

总结:

  • 首先创建一个module,命名为feign-api,
  • 然后引入feign的starter依赖
  • 将order-service中编写的UserClient、User、DefaultFeignConfiguration都复制到feign-api项目中 在order-service中引入feign-api的依赖
  • 修改order-service中的所有与上述三个组件有关的import部分,改成导入feign-api中的包
  • 重启测试

以上是关于Spring Cloud ( openFeign 服务发现配置公共client抽取 )的主要内容,如果未能解决你的问题,请参考以下文章

Spring Cloud实战OpenFeign服务接口调用

spring cloud openFeign传参的一些总结(有错,待更新)

springcloud openFeign 请求超时问题解决

Spring-Cloud系列-Openfeign源码解析

Spring-Cloud系列-Openfeign源码解析

启用 Spring-Cloud-OpenFeign 配置可刷新,项目无法启动,我 TM 人傻了(上)