【Spring Cloud 微服务教程】 Spring Cloud Feign 基本使用

2020/05/18

Spring Cloud Feign 基本使用

概述

Feign是一个声明式的REST客户端,它能让REST调用更加简单。Feign提供了HTTP请求的模板,通过编写简单的接口和插入注解,就可以定义好HTTP请求的参数、格式、地址等信息。

而Feign则会完全代理HTTP请求,我们只需要像调用方法一样调用它就可以完成服务请求及相关处理。Spring Cloud对Feign进行了封装,使其支持 SpringMVC 标准注解和 HttpMessageConverters。

服务端

创建应用

创建一个命名为: spring-cloud-feign-server-example 的 Spring cloud 应用。

    <dependencies>
        <!-- nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

配置

在 application.yml中配置

server:
  port: 8080
spring:
  application:
    name: feign-server
  cloud:
    nacos:
      server-addr: 127.0.0.1:8848

控制类实现

@RestController
@RequestMapping("/feign")
public class FeignServerController {

    @GetMapping("/say/{name}")
    public String sayHello(@PathVariable("name") String name){
        return name + " say hello";
    }
}

客户端

创建应用

创建一个命名为: spring-cloud-feign-basic-example 的 Spring cloud 应用。

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

    </dependencies>
   

配置

在 application.yml中配置

server:
  port: 8081
spring:
  application:
    name: feign-basic
  cloud:
    nacos:
      server-addr: 127.0.0.1:8848

启动类

@SpringBootApplication
@EnableFeignClients
public class SpringCloudFeignBasicExampleApplication {

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

}

  • @EnableFeignClients: 启用feign客户端

Feign 接口配置

@FeignClient(name="feign-server",path = "feign")
public interface FeignServerClient {
    /**
     * 请求服务端接口 http://feign-server/feign/say/{name}
     * @param name
     * @return
     */
    @GetMapping("/say/{name}")
    String sayHello(@PathVariable("name") String name);
}

  • @FeignClient: name指微服务名称,path请求的统一路径前缀。

控制类

@RestController
@RequestMapping("/basic")
public class BasicController {

    @Autowired
    private FeignServerClient feignServerClient;

    @GetMapping("/say/{name}")
    public String sayHello(@PathVariable("name") String name){
        return feignServerClient.sayHello(name);
    }
}

启动程序

分别服务端和客户端,访问客户端 http://localhost:8081/basic/say/mtcarpenter,返回结果如下:

mtcarpenter say hello

Feign的组成

接口 作用 默认值
Feign.Builder Feign的入口 Feign.Builder
Client Feign底层用什么去请求 和Ribbon配合时:LoadBalancerFeignClient 不和Ribbon配合时:Fgien.Client.Default
Contract 契约,注解支持 SpringMVCContract
Encoder 解码器,用于将对象转换成HTTP请求消息体 SpringEncoder
Decoder 编码器,将响应消息体转成对象 ResponseEntityDecoder
Logger 日志管理器 Slf4jLogger
RequestInterceptor 用于为每个请求添加通用逻辑 无

Feign的日记级别

日志级别 打印内容
NONE(默认) 不记录任何日志
BASIC 仅记录请求方法,URL,响应状态代码以及执行时间
HEADERS 记录BASIC级别的基础上,记录请求和响应的header (生产)
FULL 记录请求和响应的header、body 和元数据

Feign 日志级别代码实现

日志级别

//如果使用添加了 @Configuration  需要将此配置类移到启动类之外的包(避免@ComponentScan) 避免父子上下文重复扫描
public class FeignServerConfig {

    @Bean
    public Logger.Level logger(){
        // 请求的详细信息
        return Logger.Level.FULL;
    }
}

@FeignClient 配置

@FeignClient(name="feign-server",path = "feign",configuration = FeignServerConfig.class)

application.yml 配置

logging:
  level:
    com.mtcarpenter.spring.cloud.feign.basic.example.feign.FeignServerClient: debug

debug 级别以下配置才会生效

Feign 日志级别属性配置

logging:
  level:
    com.mtcarpenter.spring.cloud.feign.basic.example.feign.FeignServerClient: debug
# feign 日志级别属性配置
feign:
  client:
    config:
      # 微服务实例名称
      feign-server:
        loggerLevel: FULL

Feign 日志级别全局属性配置

logging:
  level:
    com.mtcarpenter.spring.cloud.feign.basic.example.feign.FeignServerClient: debug
# feign 日志级别属性配置
feign:
  client:
    config:
      # 全局配置
      default:
        loggerLevel: FULL

Feign支持的配置项

代码方式

配置项 作用
Logger.Level 指定日志级别
Retryer 指定重试策略
ErrorDecoder 指定错误解码器
Request.Options 超时时间
Collection 拦截器
SetterFactory 用于设置Hystrix的配置属性,Fgien整合Hystrix才会用

配置属性

feign:
  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

Ribbon配置 VS Feign配置

粒度 Ribbon Feign
代码局部 X @RibbonClient(configuration=X.class),RibbonConfig类必须加@Configuration,且必须放在父上下文无法扫到的包下 @FeignClient(configuration=X.class),FeignConfig类的@Configuration可以X不加(可选),如果有,必须放在父上下文无法扫到的包下
代码全局 @RibbonClients(defaultConfigurtion) @EnableFeignClients(defaultConfiguration )
配置属性局部 .ribbon.NFLoadBalancerClassName ... feign.client.config..loggerLevel ...
配置属性全局 无 feign.client.config.default.loggerLevel

Feign 代码方式 VS 配置属性方式

配置方式 有点 缺点
代码配置 基于代码,更加灵活 如果Feign的配置类加了@Configuration注解,需注意父子上下文,线上修改需要重打包,发布
属性配置 易上手 配置更加直观 线上修改无需重新打包,发布 优先级更高 极端场景下没有代码配置更加灵活

优先级:细粒度属性配置 > 细粒度代码配置 > 全局属性配置 > 全局代码配置

Fegin 请求具体地址

@FeignClient(name = "url-client",url = "https://blog.lixc.top/spring-cloud.html")
public interface FeignUrlClient {

    /**
     * 地址请求
     * @return
     */
    @GetMapping("")
    String cloud();
}

  • url: 请求的具体地址

性能优化

引入依赖

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

**使用 okhttp **

# feign 日志级别属性配置
feign:
  client:
    config:
      # 微服务实例名称
      feign-server:
        loggerLevel: FULL
  # 启用 okhttp 关闭默认 httpclient
  httpclient:
    enabled: false #关闭httpclient
    # 配置连接池
    max-connections: 200 #feign的最大连接数
    max-connections-per-route: 50 #fegin单个路径的最大连接数
  okhttp:
    enabled: true
  # 请求与响应的压缩以提高通信效率
  compression:
    request:
      enabled: true
      min-request-size: 2048
      mime-types: text/xml,application/xml,application/json
    response:
      enabled: true

参数配置

@Configuration
@ConditionalOnClass(Feign.class)
@AutoConfigureBefore(FeignAutoConfiguration.class) //SpringBoot自动配置
public class OkHttpConfig {

    /**
     * 中文乱码
     * @return
     */
    @Bean
    public Encoder encoder() {
        return new FormEncoder();
    }

    /**
     * 配置 okhttp 与连接池
     * ConnectionPool 默认创建5个线程,保持5分钟长连接
     */
    @Bean
    public okhttp3.OkHttpClient okHttpClient() {
        return new okhttp3.OkHttpClient.Builder()
                //设置连接超时
                .connectTimeout(10, TimeUnit.SECONDS)
                //设置读超时
                .readTimeout(10, TimeUnit.SECONDS)
                //设置写超时
                .writeTimeout(10, TimeUnit.SECONDS)
                //是否自动重连
                .retryOnConnectionFailure(true)
                .connectionPool(new ConnectionPool(10, 5L, TimeUnit.MINUTES))
                .build();
    }
}

文章参考

  • https://cloud.spring.io/spring-cloud-openfeign/2.1.x/single/spring-cloud-openfeign.html

代码示例

本文示例代码访问下面查看仓库:

其中,本文示例代码名称:

  • spring-cloud-feign-server-example: Spring Cloud Feign 服务端
  • spring-cloud-feign-basic-example: Spring Cloud Feign 客户端


微信扫描二维码,关注一个有故事的程序员

(转载本站文章请注明作者和出处 山间木匠-mtcarpenter)

Post Directory

扫码关注公众号:山间木匠
发送 290992
即可立即永久解锁本站全部文章