springCloud学习-feign

@FeignClient标签

@FeignClient标签的常用属性如下:

name:指定FeignClient的名称,如果项目使用了Ribbon,name属性会作为微服务的名称,用于服务发现 url:
url一般用于调试,可以手动指定@FeignClient调用的地址 decode404:当发生http 404错误时,如果该字段位true,会调用decoder进行解码,否则抛出FeignException configuration:
Feign配置类,可以自定义Feign的Encoder、Decoder、LogLevel、Contract fallback:
定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口
fallbackFactory: 工厂类,用于生成fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码
path:定义当前FeignClient的统一前缀,当我们项目中配置了server.context-path,server.servlet-path时使用
contextId比如我们有个user服务,但user服务中有很多个接口,我们不想将所有的调用接口都定义在一个类中,就可以使用他

@EnableFeignClients标签

@EnableFeignClients注解用来启动FeignClient,以支持Feign。该注解可以通过配置,扫描指定位置的@FeignClient注解声明的Feign客户端接口。

常用属性如下:

basePackages属性字段去指明应用程序A在启动的时候需要扫描服务B中的标注了@FeignClient注解的接口的包路径
basePackageClasses属性是basePackages属性的安全替代属性。该属性将扫描指定的每个类所在的包下面的所有被@FeignClient修饰的类;这需要考虑在每个包中创建一个特殊的标记类或接口,该类或接口除了被该属性引用外,没有其他用途。
defaultConfiguration属性用来自定义所有Feign客户端的配置,使用@Configuration进行配置。当然也可以为某一个Feign客户端进行配置。具体配置方法见@FeignClient的configuration属性。
clients扫描所有被@FeignClient注解指定的客户端列表。如果clients不是空数组,则不通过类路径自动扫描功能来加载FeignClient。

定义与使用feign

引用

父项目引入

        <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
        </dependency>

子项目引入

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

使用@EnableFeignClients

@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
}

编写feign客户端

@FeignClient(name = "user-service")
public interface UserClient {
    /**
     * 路径: /user/110
     *
     * @param id 用户id
     * @return 用户
     */
    @GetMapping("/user/{id}")
    User queryById(@PathVariable("id") Long id);
}

配置与优化

feign相关配置

在这里插入图片描述

feign的日志级别

在这里插入图片描述

配置方式

方式一 代码配置

Feign配置类,可以添加在主类下,但是不用添加@Configuration。如果添加了@Configuration而且又放在了主类之下,那么就会所有Feign客户端实例共享,同Ribbon配置类一样父子上下文加载冲突;如果一定添加@Configuration,就放在主类加载之外的包。建议还是不用加@Configuration

/**
 * 配置
 * 
 * @Description
 * @Author weiwenbin
 * @Date 2022/8/24 下午4:10
 */
public class DefaultFeignClientConfiguration {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.BASIC;
    }
}
局部-代码配置

在指定的客户端中加入configuration

@FeignClient(name = "user-service", configuration = DefaultFeignClientConfiguration.class)

全局-代码配置

在启动类的中EnableFeignClients注解中加入defaultConfiguration,
@EnableFeignClients(defaultConfiguration = DefaultFeignClientConfiguration.class)

方式二 配置文件(属性)配置

局部-属性配置
feign:
  client:
    config:
      #想要调用的微服务名称
      user-server:
        loggerLevel: FULL
全局-属性配置
feign:
  client:
    config:
      #将调用的微服务名称改成default就配置成全局的了
      default:
        loggerLevel: FULL

配置相关优化

Feign底层的客户端实现:
URLConnection:默认实现,不支持连接池
Apache HttpClient:支持连接池
OKHttp:支持连接池

因此优化Feign的性能主要包括:
①、使用连接池代替默认的URLConnection
②、日志级别,最好用basic或none

HttpClient连接池配置

feign:
  httpClient:
    # 支持HttpClient的开关
    enabled: true
代码配置
package cn.itcast.order.config;

import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;

/**
 * 连接池配置
 *
 * @Description 连接池配置
 * @Author weiwenbin
 * @Date 2022/8/25 下午2:12
 */
@Configuration
public class HttpClientConfig {
    @Bean
    public HttpClient httpClient() {
        // 生成默认请求配置
        RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
        // 超时时间
        requestConfigBuilder.setSocketTimeout(5 * 1000);
        // 连接时间
        requestConfigBuilder.setConnectTimeout(5 * 1000);
        RequestConfig defaultRequestConfig = requestConfigBuilder.build();

        // 连接池配置
        // 长连接保持30秒
        final PoolingHttpClientConnectionManager pollingConnectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.MILLISECONDS);
        // 总连接数
        pollingConnectionManager.setMaxTotal(5000);
        // 同路由的并发数
        pollingConnectionManager.setDefaultMaxPerRoute(100);

        // httpclient 配置
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        // 保持长连接配置,需要在头添加Keep-Alive
        httpClientBuilder.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy());
        httpClientBuilder.setConnectionManager(pollingConnectionManager);
        httpClientBuilder.setDefaultRequestConfig(defaultRequestConfig);
        HttpClient client = httpClientBuilder.build();

        // 启动定时器,定时回收过期的连接
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                pollingConnectionManager.closeExpiredConnections();
                pollingConnectionManager.closeIdleConnections(5, TimeUnit.SECONDS);
            }
        }, 10 * 1000, 5 * 1000);
        System.out.println("===== Apache httpclient 初始化连接池===");

        return client;
    }
}

属性配置
feign:
  client:
    config:
      default:
       loggerLevel: BASIC
      user-service:
        loggerLevel: FULL
  httpClient:
    # 支持HttpClient的开关
    enabled: true
    # 最大连接数
    max-connections: 200
    # 单个路径的最大连接数
    max-connections-per-route: 50

其他配置

feign:
  compression:
    # 配置请求GZIP压缩
    request:
      enabled: true
    # 配置响应GZIP压缩
    response:
      enabled: true
  client:
    config:
      feignName:
        connectTimeout: 5000  # 相当于Request.Optionsn 连接超时时间
        readTimeout: 5000     # 相当于Request.Options 读取超时时间
        loggerLevel: full     # 配置Feign的日志级别,相当于代码配置方式中的Logger
        errorDecoder: com.example.SimpleErrorDecoder  # Feign的错误解码器,相当于代码配置方式中的ErrorDecoder
        retryer: com.example.SimpleRetryer  # 配置重试,相当于代码配置方式中的Retryer
        requestInterceptors: # 配置拦截器,相当于代码配置方式中的RequestInterceptor
          - com.example.FooRequestInterceptor
          - com.example.BarRequestInterceptor
        # 是否对404错误解码
        decode404: false
        encode: com.example.SimpleEncoder
        decoder: com.example.SimpleDecoder
        contract: com.example.SimpleContract

配置优先级

属性配置大于代码配置,细粒度配置大于全局配置
优先级:细粒度属性配置 > 细粒度代码配置 > 全局属性配置 > 全局代码配置
坑:同时进行全局代码配置、细粒度代码配置如图,两个配置都不生效,原因可参考 Feign配置了全局日志后局部日志失效
在这里插入图片描述
在这里插入图片描述
错误原因:注入了两个Logger.Level对象,feign在获取上下文的Level对象时,因为有两个不知道取哪个所以直接返回一个null,拿feign的默认值
在这里插入图片描述

最佳实践(直接从ppt中copy的 理解即可)

Feign的最佳实践
方式一(继承):给消费者的FeignClient和提供者的controller定义统一的父接口作为标准。(不推荐)
在这里插入图片描述

缺点:
①、服务紧耦合
②、父接口参数列表中的映射不会被继承

方式二(抽取):将FeignClient抽取为独立模块,并且把接口有关的POJO、默认的Feign配置都放到这个模块中,提供给所有消费者使用

在这里插入图片描述

在这里插入图片描述

参考博客
https://juejin.cn/post/6844903961737035790
https://juejin.cn/post/6844903590159450126
https://blog.csdn.net/CSDN877425287/article/details/125026118

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值